Sync to Wine-20050830:
authorGé van Geldorp <ge@gse.nl>
Mon, 5 Sep 2005 22:07:52 +0000 (22:07 +0000)
committerGé van Geldorp <ge@gse.nl>
Mon, 5 Sep 2005 22:07:52 +0000 (22:07 +0000)
Phil Krylov <phil@newstar.rinet.ru>
- Added support for backward search to RichEdit EM_FINDTEXT[AW],
  EM_FINDTEXTEX[AW] message handler.
- Fixed EM_SETEVENTMASK RichEdit message handler to return old event
  mask.
- Added handling of deff RTF control word.
- Added common keyboard shortcuts for Select All, Undo, Redo, Cut, Copy
  and Paste to RichEdit.
- Automatically set default font after parsing a font table in RichEdit
  RTF reader.
- Fixed EM_EXLINEFROMCHAR to work for last row of a paragraph.
- Fixed UTF-8 RTF parsing.
- Fixed a bug in EM_STREAMOUT RichEdit message handler which truncated
  some streamed text.
- Generate ending \par in RTF output of RichEdit when streaming out a
  whole document.
- Fixed a RichEdit RTF reader bug which resulted in loss of text.
  Eliminated unneeded recursion in ME_InsertTextFromCursor().
- Implemented EM_CHARFROMPOS RichEdit message.
- Added EM_SETRECT, EM_SETRECTNP, and WM_SETREDRAW message handling.
  Added support for GT_SELECTION flag in EM_GETTEXTEX handler.
Mike McCormack <mike@codeweavers.com>
- gcc 4.0 warning fixes for Interlocked* functions.

svn path=/trunk/; revision=17681

12 files changed:
reactos/lib/riched20/caret.c
reactos/lib/riched20/context.c
reactos/lib/riched20/editor.c
reactos/lib/riched20/editor.h
reactos/lib/riched20/editstr.h
reactos/lib/riched20/paint.c
reactos/lib/riched20/reader.c
reactos/lib/riched20/richole.c
reactos/lib/riched20/row.c
reactos/lib/riched20/rtf.h
reactos/lib/riched20/writer.c
reactos/w32api/include/richedit.h

index f1c87db..9c30e5c 100644 (file)
@@ -325,6 +325,28 @@ void ME_InsertGraphicsFromCursor(ME_TextEditor *editor, int nCursor)
   ME_SendSelChange(editor);
 }
 
+
+static void
+ME_InternalInsertTextFromCursor(ME_TextEditor *editor, int nCursor,
+                                const WCHAR *str, int len, ME_Style *style,
+                                int flags)
+{
+  ME_DisplayItem *pNewRun = NULL;
+  ME_Cursor *p = &editor->pCursors[nCursor];
+
+  editor->bCaretAtEnd = FALSE;
+  
+  assert(p->pRun->type == diRun);
+  
+  ME_AddRefStyle(style);
+  
+  pNewRun = ME_MakeRun(style, ME_MakeStringN(str, len), flags); /* addrefs style */
+  ME_InsertRun(editor, ME_CharOfsFromRunOfs(editor, p->pRun, p->nOffset), pNewRun);
+  ME_DestroyDisplayItem(pNewRun);
+  ME_ReleaseStyle(style);
+}
+
+
 void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, 
   const WCHAR *str, int len, ME_Style *style)
 {
@@ -332,10 +354,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
   ME_Cursor *p = NULL;
 
   assert(style);
-  editor->bCaretAtEnd = FALSE;
 
-  ME_AddRefStyle(style);
-  
   /* FIXME really HERE ? */
   if (ME_IsSelection(editor))
     ME_DeleteSelection(editor);
@@ -343,75 +362,61 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
   assert(nCursor>=0 && nCursor<editor->nCursors);
   if (len == -1)
     len = lstrlenW(str);
-  pos = str;
-  /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
-  while(pos-str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
-    pos++;
-  if (pos-str < len && *pos == '\t') { /* handle tabs */
-    ME_DisplayItem *pNewRun = NULL;
-    WCHAR tab = '\t';
+  while (len)
+  {
+    pos = str;
+    /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
+    while(pos-str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
+      pos++;
+    if (pos-str < len && *pos == '\t') { /* handle tabs */
+      WCHAR tab = '\t';
 
-    if (pos!=str)
-      ME_InsertTextFromCursor(editor, nCursor, str, pos-str, style);
+      if (pos!=str)
+        ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
     
-    p = &editor->pCursors[nCursor];
-    assert(style);
-    assert(p->pRun->type == diRun);
-    pNewRun = ME_MakeRun(style, ME_MakeStringN(&tab, 1), MERF_TAB); /* addrefs style */
-    ME_InsertRun(editor, ME_CharOfsFromRunOfs(editor, p->pRun, p->nOffset), pNewRun);
-    ME_DestroyDisplayItem(pNewRun);
-    ME_ReleaseStyle(style);
-
-    pos++;
-    if(pos-str < len) {
-      ME_InsertTextFromCursor(editor, nCursor, pos, len-(pos-str), style);
+      ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
+      pos++;
+      if(pos-str <= len) {
+        len -= pos - str;
+        str = pos;
+        continue;
+      }
     }
-    return;
-  }
-  if (pos-str < len) {   /* handle EOLs */
-    ME_DisplayItem *tp, *end_run;
-    ME_Paragraph *para;
-    ME_Style *tmp_style;
-    if (pos!=str)
-      ME_InsertTextFromCursor(editor, nCursor, str, pos-str, style);
-    p = &editor->pCursors[nCursor];
-    tp = ME_FindItemBack(p->pRun, diParagraph);
-    para = &tp->member.para;
-    assert(tp);
-    if (p->nOffset) {
-      ME_SplitRunSimple(editor, p->pRun, p->nOffset);
+    if (pos-str < len) {   /* handle EOLs */
+      ME_DisplayItem *tp, *end_run;
+      ME_Paragraph *para;
+      ME_Style *tmp_style;
+      if (pos!=str)
+        ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
       p = &editor->pCursors[nCursor];
+      tp = ME_FindItemBack(p->pRun, diParagraph);
+      para = &tp->member.para;
+      assert(tp);
+      if (p->nOffset) {
+        ME_SplitRunSimple(editor, p->pRun, p->nOffset);
+        p = &editor->pCursors[nCursor];
+      }
+      tmp_style = ME_GetInsertStyle(editor, nCursor);
+      /* ME_SplitParagraph increases style refcount */
+      tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style);
+      p->pRun = ME_FindItemFwd(tp, diRun);
+      end_run = ME_FindItemBack(tp, diRun);
+      ME_ReleaseStyle(end_run->member.run.style);
+      end_run->member.run.style = tmp_style;
+      p->nOffset = 0;
+      if(pos-str < len && *pos =='\r')
+        pos++;
+      if(pos-str < len && *pos =='\n')
+        pos++;
+      if(pos-str <= len) {
+        len -= pos - str;
+        str = pos;
+        continue;
+      }
     }
-    tmp_style = ME_GetInsertStyle(editor, nCursor);
-    /* ME_SplitParagraph increases style refcount */
-    tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style);
-    p->pRun = ME_FindItemFwd(tp, diRun);
-    end_run = ME_FindItemBack(tp, diRun);
-    ME_ReleaseStyle(end_run->member.run.style);
-    end_run->member.run.style = tmp_style;
-    p->nOffset = 0;
-    if(pos-str < len && *pos =='\r')
-      pos++;
-    if(pos-str < len && *pos =='\n')
-      pos++;
-    if(pos-str < len) {
-      ME_InsertTextFromCursor(editor, nCursor, pos, len-(pos-str), style);
-    }
-    ME_ReleaseStyle(style);
-    return;
-  }
-  p = &editor->pCursors[nCursor];
-  if (style) {
-    ME_DisplayItem *pNewRun = NULL;
-
-    assert(p->pRun->type == diRun);
-    pNewRun = ME_MakeRun(style, ME_MakeStringN(str, len), 0); /* addrefs style */
-    ME_InsertRun(editor, ME_CharOfsFromRunOfs(editor, p->pRun, p->nOffset), pNewRun);
-    ME_DestroyDisplayItem(pNewRun);
-    ME_ReleaseStyle(style);
-    return;
-  } else {
-    assert(0);
+    ME_InternalInsertTextFromCursor(editor, nCursor, str, len, style, 0);
+    len = 0;
   }
 }
 
@@ -584,6 +589,22 @@ int ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *result, BOOL
   return 0;
 }
 
+
+int
+ME_CharFromPos(ME_TextEditor *editor, int x, int y)
+{
+  ME_Cursor cursor;
+  RECT rc;
+
+  GetClientRect(editor->hWnd, &rc);
+  if (x < 0 || y < 0 || x >= rc.right || y >= rc.bottom)
+    return -1;
+  ME_FindPixelPos(editor, x, y, &cursor, NULL);
+  return (ME_GetParagraph(cursor.pRun)->member.para.nCharOfs
+          + cursor.pRun->member.run.nCharOfs + cursor.nOffset);
+}
+
+
 void ME_LButtonDown(ME_TextEditor *editor, int x, int y)
 {
   ME_Cursor tmp_cursor;
index 62b0259..0c851e6 100644 (file)
@@ -28,7 +28,7 @@ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC)
   c->pt.x = 0;
   c->pt.y = 0;
   c->hbrMargin = CreateSolidBrush(RGB(224,224,224));
-  GetClientRect(editor->hWnd, &c->rcView);
+  c->rcView = editor->rcFormat;
 }
 
 void ME_DestroyContext(ME_Context *c)
index 8339b12..a074d55 100644 (file)
@@ -26,7 +26,7 @@
   + EM_CANPASTE
   + EM_CANREDO 2.0
   + EM_CANUNDO
-  - EM_CHARFROMPOS
+  + EM_CHARFROMPOS
   - EM_DISPLAYBAND
   + EM_EMPTYUNDOBUFFER
   + EM_EXGETSEL
@@ -58,7 +58,7 @@
   + EM_GETPARAFORMAT
   - EM_GETPASSWORDCHAR 2.0
   - EM_GETPUNCTUATION 1.0asian
-  - EM_GETRECT
+  + EM_GETRECT
   - EM_GETREDONAME 2.0
   + EM_GETSEL
   + EM_GETSELTEXT (ANSI&Unicode)
   - EM_SETPASSWORDCHAR 2.0
   - EM_SETPUNCTUATION 1.0asian
   + EM_SETREADONLY no beep on modification attempt
-  - EM_SETRECT
-  - EM_SETRECTNP (EM_SETRECT without repainting) - not supported in RICHEDIT
+  + EM_SETRECT
+  + EM_SETRECTNP (EM_SETRECT without repainting)
   + EM_SETSEL
   - EM_SETSCROLLPOS 3.0
   - EM_SETTABSTOPS 3.0
@@ -393,6 +393,7 @@ static void ME_RTFCharAttrHook(RTF_Info *info)
     style2 = ME_ApplyStyle(info->style, &fmt);
     ME_ReleaseStyle(info->style);
     info->style = style2;
+    info->styleChanged = TRUE;
   }
 }
 
@@ -476,18 +477,22 @@ static void ME_RTFReadHook(RTF_Info *info) {
             info->stack[info->stackTop].unicodeLength = info->unicodeLength;
           }
           info->stackTop++;
+          info->styleChanged = FALSE;
           break;
         case rtfEndGroup:
         {
           ME_Style *s;
           RTFFlushOutputBuffer(info);
           info->stackTop--;
-          /* FIXME too slow ? how come ? */
-          s = ME_ApplyStyle(info->style, &info->stack[info->stackTop].fmt);
-          ME_ReleaseStyle(info->style);
-          info->style = s;
-          info->codePage = info->stack[info->stackTop].codePage;
-          info->unicodeLength = info->stack[info->stackTop].unicodeLength;
+          if (info->styleChanged)
+          {
+            /* FIXME too slow ? how come ? */
+            s = ME_ApplyStyle(info->style, &info->stack[info->stackTop].fmt);
+            ME_ReleaseStyle(info->style);
+            info->style = s;
+            info->codePage = info->stack[info->stackTop].codePage;
+            info->unicodeLength = info->stack[info->stackTop].unicodeLength;
+          }
           break;
         }
       }
@@ -613,8 +618,11 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
   ME_CommitUndo(editor);
   ME_ReleaseStyle(style); 
   editor->nEventMask = nEventMask;
-  InvalidateRect(editor->hWnd, NULL, TRUE);
-  ME_UpdateRepaint(editor);
+  if (editor->bRedraw)
+  {
+    InvalidateRect(editor->hWnd, NULL, TRUE);
+    ME_UpdateRepaint(editor);
+  }
   if (!(format & SFF_SELECTION)) {
     ME_ClearTempStyle(editor);
   }
@@ -658,62 +666,130 @@ ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int
 static int
 ME_FindText(ME_TextEditor *editor, DWORD flags, CHARRANGE *chrg, WCHAR *text, CHARRANGE *chrgText)
 {
-  int nStart = chrg->cpMin;
+  int nStart, nEnd;
   int nLen = lstrlenW(text);
-  ME_DisplayItem *item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart);
+  int nMin, nMax;
+  ME_DisplayItem *item;
   ME_DisplayItem *para;
+
+  TRACE("flags==0x%08lx, chrg->cpMin==%ld, chrg->cpMax==%ld text==%s\n",
+        flags, chrg->cpMin, chrg->cpMax, debugstr_w(text));
   
-  if (!item)
-    return -1;
+  if (!(flags & FR_MATCHCASE))
+    FIXME("Case-insensitive search not implemented\n");
+  if (flags & ~(FR_DOWN | FR_MATCHCASE))
+    FIXME("Flags 0x%08lx not implemented\n", flags & ~(FR_DOWN | FR_MATCHCASE));
 
+  if (chrg->cpMax == -1)
+  {
+    nMin = chrg->cpMin;
+    nMax = ME_GetTextLength(editor);
+  }
+  else
+  {
+    nMin = min(chrg->cpMin, chrg->cpMax);
+    nMax = max(chrg->cpMin, chrg->cpMax);
+  }
+  
   if (!nLen)
   {
     if (chrgText)
-      chrgText->cpMin = chrgText->cpMax = chrg->cpMin;
-    return chrg->cpMin;
+      chrgText->cpMin = chrgText->cpMax = ((flags & FR_DOWN) ? nMin : nMax);
+    return chrgText->cpMin;
   }
  
-  if (!(flags & FR_DOWN))
-    FIXME("Backward search not implemented\n");
-  if (!(flags & FR_MATCHCASE))
-    FIXME("Case-insensitive search not implemented\n");
-  if (flags & ~(FR_DOWN | FR_MATCHCASE))
-    FIXME("Flags 0x%08lx not implemented\n", flags & ~(FR_DOWN | FR_MATCHCASE));
-  
-  para = ME_GetParagraph(item);
-  while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart + nLen < chrg->cpMax)
+  if (flags & FR_DOWN) /* Forward search */
   {
-    ME_DisplayItem *pCurItem = item;
-    int nCurStart = nStart;
-    int nMatched = 0;
-    
-    while (pCurItem->member.run.strText->szData[nCurStart + nMatched] == text[nMatched])
+    nStart = nMin;
+    item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart);
+    if (!item)
+      return -1;
+
+    para = ME_GetParagraph(item);
+    while (item
+           && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart + nLen < nMax)
     {
-      nMatched++;
-      if (nMatched == nLen)
+      ME_DisplayItem *pCurItem = item;
+      int nCurStart = nStart;
+      int nMatched = 0;
+    
+      while (pCurItem && pCurItem->member.run.strText->szData[nCurStart + nMatched] == text[nMatched])
       {
-        nStart += para->member.para.nCharOfs + item->member.run.nCharOfs;
-        if (chrgText)
+        nMatched++;
+        if (nMatched == nLen)
+        {
+          nStart += para->member.para.nCharOfs + item->member.run.nCharOfs;
+          if (chrgText)
+          {
+            chrgText->cpMin = nStart;
+            chrgText->cpMax = nStart + nLen;
+          }
+          TRACE("found at %d-%d\n", nStart, nStart + nLen);
+          return nStart;
+        }
+        if (nCurStart + nMatched == ME_StrLen(pCurItem->member.run.strText))
         {
-          chrgText->cpMin = nStart;
-          chrgText->cpMax = nStart + nLen;
+          pCurItem = ME_FindItemFwd(pCurItem, diRun);
+          para = ME_GetParagraph(pCurItem);
+          nCurStart = -nMatched;
         }
-        return nStart;
       }
-      if (nCurStart + nMatched == ME_StrLen(pCurItem->member.run.strText))
+      nStart++;
+      if (nStart == ME_StrLen(item->member.run.strText))
       {
-        pCurItem = ME_FindItemFwd(pCurItem, diRun);
-        nCurStart = -nMatched;
+        item = ME_FindItemFwd(item, diRun);
+        para = ME_GetParagraph(item);
+        nStart = 0;
       }
     }
-    nStart++;
-    if (nStart == ME_StrLen(item->member.run.strText))
+  }
+  else /* Backward search */
+  {
+    nEnd = nMax;
+    item = ME_FindItemAtOffset(editor, diRun, nEnd, &nEnd);
+    if (!item)
+      return -1;
+    
+    para = ME_GetParagraph(item);
+    
+    while (item
+           && para->member.para.nCharOfs + item->member.run.nCharOfs + nEnd - nLen >= nMin)
     {
-      item = ME_FindItemFwd(item, diRun);
-      para = ME_GetParagraph(item);
-      nStart = 0;
+      ME_DisplayItem *pCurItem = item;
+      int nCurEnd = nEnd;
+      int nMatched = 0;
+      
+      while (pCurItem && pCurItem->member.run.strText->szData[nCurEnd - nMatched - 1] == text[nLen - nMatched - 1])
+      {
+        nMatched++;
+        if (nMatched == nLen)
+        {
+          nStart = para->member.para.nCharOfs + item->member.run.nCharOfs + nCurEnd - nMatched;
+          if (chrgText)
+          {
+            chrgText->cpMin = nStart;
+            chrgText->cpMax = nStart + nLen;
+          }
+          TRACE("found at %d-%d\n", nStart, nStart + nLen);
+          return nStart;
+        }
+        if (nCurEnd - nMatched == 0)
+        {
+          pCurItem = ME_FindItemBack(pCurItem, diRun);
+          para = ME_GetParagraph(pCurItem);
+          nCurEnd = ME_StrLen(pCurItem->member.run.strText) + nMatched;
+        }
+      }
+      nEnd--;
+      if (nEnd < 0)
+      {
+        item = ME_FindItemBack(item, diRun);
+        para = ME_GetParagraph(item);
+        nEnd = ME_StrLen(item->member.run.strText);
+      }
     }
   }
+  TRACE("not found\n");
   return -1;
 }
 
@@ -748,6 +824,8 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
   ed->nLastSelStart = ed->nLastSelEnd = 0;
   ed->nScrollPosY = 0;
   ed->nZoomNumerator = ed->nZoomDenominator = 0;
+  ed->bRedraw = TRUE;
+  GetClientRect(hWnd, &ed->rcFormat);
   for (i=0; i<HFONT_CACHE_SIZE; i++)
   {
     ed->pFontCache[i].nRefs = 0;
@@ -1016,17 +1094,15 @@ get_msg_name(UINT msg)
  *        RichEditANSIWndProc (RICHED20.10)
  */
 LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
-  HDC hDC;
-  PAINTSTRUCT ps;
   SCROLLINFO si;
   ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongW(hWnd, 0);
   
-  TRACE("msg %d (%s) %08x %08lx\n", msg, get_msg_name(msg), wParam, lParam);
+  TRACE("hWnd %p msg %d (%s) %08x %08lx\n",
+        hWnd, msg, get_msg_name(msg), wParam, lParam);
   
   switch(msg) {
   
   UNSUPPORTED_MSG(EM_AUTOURLDETECT)
-  UNSUPPORTED_MSG(EM_CHARFROMPOS)
   UNSUPPORTED_MSG(EM_DISPLAYBAND)
   UNSUPPORTED_MSG(EM_EXLIMITTEXT)
   UNSUPPORTED_MSG(EM_FINDWORDBREAK)
@@ -1044,7 +1120,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
   /* UNSUPPORTED_MSG(EM_GETOLEINTERFACE) separate stub */
   UNSUPPORTED_MSG(EM_GETOPTIONS)
   UNSUPPORTED_MSG(EM_GETPASSWORDCHAR)
-  UNSUPPORTED_MSG(EM_GETRECT)
   UNSUPPORTED_MSG(EM_GETREDONAME)
   UNSUPPORTED_MSG(EM_GETSCROLLPOS)
   UNSUPPORTED_MSG(EM_GETTEXTMODE)
@@ -1068,8 +1143,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
   UNSUPPORTED_MSG(EM_SETOPTIONS)
   UNSUPPORTED_MSG(EM_SETPALETTE)
   UNSUPPORTED_MSG(EM_SETPASSWORDCHAR)
-  UNSUPPORTED_MSG(EM_SETRECT)
-  UNSUPPORTED_MSG(EM_SETRECTNP)
   UNSUPPORTED_MSG(EM_SETSCROLLPOS)
   UNSUPPORTED_MSG(EM_SETTABSTOPS)
   UNSUPPORTED_MSG(EM_SETTARGETDEVICE)
@@ -1131,6 +1204,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     return editor->pUndoStack != NULL;
   case EM_CANREDO:
     return editor->pRedoStack != NULL;
+  case WM_UNDO: /* FIXME: actually not the same */
   case EM_UNDO:
     ME_Undo(editor);
     return 0;
@@ -1191,9 +1265,12 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     if (wParam)
       editor->rgbBackColor = -1;
     else
-      editor->rgbBackColor = lParam; 
-    InvalidateRect(hWnd, NULL, TRUE);
-    UpdateWindow(hWnd);
+      editor->rgbBackColor = lParam;
+    if (editor->bRedraw)
+    {
+      InvalidateRect(hWnd, NULL, TRUE);
+      UpdateWindow(hWnd);
+    }
     return lColor;
   }
   case EM_GETMODIFY:
@@ -1219,8 +1296,12 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     return 0;
   }
   case EM_SETEVENTMASK:
+  {
+    DWORD nOldMask = editor->nEventMask;
+    
     editor->nEventMask = lParam;
-    return 0;
+    return nOldMask;
+  }
   case EM_GETEVENTMASK:
     return editor->nEventMask;
   case EM_SETCHARFORMAT:
@@ -1278,10 +1359,13 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     if (nPos<0)
       nPos = 0;
     if (nPos != editor->nScrollPosY) {
-      ScrollWindow(hWnd, 0, editor->nScrollPosY-nPos, NULL, NULL);
+      if (editor->bRedraw)
+      {
+        ScrollWindow(hWnd, 0, editor->nScrollPosY-nPos, NULL, NULL);
+        SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
+        UpdateWindow(hWnd);
+      }
       editor->nScrollPosY = nPos;
-      SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
-      UpdateWindow(hWnd);
     }
     return TRUE; /* Should return false if a single line richedit control */
   }
@@ -1430,20 +1514,35 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
   case EM_GETTEXTEX:
   {
     GETTEXTEX *ex = (GETTEXTEX*)wParam;
+    int nStart, nCount;
 
-    if (ex->flags != 0)
-        FIXME("Unhandled EM_GETTEXTEX flags 0x%lx\n",ex->flags);
+    if (ex->flags & ~(GT_SELECTION | GT_USECRLF))
+      FIXME("GETTEXTEX flags 0x%08lx not supported\n", ex->flags & ~(GT_SELECTION | GT_USECRLF));
 
-    if (IsWindowUnicode(hWnd))
-      return ME_GetTextW(editor, (LPWSTR)lParam, 0, ex->cb, FALSE);
+    if (ex->flags & GT_SELECTION)
+    {
+      ME_GetSelection(editor, &nStart, &nCount);
+      nCount -= nStart;
+      nCount = min(nCount, ex->cb - 1);
+    }
+    else
+    {
+      nStart = 0;
+      nCount = ex->cb - 1;
+    }
+    if (ex->codepage == 1200 || IsWindowUnicode(hWnd))
+    {
+      nCount = min(nCount, ex->cb / sizeof(WCHAR) - 1);
+      return ME_GetTextW(editor, (LPWSTR)lParam, nStart, nCount, ex->flags & GT_USECRLF);
+    }
     else
     {
-        LPWSTR buffer = HeapAlloc(GetProcessHeap(),0,ex->cb*sizeof(WCHAR));
+        LPWSTR buffer = HeapAlloc(GetProcessHeap(), 0, (nCount + 1) * sizeof(WCHAR));
         DWORD buflen = ex->cb;
         LRESULT rc;
         DWORD flags = 0;
 
-        buflen = ME_GetTextW(editor, buffer, 0, buflen, FALSE);
+        buflen = ME_GetTextW(editor, buffer, nStart, nCount, ex->flags & GT_USECRLF);
         rc = WideCharToMultiByte(ex->codepage, flags, buffer, buflen, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefaultChar);
 
         HeapFree(GetProcessHeap(),0,buffer);
@@ -1464,12 +1563,12 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
   {
     TEXTRANGEW *rng = (TEXTRANGEW *)lParam;
     if (IsWindowUnicode(hWnd))
-      return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, rng->chrg.cpMax-rng->chrg.cpMin, FALSE);
+      return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, rng->chrg.cpMax-rng->chrg.cpMin, editor->bEmulateVersion10);
     else
     {
       int nLen = rng->chrg.cpMax-rng->chrg.cpMin;
       WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1);
-      int nChars = ME_GetTextW(editor, p, rng->chrg.cpMin, nLen, FALSE);
+      int nChars = ME_GetTextW(editor, p, rng->chrg.cpMin, nLen, editor->bEmulateVersion10);
       /* FIXME this is a potential security hole (buffer overrun) 
          if you know more about wchar->mbyte conversion please explain
       */
@@ -1477,7 +1576,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
       FREE_OBJ(p);
       return nChars;
     }
-    return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, rng->chrg.cpMax-rng->chrg.cpMin, FALSE);
   }
   case EM_GETLINECOUNT:
   {
@@ -1587,6 +1685,8 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     return TRUE;
   case EM_SETZOOM:
     return ME_SetZoom(editor, wParam, lParam);
+  case EM_CHARFROMPOS:
+    return ME_CharFromPos(editor, ((POINTL *)lParam)->x, ((POINTL *)lParam)->y);
   case WM_CREATE:
     ME_CommitUndo(editor);
     ME_WrapMarkedParagraphs(editor);
@@ -1610,9 +1710,15 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
       ReleaseCapture();
     break;
   case WM_PAINT:
-    hDC = BeginPaint(hWnd, &ps);
-    ME_PaintContent(editor, hDC, FALSE, &ps.rcPaint);
-    EndPaint(hWnd, &ps);
+    if (editor->bRedraw)
+    {
+      HDC hDC;
+      PAINTSTRUCT ps;
+
+      hDC = BeginPaint(hWnd, &ps);
+      ME_PaintContent(editor, hDC, FALSE, &ps.rcPaint);
+      EndPaint(hWnd, &ps);
+    }
     break;
   case WM_SETFOCUS:
     ME_ShowCaret(editor);
@@ -1624,14 +1730,17 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     return 0;
   case WM_ERASEBKGND:
   {
-    HDC hDC = (HDC)wParam;
-    RECT rc;
-    COLORREF rgbBG = ME_GetBackColor(editor);
-    if (GetUpdateRect(hWnd,&rc,TRUE))
+    if (editor->bRedraw)
     {
-      HBRUSH hbr = CreateSolidBrush(rgbBG);
-      FillRect(hDC, &rc, hbr);
-      DeleteObject(hbr);
+      HDC hDC = (HDC)wParam;
+      RECT rc;
+      COLORREF rgbBG = ME_GetBackColor(editor);
+      if (GetUpdateRect(hWnd,&rc,TRUE))
+      {
+        HBRUSH hbr = CreateSolidBrush(rgbBG);
+        FillRect(hDC, &rc, hbr);
+        DeleteObject(hbr);
+      }
     }
     return 1;
   }
@@ -1665,12 +1774,38 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     goto do_default;
   case WM_CHAR: 
   {
-    WCHAR wstr;
+    WCHAR wstr = LOWORD(wParam);
+
+    switch (wstr)
+    {
+    case 3: /* Ctrl-C */
+      SendMessageW(editor->hWnd, WM_COPY, 0, 0);
+      return 0;
+    }
+    
     if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_READONLY) {
       MessageBeep(MB_ICONERROR);
       return 0; /* FIXME really 0 ? */
     }
-    wstr = LOWORD(wParam);
+
+    switch (wstr)
+    {
+    case 1: /* Ctrl-A */
+      ME_SetSelection(editor, 0, -1);
+      return 0;
+    case 22: /* Ctrl-V */
+      SendMessageW(editor->hWnd, WM_PASTE, 0, 0);
+      return 0;
+    case 24: /* Ctrl-X */
+      SendMessageW(editor->hWnd, WM_CUT, 0, 0);
+      return 0;
+    case 25: /* Ctrl-Y */
+      SendMessageW(editor->hWnd, EM_REDO, 0, 0);
+      return 0;
+    case 26: /* Ctrl-Z */
+      SendMessageW(editor->hWnd, EM_UNDO, 0, 0);
+      return 0;
+    }
     if (((unsigned)wstr)>=' ' || wstr=='\r' || wstr=='\t') {
       /* FIXME maybe it would make sense to call EM_REPLACESEL instead ? */
       ME_Style *style = ME_GetInsertStyle(editor, 0);
@@ -1714,10 +1849,13 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
       break;
     }
     if (nPos != editor->nScrollPosY) {
-      ScrollWindow(hWnd, 0, editor->nScrollPosY-nPos, NULL, NULL);
+      if (editor->bRedraw)
+      {
+        ScrollWindow(hWnd, 0, editor->nScrollPosY-nPos, NULL, NULL);
+        SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
+        UpdateWindow(hWnd);
+      }
       editor->nScrollPosY = nPos;
-      SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
-      UpdateWindow(hWnd);
     }
     break;
   }
@@ -1734,15 +1872,54 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
     if (nPos<0)
       nPos = 0;
     if (nPos != editor->nScrollPosY) {
-      ScrollWindow(hWnd, 0, editor->nScrollPosY-nPos, NULL, NULL);
+      if (editor->bRedraw)
+      {
+        ScrollWindow(hWnd, 0, editor->nScrollPosY-nPos, NULL, NULL);
+        SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
+        UpdateWindow(hWnd);
+      }
       editor->nScrollPosY = nPos;
-      SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
-      UpdateWindow(hWnd);
     }
     break;
   }
+  case EM_GETRECT:
+  {
+    *((RECT *)lParam) = editor->rcFormat;
+    return 0;
+  }
+  case EM_SETRECT:
+  case EM_SETRECTNP:
+  {
+    if (lParam)
+    {
+      RECT *rc = (RECT *)lParam;
+      
+      if (wParam)
+      {
+        editor->rcFormat.left += rc->left;
+        editor->rcFormat.top += rc->top;
+        editor->rcFormat.right += rc->right;
+        editor->rcFormat.bottom += rc->bottom;
+      }
+      else
+      {
+        editor->rcFormat = *rc;
+      }
+    }
+    else
+    {
+      GetClientRect(hWnd, &editor->rcFormat);
+    }
+    if (msg != EM_SETRECTNP)
+      ME_RewrapRepaint(editor);
+    return 0;
+  }
+  case WM_SETREDRAW:
+    editor->bRedraw = wParam;
+    return 0;
   case WM_SIZE:
   {
+    GetClientRect(hWnd, &editor->rcFormat);
     ME_RewrapRepaint(editor);
     return DefWindowProcW(hWnd, msg, wParam, lParam);
   }
@@ -1836,11 +2013,12 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in
       
     if (item->member.run.nFlags & MERF_ENDPARA)
     {
-      if (bCRLF) {
-        *buffer++ = '\r';
+      *buffer++ = '\r';
+      if (bCRLF)
+      {
+        *buffer = '\n';
         nWritten++;
-      }        
-      *buffer = '\n';
+      }
       assert(nLen == 1);
     }
     else      
index 9f5f6bd..b168d01 100644 (file)
@@ -141,6 +141,7 @@ void ME_HideCaret(ME_TextEditor *ed);
 void ME_ShowCaret(ME_TextEditor *ed);
 void ME_MoveCaret(ME_TextEditor *ed);
 int ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *result, BOOL *is_eol);
+int ME_CharFromPos(ME_TextEditor *editor, int x, int y);
 void ME_LButtonDown(ME_TextEditor *editor, int x, int y);
 void ME_MouseMove(ME_TextEditor *editor, int x, int y);
 void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars);
index b6df587..39de7e1 100644 (file)
@@ -270,6 +270,8 @@ typedef struct tagME_TextEditor
   BOOL bScrollX, bScrollY;
   int nScrollPosY;
   int nZoomNumerator, nZoomDenominator;
+  RECT rcFormat;
+  BOOL bRedraw;
 } ME_TextEditor;
 
 typedef struct tagME_Context
index 7b734af..c60b50d 100644 (file)
@@ -154,12 +154,15 @@ void ME_Repaint(ME_TextEditor *editor)
   if (ME_WrapMarkedParagraphs(editor)) {
     ME_UpdateScrollBar(editor);
   }
-  hDC = GetDC(editor->hWnd);
-  ME_HideCaret(editor);
-  ME_PaintContent(editor, hDC, TRUE, NULL);
-  ReleaseDC(editor->hWnd, hDC);
-  ME_ShowCaret(editor);
-  ME_EnsureVisible(editor, pCursor->pRun);
+  if (editor->bRedraw)
+  {
+    hDC = GetDC(editor->hWnd);
+    ME_HideCaret(editor);
+    ME_PaintContent(editor, hDC, TRUE, NULL);
+    ReleaseDC(editor->hWnd, hDC);
+    ME_ShowCaret(editor);
+    ME_EnsureVisible(editor, pCursor->pRun);
+  }
 }
 
 void ME_UpdateRepaint(ME_TextEditor *editor)
@@ -415,10 +418,13 @@ void ME_Scroll(ME_TextEditor *editor, int cx, int cy)
   GetScrollInfo(hWnd, SB_VERT, &si);
   si.nPos = editor->nScrollPosY -= cy;
   SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
-  if (abs(cy) > editor->sizeWindow.cy)
-    InvalidateRect(editor->hWnd, NULL, TRUE);
-  else
-    ScrollWindowEx(hWnd, cx, cy, NULL, NULL, NULL, NULL, SW_ERASE|SW_INVALIDATE);
+  if (editor->bRedraw)
+  {
+    if (abs(cy) > editor->sizeWindow.cy)
+      InvalidateRect(editor->hWnd, NULL, TRUE);
+    else
+      ScrollWindowEx(hWnd, cx, cy, NULL, NULL, NULL, NULL, SW_ERASE|SW_INVALIDATE);
+  }
 }
 
 void ME_UpdateScrollBar(ME_TextEditor *editor)
@@ -495,14 +501,20 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
   if (yrel < 0) {
     editor->nScrollPosY = y;
     SetScrollPos(hWnd, SB_VERT, y, TRUE);
-    ScrollWindow(hWnd, 0, -yrel, NULL, NULL);
-    UpdateWindow(hWnd);
+    if (editor->bRedraw)
+    {
+      ScrollWindow(hWnd, 0, -yrel, NULL, NULL);
+      UpdateWindow(hWnd);
+    }
   } else if (yrel + yheight > editor->sizeWindow.cy) {
     int newy = y+yheight-editor->sizeWindow.cy;
     editor->nScrollPosY = newy;
     SetScrollPos(hWnd, SB_VERT, newy, TRUE);
-    ScrollWindow(hWnd, 0, -(newy-yold), NULL, NULL);
-    UpdateWindow(hWnd);
+    if (editor->bRedraw)
+    {
+      ScrollWindow(hWnd, 0, -(newy-yold), NULL, NULL);
+      UpdateWindow(hWnd);
+    }
   }
 }
         
index caecb52..25805c2 100644 (file)
@@ -257,6 +257,7 @@ void RTFInit(RTF_Info *info)
         info->ansiCodePage = 1252; /* Latin-1; actually unused */
        info->unicodeLength = 1; /* \uc1 is the default */
        info->codePage = info->ansiCodePage;
+        info->defFont = 0;
 
        info->rtfClass = -1;
        info->pushedClass = -1;
@@ -1005,6 +1006,14 @@ static void ReadFontTbl(RTF_Info *info)
                        if (!RTFCheckCM (info, rtfGroup, rtfEndGroup))
                                RTFPanic (info, "%s: missing \"}\"", fn);
                }
+
+                /* Apply the real properties of the default font */
+                if (fp->rtfFNum == info->defFont)
+                {
+                        if (info->ansiCodePage != CP_UTF8)
+                                info->codePage = fp->rtfFCodePage;
+                        TRACE("default font codepage %d\n", info->codePage);
+                }
        }
        if (fp->rtfFNum == -1)
                RTFPanic (info,"%s: missing font number", fn);
@@ -1012,6 +1021,14 @@ static void ReadFontTbl(RTF_Info *info)
  * Could check other pieces of structure here, too, I suppose.
  */
        RTFRouteToken (info);   /* feed "}" back to router */
+
+        /* Set default font */
+       info->rtfClass = rtfControl;
+       info->rtfMajor = rtfCharAttr;
+       info->rtfMinor = rtfFontNum;
+       info->rtfParam = info->defFont;
+       lstrcpyA(info->rtfTextBuf, "f");
+        RTFUngetToken(info);
 }
 
 
@@ -2467,6 +2484,7 @@ void RTFPanic(RTF_Info *info, const char *fmt, ...)
 
 static void    TextClass (RTF_Info *info);
 static void    ControlClass (RTF_Info *info);
+static void     DefFont(RTF_Info *info);
 static void    Destination (RTF_Info *info);
 static void    SpecialChar (RTF_Info *info);
 static void    RTFPutUnicodeChar (RTF_Info *info, int c);
@@ -2516,6 +2534,9 @@ ControlClass (RTF_Info *info)
         case rtfCharSet:
                 CharSet(info);
                 break;
+        case rtfDefFont:
+                DefFont(info);
+                break;
        case rtfDestination:
                Destination (info);
                break;
@@ -2542,6 +2563,7 @@ CharAttr(RTF_Info *info)
                 {
                         if (info->ansiCodePage != CP_UTF8)
                                 info->codePage = font->rtfFCodePage;
+                        TRACE("font %d codepage %d\n", info->rtfParam, info->codePage);
                 }
                 else
                         RTFMsg(info, "unknown font %d\n", info->rtfParam);
@@ -2556,6 +2578,9 @@ CharAttr(RTF_Info *info)
 static void
 CharSet(RTF_Info *info)
 {
+       if (info->ansiCodePage == CP_UTF8)
+               return;
         switch (info->rtfMinor)
         {
         case rtfAnsiCharSet:
@@ -2588,16 +2613,26 @@ Destination (RTF_Info *info)
 }
 
 
+static void
+DefFont(RTF_Info *info)
+{
+        TRACE("%d\n", info->rtfParam);
+        info->defFont = info->rtfParam;
+}
+
+
 static void
 DocAttr(RTF_Info *info)
 {
+        TRACE("minor %d, param %d\n", info->rtfMinor, info->rtfParam);
+
         switch (info->rtfMinor)
         {
         case rtfAnsiCodePage:
-                info->ansiCodePage = info->rtfParam;
+                info->codePage = info->ansiCodePage = info->rtfParam;
                 break;
         case rtfUTF8RTF:
-                info->ansiCodePage = CP_UTF8;
+                info->codePage = info->ansiCodePage = CP_UTF8;
                 break;
         }
 }
@@ -2704,10 +2739,9 @@ RTFPutUnicodeString(RTF_Info *info, WCHAR *string, int length)
                 int fit = min(length, sizeof(info->OutputBuffer) / sizeof(WCHAR) - info->dwOutputCount);
 
                 memmove(info->OutputBuffer + info->dwOutputCount, string, fit * sizeof(WCHAR));
+                info->dwOutputCount += fit;
                 if (fit == sizeof(info->OutputBuffer) / sizeof(WCHAR) - info->dwOutputCount)
                         RTFFlushUnicodeOutputBuffer(info);
-                else
-                        info->dwOutputCount += fit;
                 length -= fit;
                 string += fit;
         }
index 4f399a2..d457414 100644 (file)
@@ -37,7 +37,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 
 typedef struct IRichEditOleImpl {
     const IRichEditOleVtbl *lpVtbl;
-    DWORD ref;
+    LONG ref;
 } IRichEditOleImpl;
 
 /* there is no way to be consistent across different sets of headers - mingw, Wine, Win32 SDK*/
index b803ed2..d7a6bd1 100644 (file)
@@ -116,10 +116,14 @@ ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs)
   }
   if (item)
   {
+    ME_DisplayItem *next_para = item->member.para.next_para;
+    
     nOfs -= item->member.para.nCharOfs;
     item = ME_FindItemFwd(item, diRun);
     while ((item = ME_FindItemFwd(item, diStartRowOrParagraph)) != NULL)
     {
+      if (item == next_para)
+        break;
       item = ME_FindItemFwd(item, diRun);
       if (item->member.run.nCharOfs > nOfs)
         break;
index 53ec6ee..d3720be 100644 (file)
@@ -1070,6 +1070,7 @@ struct _RTF_Info {
     RTFColor   *colorList;     /* initialized to NULL */
     RTFStyle   *styleList;
     int ansiCodePage; /* ANSI codepage used in conversion to Unicode */
+    int defFont;
 
     /* Character attributes */
     int unicodeLength; /* The length of ANSI representation of Unicode characters */
@@ -1103,6 +1104,7 @@ struct _RTF_Info {
 
     RTFState         stack[maxStack];
     int              stackTop;
+    BOOL             styleChanged;
 };
 
 
index a6aba95..11d55a8 100644 (file)
@@ -588,7 +588,7 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars)
             return FALSE;
           pos = i;
         }
-      if (!pos)
+      if (pos < nBytes)
         if (!ME_StreamOutMove(editor, buffer + pos, nBytes - pos))
           return FALSE;
       pos = 0;
@@ -681,6 +681,8 @@ ME_StreamOutRTF(ME_TextEditor *editor, int nStart, int nChars, int dwFormat)
           if (!ME_StreamOutPrint(editor, "\r\n\\par"))
             return FALSE;
           nChars--;
+          if (editor->bEmulateVersion10 && nChars)
+            nChars--;
         } else {
           int nEnd;
           
@@ -790,7 +792,12 @@ ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream)
     nTo = -1;
   }
   if (nTo == -1)
+  {
     nTo = ME_GetTextLength(editor);
+    /* Generate an end-of-paragraph at the end of SCF_ALL RTF output */
+    if (dwFormat & SF_RTF)
+      nTo++;
+  }
   TRACE("from %d to %d\n", nStart, nTo);
   
   if (dwFormat & SF_RTF)
index 5a1a5fe..c8ca83f 100644 (file)
@@ -296,6 +296,7 @@ extern "C" {
 #define TM_MULTICODEPAGE       32
 #define GT_DEFAULT     0
 #define GT_USECRLF     1
+#define GT_SELECTION   2
 #define yHeightCharPtsMost 1638
 #define lDefaultTab 720