2 * RichEdit - string operations
4 * Copyright 2004 by Krzysztof Foltman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 WINE_DEFAULT_DEBUG_CHANNEL(richedit
);
25 static int ME_GetOptimalBuffer(int nLen
)
27 return ((sizeof(WCHAR
) * nLen
) + 128) & ~63;
30 static ME_String
*make_string( void (*free
)(ME_String
*) )
32 ME_String
*s
= heap_alloc( sizeof(*s
) );
34 if (s
) s
->free
= free
;
38 /* Create a ME_String using the const string provided.
39 * str must exist for the lifetime of the returned ME_String.
41 ME_String
*ME_MakeStringConst(const WCHAR
*str
, int len
)
43 ME_String
*s
= make_string( NULL
);
46 s
->szData
= (WCHAR
*)str
;
52 static void heap_string_free(ME_String
*s
)
54 heap_free( s
->szData
);
57 /* Create a buffer (uninitialized string) of size nMaxChars */
58 ME_String
*ME_MakeStringEmpty(int nMaxChars
)
60 ME_String
*s
= make_string( heap_string_free
);
64 s
->nBuffer
= ME_GetOptimalBuffer(s
->nLen
+ 1);
65 s
->szData
= heap_alloc( s
->nBuffer
* sizeof(WCHAR
) );
71 s
->szData
[s
->nLen
] = 0;
75 ME_String
*ME_MakeStringN(LPCWSTR szText
, int nMaxChars
)
77 ME_String
*s
= ME_MakeStringEmpty(nMaxChars
);
80 memcpy(s
->szData
, szText
, s
->nLen
* sizeof(WCHAR
));
84 /* Make a string by repeating a char nMaxChars times */
85 ME_String
*ME_MakeStringR(WCHAR cRepeat
, int nMaxChars
)
88 ME_String
*s
= ME_MakeStringEmpty(nMaxChars
);
91 for (i
= 0; i
< nMaxChars
; i
++)
92 s
->szData
[i
] = cRepeat
;
96 void ME_DestroyString(ME_String
*s
)
99 if (s
->free
) s
->free( s
);
103 BOOL
ME_InsertString(ME_String
*s
, int ofs
, const WCHAR
*insert
, int len
)
105 DWORD new_len
= s
->nLen
+ len
+ 1;
108 assert( s
->nBuffer
); /* Not a const string */
109 assert( ofs
<= s
->nLen
);
111 if( new_len
> s
->nBuffer
)
113 s
->nBuffer
= ME_GetOptimalBuffer( new_len
);
114 new = heap_realloc( s
->szData
, s
->nBuffer
* sizeof(WCHAR
) );
115 if (!new) return FALSE
;
119 memmove( s
->szData
+ ofs
+ len
, s
->szData
+ ofs
, (s
->nLen
- ofs
+ 1) * sizeof(WCHAR
) );
120 memcpy( s
->szData
+ ofs
, insert
, len
* sizeof(WCHAR
) );
126 BOOL
ME_AppendString(ME_String
*s
, const WCHAR
*append
, int len
)
128 return ME_InsertString( s
, s
->nLen
, append
, len
);
131 ME_String
*ME_VSplitString(ME_String
*orig
, int charidx
)
135 assert(orig
->nBuffer
); /* Not a const string */
137 assert(charidx
<=orig
->nLen
);
139 s
= ME_MakeStringN(orig
->szData
+charidx
, orig
->nLen
-charidx
);
142 orig
->nLen
= charidx
;
143 orig
->szData
[charidx
] = '\0';
147 void ME_StrDeleteV(ME_String
*s
, int nVChar
, int nChars
)
149 int end_ofs
= nVChar
+ nChars
;
151 assert(s
->nBuffer
); /* Not a const string */
154 assert(end_ofs
<= s
->nLen
);
156 memmove(s
->szData
+ nVChar
, s
->szData
+ end_ofs
,
157 (s
->nLen
- end_ofs
+ 1) * sizeof(WCHAR
));
162 ME_WordBreakProc(LPWSTR s
, INT start
, INT len
, INT code
)
164 /* FIXME: Native also knows about punctuation */
165 TRACE("s==%s, start==%d, len==%d, code==%d\n",
166 debugstr_wn(s
, len
), start
, len
, code
);
171 return ME_IsWSpace(s
[start
]);
173 case WB_MOVEWORDLEFT
:
174 while (start
&& ME_IsWSpace(s
[start
- 1]))
176 while (start
&& !ME_IsWSpace(s
[start
- 1]))
180 case WB_MOVEWORDRIGHT
:
181 while (start
< len
&& !ME_IsWSpace(s
[start
]))
183 while (start
< len
&& ME_IsWSpace(s
[start
]))
192 ME_CallWordBreakProc(ME_TextEditor
*editor
, WCHAR
*str
, INT len
, INT start
, INT code
)
194 if (!editor
->pfnWordBreak
) {
195 return ME_WordBreakProc(str
, start
, len
, code
);
196 } else if (!editor
->bEmulateVersion10
) {
197 /* MSDN lied about the third parameter for EditWordBreakProc being the number
198 * of characters, it is actually the number of bytes of the string. */
199 return editor
->pfnWordBreak(str
, start
, len
* sizeof(WCHAR
), code
);
202 int buffer_size
= WideCharToMultiByte(CP_ACP
, 0, str
, len
,
203 NULL
, 0, NULL
, NULL
);
204 char *buffer
= heap_alloc(buffer_size
);
205 if (!buffer
) return 0;
206 WideCharToMultiByte(CP_ACP
, 0, str
, len
,
207 buffer
, buffer_size
, NULL
, NULL
);
208 result
= editor
->pfnWordBreak((WCHAR
*)buffer
, start
, buffer_size
, code
);
214 LPWSTR
ME_ToUnicode(LONG codepage
, LPVOID psz
, INT
*len
)
217 if (!psz
) return NULL
;
219 if (codepage
== CP_UNICODE
)
221 *len
= lstrlenW(psz
);
226 int nChars
= MultiByteToWideChar(codepage
, 0, psz
, -1, NULL
, 0);
228 if(!nChars
) return NULL
;
230 if((tmp
= heap_alloc( nChars
* sizeof(WCHAR
) )) != NULL
)
231 *len
= MultiByteToWideChar(codepage
, 0, psz
, -1, tmp
, nChars
) - 1;
236 void ME_EndToUnicode(LONG codepage
, LPVOID psz
)
238 if (codepage
!= CP_UNICODE
)