riched20: refactor some code out of WndProc

Krzysztof Foltman wdev at foltman.com
Fri Aug 4 15:37:00 CDT 2006


Usual suspects and regression tests still work, so I assume I didn't 
break anything.

I've changed EM_SETTEXTMODE implementation status from - to +, because 
it is handled, although in a very limited way so far.

Krzysztof

-------------- next part --------------
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 58789de..1b7d240 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -115,7 +115,7 @@
   - EM_SETTABSTOPS 3.0
   - EM_SETTARGETDEVICE
   + EM_SETTEXTEX 3.0 (unicode only, no rich text insertion handling, proper style?)
-  - EM_SETTEXTMODE 2.0
+  + EM_SETTEXTMODE 2.0
   - EM_SETTYPOGRAPHYOPTIONS 3.0
   + EM_SETUNDOLIMIT 2.0
   + EM_SETWORDBREAKPROC (used only for word movement at the moment)
@@ -1389,11 +1389,246 @@ get_msg_name(UINT msg)
   return "";
 }
 
+static LRESULT
+ME_EM_SetTextMode(ME_TextEditor *editor, UINT mode) 
+{
+  LRESULT ret = ME_GetTextLength(editor);
+  int mask = 0;
+  int changes = 0;
+  if (ret == 0)
+  {
+    /*Check for contradictory flags*/
+    if ((((mode & TM_RICHTEXT) && ((mode & TM_PLAINTEXT) << 1))) ||
+        (((mode & TM_MULTILEVELUNDO) && ((mode & TM_SINGLELEVELUNDO) << 1))) ||
+        (((mode & TM_MULTICODEPAGE) && ((mode & TM_SINGLECODEPAGE) << 1))))
+      return 1;
+    else
+    {
+      if (mode & (TM_RICHTEXT | TM_PLAINTEXT))
+      {
+        mask |= (TM_RICHTEXT | TM_PLAINTEXT);
+        changes |= (mode & (TM_RICHTEXT | TM_PLAINTEXT));
+      }
+      /*FIXME: Currently no support for undo level and code page options*/ 
+      editor->mode = (editor->mode & (~mask)) | changes;
+      return 0;
+    }
+  }
+  return ret;
+}
+
+static LRESULT
+ME_EM_Scroll(ME_TextEditor *editor, SHORT nScrollOp) 
+{
+  SCROLLINFO si;
+  int nEnd;
+  int nPos = editor->nScrollPosY;
+  int origNPos = nPos;
+  int lineHeight = 24;
+  HWND hWnd = editor->hWnd;
+  si.cbSize = sizeof(SCROLLINFO);
+  si.fMask = SIF_PAGE|SIF_POS|SIF_RANGE|SIF_TRACKPOS;
+  GetScrollInfo(hWnd, SB_VERT, &si);
+  if (editor && editor->pBuffer && editor->pBuffer->pDefaultStyle)
+      lineHeight = editor->pBuffer->pDefaultStyle->tm.tmHeight;
+  if (lineHeight <= 0) lineHeight = 24;
+  switch(nScrollOp) {
+  case SB_LINEUP:
+    nPos -= lineHeight;
+    if (nPos<0) nPos = 0;
+    break;
+  case SB_LINEDOWN:
+  {
+    nEnd = editor->nTotalLength - editor->sizeWindow.cy;
+    if (nEnd < 0) nEnd = 0;
+    nPos += lineHeight;
+    if (nPos>=nEnd) nPos = nEnd;
+    break;
+  }
+  case SB_PAGEUP:
+    nPos -= editor->sizeWindow.cy;
+    if (nPos<0) nPos = 0;
+    break;
+  case SB_PAGEDOWN:
+    nEnd = editor->nTotalLength - editor->sizeWindow.cy;
+    if (nEnd < 0) nEnd = 0;
+    nPos += editor->sizeWindow.cy;
+    if (nPos>=nEnd) nPos = nEnd;
+    break;
+  case SB_THUMBTRACK:
+  case SB_THUMBPOSITION:
+    nPos = si.nTrackPos;
+    break;
+  }
+  if (nPos != editor->nScrollPosY) {
+    int dy = editor->nScrollPosY - nPos;
+    editor->nScrollPosY = nPos;
+    SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
+    if (editor->bRedraw)
+    {
+      ScrollWindow(hWnd, 0, dy, NULL, NULL);
+      UpdateWindow(hWnd);
+    }
+  }
+  return 0x00010000 | (((nPos - origNPos)/lineHeight) & 0xffff);
+}
+
+static LRESULT
+ME_EM_SetOptions(ME_TextEditor *editor, UINT op, UINT changes) 
+{
+  /* these flags are equivalent to ES_* counterparts                      
+   * ECO_READONLY is already implemented in the code, only requires 
+   * setting the bit to work                                        
+   */
+  DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
+               ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN;
+  DWORD raw = GetWindowLongW(editor->hWnd, GWL_STYLE);
+  DWORD settings = mask & raw;
+
+  switch(op)
+  {
+    case ECOOP_SET:
+      settings = changes;
+      break;
+    case ECOOP_OR:
+      settings |= changes;
+      break;
+    case ECOOP_AND:
+      settings &= changes;
+      break;
+    case ECOOP_XOR:
+      settings ^= changes;
+  }
+  SetWindowLongW(editor->hWnd, GWL_STYLE, (raw & ~mask) | (settings & mask));
+
+  if (changes & ECO_AUTOWORDSELECTION)
+    FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n");
+  if (changes & ECO_SELECTIONBAR)
+    FIXME("ECO_SELECTIONBAR not implemented yet!\n");
+  if (changes & ECO_VERTICAL)
+    FIXME("ECO_VERTICAL not implemented yet!\n");
+  if (changes & ECO_AUTOHSCROLL)
+    FIXME("ECO_AUTOHSCROLL not implemented yet!\n");
+  if (changes & ECO_AUTOVSCROLL)
+    FIXME("ECO_AUTOVSCROLL not implemented yet!\n");
+  if (changes & ECO_NOHIDESEL)
+    FIXME("ECO_NOHIDESEL not implemented yet!\n");
+  if (changes & ECO_WANTRETURN)
+    FIXME("ECO_WANTRETURN not implemented yet!\n");
+
+  return settings;
+}
+
+
+static LRESULT
+ME_EM_SetTextEx(ME_TextEditor *editor, SETTEXTEX *pStruct, LPWSTR wszText) 
+{
+  size_t len = lstrlenW(wszText);
+  int from, to;
+  ME_Style *style;
+  TRACE("EM_SETTEXEX - %s, flags %d, cp %d\n", debugstr_w(wszText), (int)pStruct->flags, pStruct->codepage);
+  if (pStruct->codepage != 1200) {
+    FIXME("EM_SETTEXTEX only supports unicode right now!\n"); 
+    return 0;
+  }
+  /* FIXME: this should support RTF strings too, according to MSDN */
+  if (pStruct->flags & ST_SELECTION) {
+    ME_GetSelection(editor, &from, &to);
+    style = ME_GetSelectionInsertStyle(editor);
+    ME_InternalDeleteText(editor, from, to - from);
+    ME_InsertTextFromCursor(editor, 0, wszText, len, style);
+    ME_ReleaseStyle(style);
+  }
+  else {
+    ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
+    ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);
+    len = 1;
+  }
+  ME_CommitUndo(editor);
+  if (!(pStruct->flags & ST_KEEPUNDO))
+    ME_EmptyUndoStack(editor);
+  ME_UpdateRepaint(editor);
+  return len;
+}
+
+static LRESULT
+ME_EM_SetBackgroundColor(ME_TextEditor *editor, BOOL fUseWindowColor, COLORREF rgbColor) 
+{
+  HWND hWnd = editor->hWnd;
+  LRESULT lColor = ME_GetBackColor(editor);
+  if (editor->rgbBackColor != -1)
+    DeleteObject(editor->hbrBackground);
+  if (fUseWindowColor)
+  {
+    editor->rgbBackColor = -1;
+    editor->hbrBackground = GetSysColorBrush(COLOR_WINDOW);
+  }
+  else
+  {
+    editor->rgbBackColor = rgbColor;
+    editor->hbrBackground = CreateSolidBrush(editor->rgbBackColor);
+  }
+  if (editor->bRedraw)
+  {
+    InvalidateRect(hWnd, NULL, TRUE);
+    UpdateWindow(hWnd);
+  }
+  return lColor;
+}
+
+static LRESULT
+ME_EM_ReplaceSel(ME_TextEditor *editor, BOOL fKeepUndo, LPVOID pData)
+{
+  int from, to;
+  ME_Style *style;
+  LPWSTR wszText = ME_ToUnicode(editor->hWnd, pData);
+  size_t len = lstrlenW(wszText);
+  TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText));
+  
+  ME_GetSelection(editor, &from, &to);
+  style = ME_GetSelectionInsertStyle(editor);
+  ME_InternalDeleteText(editor, from, to-from);
+  ME_InsertTextFromCursor(editor, 0, wszText, len, style);
+  ME_ReleaseStyle(style);
+  ME_EndToUnicode(editor->hWnd, wszText);
+  /* drop temporary style if line end */
+  /* FIXME question: does abc\n mean: put abc, clear temp style, put \n? (would require a change) */  
+  if (len>0 && wszText[len-1] == '\n')
+    ME_ClearTempStyle(editor);
+    
+  ME_CommitUndo(editor);
+  if (!fKeepUndo)
+    ME_EmptyUndoStack(editor);
+  ME_UpdateRepaint(editor);
+  return 0;
+}
+
+static LRESULT
+ME_WM_SetFont(ME_TextEditor *editor, HGDIOBJ hFont, BOOL fRepaint)
+{
+  LOGFONTW lf;
+  CHARFORMAT2W fmt;
+  HDC hDC;
+  
+  if (!hFont)
+    hFont = GetStockObject(DEFAULT_GUI_FONT); 
+  GetObjectW(hFont, sizeof(LOGFONTW), &lf);
+  hDC = GetDC(editor->hWnd);
+  ME_CharFormatFromLogFont(hDC, &lf, &fmt); 
+  ReleaseDC(editor->hWnd, hDC);   
+  ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), &fmt);
+  ME_SetDefaultCharFormat(editor, &fmt);
+
+  ME_CommitUndo(editor);
+  if (fRepaint)
+    ME_UpdateRepaint(editor);
+  return 0;
+}
+
 /******************************************************************
  *        RichEditANSIWndProc (RICHED20.10)
  */
 LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
-  SCROLLINFO si;
   ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(hWnd, 0);
   
   TRACE("hWnd %p msg %04x (%s) %08x %08lx\n",
@@ -1513,49 +1748,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
     return settings;
   }
   case EM_SETOPTIONS:
-  {
-    /* these flags are equivalent to ES_* counterparts                      
-     * ECO_READONLY is already implemented in the code, only requires 
-     * setting the bit to work                                        
-     */
-    DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
-                 ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN;
-    DWORD raw = GetWindowLongW(hWnd, GWL_STYLE);
-    DWORD settings = mask & raw;
-
-    switch(wParam)
-    {
-      case ECOOP_SET:
-        settings = lParam;
-        break;
-      case ECOOP_OR:
-        settings |= lParam;
-        break;
-      case ECOOP_AND:
-        settings &= lParam;
-        break;
-      case ECOOP_XOR:
-        settings ^= lParam;
-    }
-    SetWindowLongW(hWnd, GWL_STYLE, (raw & ~mask) | (settings & mask));
-
-    if (lParam & ECO_AUTOWORDSELECTION)
-      FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n");
-    if (lParam & ECO_SELECTIONBAR)
-      FIXME("ECO_SELECTIONBAR not implemented yet!\n");
-    if (lParam & ECO_VERTICAL)
-      FIXME("ECO_VERTICAL not implemented yet!\n");
-    if (lParam & ECO_AUTOHSCROLL)
-      FIXME("ECO_AUTOHSCROLL not implemented yet!\n");
-    if (lParam & ECO_AUTOVSCROLL)
-      FIXME("ECO_AUTOVSCROLL not implemented yet!\n");
-    if (lParam & ECO_NOHIDESEL)
-      FIXME("ECO_NOHIDESEL not implemented yet!\n");
-    if (lParam & ECO_WANTRETURN)
-      FIXME("ECO_WANTRETURN not implemented yet!\n");
-
-    return settings;
-  }
+    return ME_EM_SetOptions(editor, wParam, lParam);
   case EM_SETSEL:
   {
     ME_InvalidateSelection(editor);
@@ -1588,58 +1781,9 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
     return 0;
   }
   case EM_SETTEXTEX:
-  {
-    LPWSTR wszText = (LPWSTR)lParam;
-    SETTEXTEX *pStruct = (SETTEXTEX *)wParam;
-    size_t len = lstrlenW(wszText);
-    int from, to;
-    ME_Style *style;
-    TRACE("EM_SETTEXEX - %s, flags %d, cp %d\n", debugstr_w(wszText), (int)pStruct->flags, pStruct->codepage);
-    if (pStruct->codepage != 1200) {
-      FIXME("EM_SETTEXTEX only supports unicode right now!\n"); 
-      return 0;
-    }
-    /* FIXME: this should support RTF strings too, according to MSDN */
-    if (pStruct->flags & ST_SELECTION) {
-      ME_GetSelection(editor, &from, &to);
-      style = ME_GetSelectionInsertStyle(editor);
-      ME_InternalDeleteText(editor, from, to - from);
-      ME_InsertTextFromCursor(editor, 0, wszText, len, style);
-      ME_ReleaseStyle(style);
-    }
-    else {
-      ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
-      ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);
-      len = 1;
-    }
-    ME_CommitUndo(editor);
-    if (!(pStruct->flags & ST_KEEPUNDO))
-      ME_EmptyUndoStack(editor);
-    ME_UpdateRepaint(editor);
-    return len;
-  }
+    return ME_EM_SetTextEx(editor, (SETTEXTEX *)wParam, (LPWSTR)lParam);  
   case EM_SETBKGNDCOLOR:
-  {
-    LRESULT lColor = ME_GetBackColor(editor);
-    if (editor->rgbBackColor != -1)
-      DeleteObject(editor->hbrBackground);
-    if (wParam)
-    {
-      editor->rgbBackColor = -1;
-      editor->hbrBackground = GetSysColorBrush(COLOR_WINDOW);
-    }
-    else
-    {
-      editor->rgbBackColor = lParam;
-      editor->hbrBackground = CreateSolidBrush(editor->rgbBackColor);
-    }
-    if (editor->bRedraw)
-    {
-      InvalidateRect(hWnd, NULL, TRUE);
-      UpdateWindow(hWnd);
-    }
-    return lColor;
-  }
+    return ME_EM_SetBackgroundColor(editor, wParam != 0, lParam);
   case EM_GETMODIFY:
     return editor->nModifyStep == 0 ? 0 : 1;
   case EM_SETMODIFY:
@@ -1717,29 +1861,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
     ME_GetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam);
     return 0;
   case EM_GETFIRSTVISIBLELINE:
-  {
-    ME_DisplayItem *p = editor->pBuffer->pFirst;
-    int y = editor->nScrollPosY;
-    int ypara = 0;
-    int count = 0;
-    int ystart, yend;
-    while(p) {
-      p = ME_FindItemFwd(p, diStartRowOrParagraphOrEnd);
-      if (p->type == diTextEnd)
-        break;
-      if (p->type == diParagraph) {
-        ypara = p->member.para.nYPos;
-        continue;
-      }
-      ystart = ypara + p->member.row.nYPos;
-      yend = ystart + p->member.row.nHeight;
-      if (y < yend) {
-        break;
-      }
-      count++;
-    }
-    return count;
-  }
+    return ME_GetFirstVisibleLine(editor);
   case EM_HIDESELECTION:
   {
      editor->bHideSelection = (wParam != 0);
@@ -1776,30 +1898,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
     return 0;
   }
   case EM_REPLACESEL:
-  {
-    int from, to;
-    ME_Style *style;
-    LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
-    size_t len = lstrlenW(wszText);
-    TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText));
-    
-    ME_GetSelection(editor, &from, &to);
-    style = ME_GetSelectionInsertStyle(editor);
-    ME_InternalDeleteText(editor, from, to-from);
-    ME_InsertTextFromCursor(editor, 0, wszText, len, style);
-    ME_ReleaseStyle(style);
-    ME_EndToUnicode(hWnd, wszText);
-    /* drop temporary style if line end */
-    /* FIXME question: does abc\n mean: put abc, clear temp style, put \n? (would require a change) */  
-    if (len>0 && wszText[len-1] == '\n')
-      ME_ClearTempStyle(editor);
-      
-    ME_CommitUndo(editor);
-    if (!wParam)
-      ME_EmptyUndoStack(editor);
-    ME_UpdateRepaint(editor);
-    return 0;
-  }
+    return ME_EM_ReplaceSel(editor, wParam, (void *)lParam); 
   case EM_SCROLLCARET:
   {
     int top, bottom; /* row's edges relative to document top */
@@ -1836,26 +1935,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
     return 0;
   }
   case WM_SETFONT:
-  {
-    LOGFONTW lf;
-    CHARFORMAT2W fmt;
-    HDC hDC;
-    BOOL bRepaint = LOWORD(lParam);
-    
-    if (!wParam)
-      wParam = (WPARAM)GetStockObject(DEFAULT_GUI_FONT); 
-    GetObjectW((HGDIOBJ)wParam, sizeof(LOGFONTW), &lf);
-    hDC = GetDC(hWnd);
-    ME_CharFormatFromLogFont(hDC, &lf, &fmt); 
-    ReleaseDC(hWnd, hDC);   
-    ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), &fmt);
-    ME_SetDefaultCharFormat(editor, &fmt);
-
-    ME_CommitUndo(editor);
-    if (bRepaint)
-      ME_UpdateRepaint(editor);
-    return 0;
-  }
+    return ME_WM_SetFont(editor, (HGDIOBJ)wParam, LOWORD(lParam)); 
   case WM_SETTEXT:
   {
     ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
@@ -2340,61 +2420,11 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
     }
     return 0;
   }
-  case EM_SCROLL: /* fall through */
-  case WM_VSCROLL: 
-  {
-    int nEnd;
-    int nPos = editor->nScrollPosY;
-    int origNPos = nPos;
-    int lineHeight = 24;
-    si.cbSize = sizeof(SCROLLINFO);
-    si.fMask = SIF_PAGE|SIF_POS|SIF_RANGE|SIF_TRACKPOS;
-    GetScrollInfo(hWnd, SB_VERT, &si);
-    if (editor && editor->pBuffer && editor->pBuffer->pDefaultStyle)
-        lineHeight = editor->pBuffer->pDefaultStyle->tm.tmHeight;
-    if (lineHeight <= 0) lineHeight = 24;
-    switch(LOWORD(wParam)) {
-    case SB_LINEUP:
-      nPos -= lineHeight;
-      if (nPos<0) nPos = 0;
-      break;
-    case SB_LINEDOWN:
-    {
-      nEnd = editor->nTotalLength - editor->sizeWindow.cy;
-      if (nEnd < 0) nEnd = 0;
-      nPos += lineHeight;
-      if (nPos>=nEnd) nPos = nEnd;
-      break;
-    }
-    case SB_PAGEUP:
-      nPos -= editor->sizeWindow.cy;
-      if (nPos<0) nPos = 0;
-      break;
-    case SB_PAGEDOWN:
-      nEnd = editor->nTotalLength - editor->sizeWindow.cy;
-      if (nEnd < 0) nEnd = 0;
-      nPos += editor->sizeWindow.cy;
-      if (nPos>=nEnd) nPos = nEnd;
-      break;
-    case SB_THUMBTRACK:
-    case SB_THUMBPOSITION:
-      nPos = si.nTrackPos;
-      break;
-    }
-    if (nPos != editor->nScrollPosY) {
-      int dy = editor->nScrollPosY - nPos;
-      editor->nScrollPosY = nPos;
-      SetScrollPos(hWnd, SB_VERT, nPos, TRUE);
-      if (editor->bRedraw)
-      {
-        ScrollWindow(hWnd, 0, dy, NULL, NULL);
-        UpdateWindow(hWnd);
-      }
-    }
-    if (msg == EM_SCROLL)
-      return 0x00010000 | (((nPos - origNPos)/lineHeight) & 0xffff);
-    break;
-  }
+  case EM_SCROLL:
+    return ME_EM_Scroll(editor, LOWORD(wParam));  
+  case WM_VSCROLL:
+    ME_EM_Scroll(editor, LOWORD(wParam));
+    return 0;  
   case WM_MOUSEWHEEL:
   {
     int gcWheelDelta = 0, nPos = editor->nScrollPosY, nEnd = editor->nTotalLength - editor->sizeWindow.cy; 
@@ -2485,31 +2515,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND 
     return (LRESULT)pfnOld;
   }
   case EM_SETTEXTMODE:
-  {
-    LRESULT ret;
-    int mask = 0;
-    int changes = 0;
-    if ((ret = RichEditANSIWndProc(hWnd, WM_GETTEXTLENGTH, 0, 0)) == 0)
-    {
-      /*Check for valid wParam*/
-      if ((((wParam & TM_RICHTEXT) && ((wParam & TM_PLAINTEXT) << 1))) ||
-	  (((wParam & TM_MULTILEVELUNDO) && ((wParam & TM_SINGLELEVELUNDO) << 1))) ||
-	  (((wParam & TM_MULTICODEPAGE) && ((wParam & TM_SINGLECODEPAGE) << 1))))
-	return 1;
-      else
-      {
-	if (wParam & (TM_RICHTEXT | TM_PLAINTEXT))
-	{
-	  mask |= (TM_RICHTEXT | TM_PLAINTEXT);
-	  changes |= (wParam & (TM_RICHTEXT | TM_PLAINTEXT));
-	}
-	/*FIXME: Currently no support for undo level and code page options*/ 
-	editor->mode = (editor->mode & (~mask)) | changes;
-	return 0;
-      }
-    }
-    return ret;
-  }      
+    return ME_EM_SetTextMode(editor, wParam);
   default:
   do_default:
     return DefWindowProcW(hWnd, msg, wParam, lParam);
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index a4d4980..752852a 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -123,6 +123,7 @@ ME_DisplayItem *ME_RowStart(ME_DisplayIt
 void ME_RenumberParagraphs(ME_DisplayItem *item); /* TODO */
 ME_DisplayItem *ME_FindRowWithNumber(ME_TextEditor *editor, int nRow);
 int ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs);
+int ME_GetFirstVisibleLine(ME_TextEditor *editor);
 
 /* run.c */
 ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags);
diff --git a/dlls/riched20/row.c b/dlls/riched20/row.c
index 549b3cb..f0d884a 100644
--- a/dlls/riched20/row.c
+++ b/dlls/riched20/row.c
@@ -133,3 +133,29 @@ ME_RowNumberFromCharOfs(ME_TextEditor *e
   }
   return nRow;
 }
+
+int
+ME_GetFirstVisibleLine(ME_TextEditor *editor)
+{
+  ME_DisplayItem *p = editor->pBuffer->pFirst;
+  int y = editor->nScrollPosY;
+  int ypara = 0;
+  int count = 0;
+  int ystart, yend;
+  while(p) {
+    p = ME_FindItemFwd(p, diStartRowOrParagraphOrEnd);
+    if (p->type == diTextEnd)
+      break;
+    if (p->type == diParagraph) {
+      ypara = p->member.para.nYPos;
+      continue;
+    }
+    ystart = ypara + p->member.row.nYPos;
+    yend = ystart + p->member.row.nHeight;
+    if (y < yend) {
+      break;
+    }
+    count++;
+  }
+  return count;
+}


More information about the wine-patches mailing list