1c2c66affSColin Finck /*
2c2c66affSColin Finck * RichEdit - string operations
3c2c66affSColin Finck *
4c2c66affSColin Finck * Copyright 2004 by Krzysztof Foltman
5c2c66affSColin Finck *
6c2c66affSColin Finck * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck * License as published by the Free Software Foundation; either
9c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck *
11c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14c2c66affSColin Finck * Lesser General Public License for more details.
15c2c66affSColin Finck *
16c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck */
20c2c66affSColin Finck
21c2c66affSColin Finck #include "editor.h"
22c2c66affSColin Finck
23c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(richedit);
24c2c66affSColin Finck
ME_GetOptimalBuffer(int nLen)25c2c66affSColin Finck static int ME_GetOptimalBuffer(int nLen)
26c2c66affSColin Finck {
27c2c66affSColin Finck return ((sizeof(WCHAR) * nLen) + 128) & ~63;
28c2c66affSColin Finck }
29c2c66affSColin Finck
make_string(void (* free)(ME_String *))30c2c66affSColin Finck static ME_String *make_string( void (*free)(ME_String *) )
31c2c66affSColin Finck {
32c2c66affSColin Finck ME_String *s = heap_alloc( sizeof(*s) );
33c2c66affSColin Finck
34c2c66affSColin Finck if (s) s->free = free;
35c2c66affSColin Finck return s;
36c2c66affSColin Finck }
37c2c66affSColin Finck
38c2c66affSColin Finck /* Create a ME_String using the const string provided.
39c2c66affSColin Finck * str must exist for the lifetime of the returned ME_String.
40c2c66affSColin Finck */
ME_MakeStringConst(const WCHAR * str,int len)41c2c66affSColin Finck ME_String *ME_MakeStringConst(const WCHAR *str, int len)
42c2c66affSColin Finck {
43c2c66affSColin Finck ME_String *s = make_string( NULL );
44c2c66affSColin Finck if (!s) return NULL;
45c2c66affSColin Finck
46c2c66affSColin Finck s->szData = (WCHAR *)str;
47c2c66affSColin Finck s->nLen = len;
48c2c66affSColin Finck s->nBuffer = 0;
49c2c66affSColin Finck return s;
50c2c66affSColin Finck }
51c2c66affSColin Finck
heap_string_free(ME_String * s)52c2c66affSColin Finck static void heap_string_free(ME_String *s)
53c2c66affSColin Finck {
54c2c66affSColin Finck heap_free( s->szData );
55c2c66affSColin Finck }
56c2c66affSColin Finck
57c2c66affSColin Finck /* Create a buffer (uninitialized string) of size nMaxChars */
ME_MakeStringEmpty(int nMaxChars)58c2c66affSColin Finck ME_String *ME_MakeStringEmpty(int nMaxChars)
59c2c66affSColin Finck {
60c2c66affSColin Finck ME_String *s = make_string( heap_string_free );
61c2c66affSColin Finck
62c2c66affSColin Finck if (!s) return NULL;
63c2c66affSColin Finck s->nLen = nMaxChars;
64c2c66affSColin Finck s->nBuffer = ME_GetOptimalBuffer(s->nLen + 1);
65c2c66affSColin Finck s->szData = heap_alloc( s->nBuffer * sizeof(WCHAR) );
66c2c66affSColin Finck if (!s->szData)
67c2c66affSColin Finck {
68c2c66affSColin Finck heap_free( s );
69c2c66affSColin Finck return NULL;
70c2c66affSColin Finck }
71c2c66affSColin Finck s->szData[s->nLen] = 0;
72c2c66affSColin Finck return s;
73c2c66affSColin Finck }
74c2c66affSColin Finck
ME_MakeStringN(LPCWSTR szText,int nMaxChars)75c2c66affSColin Finck ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars)
76c2c66affSColin Finck {
77c2c66affSColin Finck ME_String *s = ME_MakeStringEmpty(nMaxChars);
78c2c66affSColin Finck
79c2c66affSColin Finck if (!s) return NULL;
80c2c66affSColin Finck memcpy(s->szData, szText, s->nLen * sizeof(WCHAR));
81c2c66affSColin Finck return s;
82c2c66affSColin Finck }
83c2c66affSColin Finck
84c2c66affSColin Finck /* Make a string by repeating a char nMaxChars times */
ME_MakeStringR(WCHAR cRepeat,int nMaxChars)85c2c66affSColin Finck ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars)
86c2c66affSColin Finck {
87c2c66affSColin Finck int i;
88c2c66affSColin Finck ME_String *s = ME_MakeStringEmpty(nMaxChars);
89c2c66affSColin Finck
90c2c66affSColin Finck if (!s) return NULL;
91c2c66affSColin Finck for (i = 0; i < nMaxChars; i++)
92c2c66affSColin Finck s->szData[i] = cRepeat;
93c2c66affSColin Finck return s;
94c2c66affSColin Finck }
95c2c66affSColin Finck
ME_DestroyString(ME_String * s)96c2c66affSColin Finck void ME_DestroyString(ME_String *s)
97c2c66affSColin Finck {
98c2c66affSColin Finck if (!s) return;
99c2c66affSColin Finck if (s->free) s->free( s );
100c2c66affSColin Finck heap_free( s );
101c2c66affSColin Finck }
102c2c66affSColin Finck
ME_InsertString(ME_String * s,int ofs,const WCHAR * insert,int len)103c2c66affSColin Finck BOOL ME_InsertString(ME_String *s, int ofs, const WCHAR *insert, int len)
104c2c66affSColin Finck {
105c2c66affSColin Finck DWORD new_len = s->nLen + len + 1;
106c2c66affSColin Finck WCHAR *new;
107c2c66affSColin Finck
108c2c66affSColin Finck assert( s->nBuffer ); /* Not a const string */
109c2c66affSColin Finck assert( ofs <= s->nLen );
110c2c66affSColin Finck
111c2c66affSColin Finck if( new_len > s->nBuffer )
112c2c66affSColin Finck {
113c2c66affSColin Finck s->nBuffer = ME_GetOptimalBuffer( new_len );
114c2c66affSColin Finck new = heap_realloc( s->szData, s->nBuffer * sizeof(WCHAR) );
115c2c66affSColin Finck if (!new) return FALSE;
116c2c66affSColin Finck s->szData = new;
117c2c66affSColin Finck }
118c2c66affSColin Finck
119c2c66affSColin Finck memmove( s->szData + ofs + len, s->szData + ofs, (s->nLen - ofs + 1) * sizeof(WCHAR) );
120c2c66affSColin Finck memcpy( s->szData + ofs, insert, len * sizeof(WCHAR) );
121c2c66affSColin Finck s->nLen += len;
122c2c66affSColin Finck
123c2c66affSColin Finck return TRUE;
124c2c66affSColin Finck }
125c2c66affSColin Finck
ME_AppendString(ME_String * s,const WCHAR * append,int len)126c2c66affSColin Finck BOOL ME_AppendString(ME_String *s, const WCHAR *append, int len)
127c2c66affSColin Finck {
128c2c66affSColin Finck return ME_InsertString( s, s->nLen, append, len );
129c2c66affSColin Finck }
130c2c66affSColin Finck
ME_VSplitString(ME_String * orig,int charidx)131c2c66affSColin Finck ME_String *ME_VSplitString(ME_String *orig, int charidx)
132c2c66affSColin Finck {
133c2c66affSColin Finck ME_String *s;
134c2c66affSColin Finck
135c2c66affSColin Finck assert(orig->nBuffer); /* Not a const string */
136c2c66affSColin Finck assert(charidx>=0);
137c2c66affSColin Finck assert(charidx<=orig->nLen);
138c2c66affSColin Finck
139c2c66affSColin Finck s = ME_MakeStringN(orig->szData+charidx, orig->nLen-charidx);
140c2c66affSColin Finck if (!s) return NULL;
141c2c66affSColin Finck
142c2c66affSColin Finck orig->nLen = charidx;
143c2c66affSColin Finck orig->szData[charidx] = '\0';
144c2c66affSColin Finck return s;
145c2c66affSColin Finck }
146c2c66affSColin Finck
ME_StrDeleteV(ME_String * s,int nVChar,int nChars)147c2c66affSColin Finck void ME_StrDeleteV(ME_String *s, int nVChar, int nChars)
148c2c66affSColin Finck {
149c2c66affSColin Finck int end_ofs = nVChar + nChars;
150c2c66affSColin Finck
151c2c66affSColin Finck assert(s->nBuffer); /* Not a const string */
152c2c66affSColin Finck assert(nChars >= 0);
153c2c66affSColin Finck assert(nVChar >= 0);
154c2c66affSColin Finck assert(end_ofs <= s->nLen);
155c2c66affSColin Finck
156c2c66affSColin Finck memmove(s->szData + nVChar, s->szData + end_ofs,
157c2c66affSColin Finck (s->nLen - end_ofs + 1) * sizeof(WCHAR));
158c2c66affSColin Finck s->nLen -= nChars;
159c2c66affSColin Finck }
160c2c66affSColin Finck
161c2c66affSColin Finck static int
ME_WordBreakProc(LPWSTR s,INT start,INT len,INT code)162c2c66affSColin Finck ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code)
163c2c66affSColin Finck {
164*64527aa9SKatayama Hirofumi MZ #ifndef __REACTOS__
165c2c66affSColin Finck /* FIXME: Native also knows about punctuation */
166*64527aa9SKatayama Hirofumi MZ #endif
167c2c66affSColin Finck TRACE("s==%s, start==%d, len==%d, code==%d\n",
168c2c66affSColin Finck debugstr_wn(s, len), start, len, code);
169c2c66affSColin Finck
170c2c66affSColin Finck switch (code)
171c2c66affSColin Finck {
172c2c66affSColin Finck case WB_ISDELIMITER:
173c2c66affSColin Finck return ME_IsWSpace(s[start]);
174c2c66affSColin Finck case WB_LEFT:
175c2c66affSColin Finck case WB_MOVEWORDLEFT:
176c2c66affSColin Finck while (start && ME_IsWSpace(s[start - 1]))
177c2c66affSColin Finck start--;
178*64527aa9SKatayama Hirofumi MZ #ifdef __REACTOS__
179*64527aa9SKatayama Hirofumi MZ while (start && !ME_IsWSpace(s[start - 1]) && !iswpunct(s[start - 1]))
180*64527aa9SKatayama Hirofumi MZ start--;
181*64527aa9SKatayama Hirofumi MZ #else
182c2c66affSColin Finck while (start && !ME_IsWSpace(s[start - 1]))
183c2c66affSColin Finck start--;
184*64527aa9SKatayama Hirofumi MZ #endif
185c2c66affSColin Finck return start;
186c2c66affSColin Finck case WB_RIGHT:
187c2c66affSColin Finck case WB_MOVEWORDRIGHT:
188*64527aa9SKatayama Hirofumi MZ #ifdef __REACTOS__
189*64527aa9SKatayama Hirofumi MZ while (start < len && !ME_IsWSpace(s[start]) && !iswpunct(s[start]))
190*64527aa9SKatayama Hirofumi MZ start++;
191*64527aa9SKatayama Hirofumi MZ #else
192c2c66affSColin Finck while (start < len && !ME_IsWSpace(s[start]))
193c2c66affSColin Finck start++;
194*64527aa9SKatayama Hirofumi MZ #endif
195c2c66affSColin Finck while (start < len && ME_IsWSpace(s[start]))
196c2c66affSColin Finck start++;
197c2c66affSColin Finck return start;
198c2c66affSColin Finck }
199c2c66affSColin Finck return 0;
200c2c66affSColin Finck }
201c2c66affSColin Finck
202c2c66affSColin Finck
203c2c66affSColin Finck int
ME_CallWordBreakProc(ME_TextEditor * editor,WCHAR * str,INT len,INT start,INT code)204c2c66affSColin Finck ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start, INT code)
205c2c66affSColin Finck {
206c2c66affSColin Finck if (!editor->pfnWordBreak) {
207c2c66affSColin Finck return ME_WordBreakProc(str, start, len, code);
208c2c66affSColin Finck } else if (!editor->bEmulateVersion10) {
209c2c66affSColin Finck /* MSDN lied about the third parameter for EditWordBreakProc being the number
210c2c66affSColin Finck * of characters, it is actually the number of bytes of the string. */
211c2c66affSColin Finck return editor->pfnWordBreak(str, start, len * sizeof(WCHAR), code);
212c2c66affSColin Finck } else {
213c2c66affSColin Finck int result;
214c2c66affSColin Finck int buffer_size = WideCharToMultiByte(CP_ACP, 0, str, len,
215c2c66affSColin Finck NULL, 0, NULL, NULL);
216c2c66affSColin Finck char *buffer = heap_alloc(buffer_size);
217c2c66affSColin Finck if (!buffer) return 0;
218c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, str, len,
219c2c66affSColin Finck buffer, buffer_size, NULL, NULL);
220c2c66affSColin Finck result = editor->pfnWordBreak((WCHAR*)buffer, start, buffer_size, code);
221c2c66affSColin Finck heap_free(buffer);
222c2c66affSColin Finck return result;
223c2c66affSColin Finck }
224c2c66affSColin Finck }
225c2c66affSColin Finck
ME_ToUnicode(LONG codepage,LPVOID psz,INT * len)226c2c66affSColin Finck LPWSTR ME_ToUnicode(LONG codepage, LPVOID psz, INT *len)
227c2c66affSColin Finck {
228c2c66affSColin Finck *len = 0;
229c2c66affSColin Finck if (!psz) return NULL;
230c2c66affSColin Finck
231c2c66affSColin Finck if (codepage == CP_UNICODE)
232c2c66affSColin Finck {
233c2c66affSColin Finck *len = lstrlenW(psz);
234c2c66affSColin Finck return psz;
235c2c66affSColin Finck }
236c2c66affSColin Finck else {
237c2c66affSColin Finck WCHAR *tmp;
238c2c66affSColin Finck int nChars = MultiByteToWideChar(codepage, 0, psz, -1, NULL, 0);
239c2c66affSColin Finck
240c2c66affSColin Finck if(!nChars) return NULL;
241c2c66affSColin Finck
242c2c66affSColin Finck if((tmp = heap_alloc( nChars * sizeof(WCHAR) )) != NULL)
243c2c66affSColin Finck *len = MultiByteToWideChar(codepage, 0, psz, -1, tmp, nChars) - 1;
244c2c66affSColin Finck return tmp;
245c2c66affSColin Finck }
246c2c66affSColin Finck }
247c2c66affSColin Finck
ME_EndToUnicode(LONG codepage,LPVOID psz)248c2c66affSColin Finck void ME_EndToUnicode(LONG codepage, LPVOID psz)
249c2c66affSColin Finck {
250c2c66affSColin Finck if (codepage != CP_UNICODE)
251c2c66affSColin Finck heap_free( psz );
252c2c66affSColin Finck }
253