sync with trunk r46493
[reactos.git] / dll / win32 / riched20 / string.c
index 97b5a67..db45d92 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "editor.h"     
+#include "editor.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 
-int ME_GetOptimalBuffer(int nLen)
+static int ME_GetOptimalBuffer(int nLen)
 {
-  return ((2*nLen+1)+128)&~63;
+  /* FIXME: This seems wasteful for tabs and end of lines strings,
+   *        since they have a small fixed length. */
+  return ((sizeof(WCHAR) * nLen) + 128) & ~63;
 }
 
-ME_String *ME_MakeString(LPCWSTR szText)
+/* Create a buffer (uninitialized string) of size nMaxChars */
+static ME_String *ME_MakeStringB(int nMaxChars)
 {
   ME_String *s = ALLOC_OBJ(ME_String);
-  s->nLen = lstrlenW(szText);
-  s->nBuffer = ME_GetOptimalBuffer(s->nLen+1);
+
+  s->nLen = nMaxChars;
+  s->nBuffer = ME_GetOptimalBuffer(s->nLen + 1);
   s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
-  lstrcpyW(s->szData, szText);
+  s->szData[s->nLen] = 0;
   return s;
 }
 
 ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars)
 {
-  ME_String *s = ALLOC_OBJ(ME_String);
-  
-  s->nLen = nMaxChars;
-  s->nBuffer = ME_GetOptimalBuffer(s->nLen+1);
-  s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
-  /* Native allows NUL chars */
-  memmove(s->szData, szText, s->nLen * sizeof(WCHAR));
-  s->szData[s->nLen] = 0;
+  ME_String *s = ME_MakeStringB(nMaxChars);
+  /* Native allows NULL chars */
+  memcpy(s->szData, szText, s->nLen * sizeof(WCHAR));
   return s;
 }
 
+/* Make a string by repeating a char nMaxChars times */
 ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars)
-{ /* Make a string by repeating a char nMaxChars times */
+{
   int i;
-   ME_String *s = ALLOC_OBJ(ME_String);
-  
-  s->nLen = nMaxChars;
-  s->nBuffer = ME_GetOptimalBuffer(s->nLen+1);
-  s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
-
-  for (i = 0;i<nMaxChars;i++)
+  ME_String *s = ME_MakeStringB(nMaxChars);
+  for (i = 0; i < nMaxChars; i++)
     s->szData[i] = cRepeat;
-  s->szData[s->nLen] = 0;
-  return s;
-}
-
-ME_String *ME_MakeStringB(int nMaxChars)
-{ /* Create a buffer (uninitialized string) of size nMaxChars */
-  ME_String *s = ALLOC_OBJ(ME_String);
-  
-  s->nLen = nMaxChars;
-  s->nBuffer = ME_GetOptimalBuffer(s->nLen+1);
-  s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
-  s->szData[s->nLen] = 0;
   return s;
 }
 
@@ -83,41 +66,32 @@ ME_String *ME_StrDup(const ME_String *s)
 
 void ME_DestroyString(ME_String *s)
 {
+  if (!s) return;
   FREE_OBJ(s->szData);
   FREE_OBJ(s);
 }
 
 void ME_AppendString(ME_String *s1, const ME_String *s2)
 {
-  if (s1->nLen+s2->nLen+1 <= s1->nBuffer) {
-    lstrcpyW(s1->szData+s1->nLen, s2->szData);
-    s1->nLen += s2->nLen;
-  }
-  else
+  if (s1->nLen+s2->nLen+1 <= s1->nBuffer)
   {
+    memcpy(s1->szData + s1->nLen, s2->szData, s2->nLen * sizeof(WCHAR));
+    s1->nLen += s2->nLen;
+    s1->szData[s1->nLen] = 0;
+  } else {
     WCHAR *buf;
     s1->nBuffer = ME_GetOptimalBuffer(s1->nLen+s2->nLen+1);
 
-    buf = ALLOC_N_OBJ(WCHAR, s1->nBuffer); 
-    lstrcpyW(buf, s1->szData);
-    lstrcpyW(buf+s1->nLen, s2->szData);
+    buf = ALLOC_N_OBJ(WCHAR, s1->nBuffer);
+    memcpy(buf, s1->szData, s1->nLen * sizeof(WCHAR));
+    memcpy(buf + s1->nLen, s2->szData, s2->nLen * sizeof(WCHAR));
     FREE_OBJ(s1->szData);
     s1->szData = buf;
     s1->nLen += s2->nLen;
+    s1->szData[s1->nLen] = 0;
   }
 }
 
-ME_String *ME_ConcatString(const ME_String *s1, const ME_String *s2)
-{
-  ME_String *s = ALLOC_OBJ(ME_String);
-  s->nLen = s1->nLen+s2->nLen;
-  s->nBuffer = ME_GetOptimalBuffer(s1->nLen+s2->nLen+1);
-  s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
-  lstrcpyW(s->szData, s1->szData);
-  lstrcpyW(s->szData+s1->nLen, s2->szData);
-  return s;  
-}
-
 ME_String *ME_VSplitString(ME_String *orig, int charidx)
 {
   ME_String *s;
@@ -162,113 +136,17 @@ int ME_IsSplitable(const ME_String *s)
   return 0;
 }
 
-/* FIXME multibyte */
-/*
-int ME_CalcSkipChars(ME_String *s)
-{
-  int cnt = 0;
-  while(cnt < s->nLen && s->szData[s->nLen-1-cnt]==' ')
-    cnt++;
-  return cnt;
-}
-*/
-
-int ME_StrLen(const ME_String *s) {
-  return s->nLen;
-}
-
-int ME_StrVLen(const ME_String *s) {
-  return s->nLen;
-}
-
-int ME_StrRelPos(const ME_String *s, int nVChar, int *pRelChars)
-{
-  int nRelChars = *pRelChars;
-
-  TRACE("%s,%d,&%d\n", debugstr_w(s->szData), nVChar, *pRelChars);
-
-  assert(*pRelChars);
-  if (!nRelChars)
-    return nVChar;
-  
-  if (nRelChars>0)
-    nRelChars = min(*pRelChars, s->nLen - nVChar);
-  else
-    nRelChars = max(*pRelChars, -nVChar);
-  nVChar += nRelChars;
-  *pRelChars -= nRelChars;
-  return nVChar;
-}
-
-int ME_StrRelPos2(const ME_String *s, int nVChar, int nRelChars)
-{
-  return ME_StrRelPos(s, nVChar, &nRelChars);
-}
-
-int ME_VPosToPos(ME_String *s, int nVPos)
-{
-  return nVPos;
-  /*
-  int i = 0, len = 0;
-  if (!nVPos)
-    return 0;
-  while (i < s->nLen)
-  {
-    if (i == nVPos)
-      return len;
-    if (s->szData[i]=='\\') i++;
-    i++;
-    len++;
-  }
-  return len;
-  */
-}
-
-int ME_PosToVPos(const ME_String *s, int nPos)
-{
-  if (!nPos)
-    return 0;
-  return ME_StrRelPos2(s, 0, nPos);
-}
-
 void ME_StrDeleteV(ME_String *s, int nVChar, int nChars)
 {
-  int end_ofs;
-  
-  assert(nVChar >=0 && nVChar <= s->nLen);
+  int end_ofs = nVChar + nChars;
+
   assert(nChars >= 0);
-  assert(nVChar+nChars <= s->nLen);
-  
-  end_ofs = ME_StrRelPos2(s, nVChar, nChars);
+  assert(nVChar >= 0);
   assert(end_ofs <= s->nLen);
-  memmove(s->szData+nVChar, s->szData+end_ofs, 2*(s->nLen+1-end_ofs));
-  s->nLen -= (end_ofs - nVChar);
-}
 
-int ME_GetCharFwd(const ME_String *s, int nPos)
-{
-  int nVPos = 0;
-
-  assert(nPos < ME_StrLen(s));
-  if (nPos)
-    nVPos = ME_StrRelPos2(s, nVPos, nPos);
-  
-  if (nVPos < s->nLen)
-    return s->szData[nVPos];
-  return -1;
-}
-
-int ME_GetCharBack(const ME_String *s, int nPos)
-{
-  int nVPos = ME_StrVLen(s);
-
-  assert(nPos < ME_StrLen(s));
-  if (nPos)
-    nVPos = ME_StrRelPos2(s, nVPos, -nPos);
-  
-  if (nVPos < s->nLen)
-    return s->szData[nVPos];
-  return -1;
+  memmove(s->szData + nVChar, s->szData + end_ofs,
+          (s->nLen - end_ofs + 1) * sizeof(WCHAR));
+  s->nLen -= nChars;
 }
 
 int ME_FindNonWhitespaceV(const ME_String *s, int nVChar) {
@@ -304,6 +182,8 @@ ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code)
   /* FIXME: Native also knows about punctuation */
   TRACE("s==%s, start==%d, len==%d, code==%d\n",
         debugstr_wn(s, len), start, len, code);
+  /* convert number of bytes to number of characters. */
+  len /= sizeof(WCHAR);
   switch (code)
   {
     case WB_ISDELIMITER:
@@ -330,11 +210,23 @@ ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code)
 int
 ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code)
 {
-  /* FIXME: ANSIfy the string when bEmulateVersion10 is TRUE */
-  if (!editor->pfnWordBreak)
-    return ME_WordBreakProc(str->szData, start, str->nLen, code);
-  else
-    return editor->pfnWordBreak(str->szData, start, str->nLen, code);
+  if (!editor->pfnWordBreak) {
+    return ME_WordBreakProc(str->szData, start, str->nLen*sizeof(WCHAR), code);
+  } else if (!editor->bEmulateVersion10) {
+    /* MSDN lied about the third parameter for EditWordBreakProc being the number
+     * of characters, it is actually the number of bytes of the string. */
+    return editor->pfnWordBreak(str->szData, start, str->nLen*sizeof(WCHAR), code);
+  } else {
+    int result;
+    int buffer_size = WideCharToMultiByte(CP_ACP, 0, str->szData, str->nLen,
+                                          NULL, 0, NULL, NULL);
+    char *buffer = heap_alloc(buffer_size);
+    WideCharToMultiByte(CP_ACP, 0, str->szData, str->nLen,
+                        buffer, buffer_size, NULL, NULL);
+    result = editor->pfnWordBreak(str->szData, start, str->nLen, code);
+    heap_free(buffer);
+    return result;
+  }
 }
 
 LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz)
@@ -342,12 +234,12 @@ LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz)
   assert(psz != NULL);
 
   if (unicode)
-    return (LPWSTR)psz;
+    return psz;
   else {
     WCHAR *tmp;
-    int nChars = MultiByteToWideChar(CP_ACP, 0, (char *)psz, -1, NULL, 0);
+    int nChars = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
     if((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL)
-      MultiByteToWideChar(CP_ACP, 0, (char *)psz, -1, tmp, nChars);
+      MultiByteToWideChar(CP_ACP, 0, psz, -1, tmp, nChars);
     return tmp;
   }
 }