xref: /reactos/dll/win32/riched20/string.c (revision 64527aa9)
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