RICHED20: tabs and indenting

Krzysztof Foltman wdev at foltman.com
Fri Apr 15 01:47:30 CDT 2005


ChangeLog:
  * removed trailing spaces from some files to avoid unnecessary diff's 
later (Alexandre will hate me for that :) )
  * tab support
  * indent support

Krzysztof
-------------- next part --------------
Index: dlls/riched20/caret.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/caret.c,v
retrieving revision 1.8
diff -u -r1.8 caret.c
--- dlls/riched20/caret.c	21 Mar 2005 10:27:24 -0000	1.8
+++ dlls/riched20/caret.c	15 Apr 2005 06:41:52 -0000
@@ -104,11 +104,11 @@
         {
           row = ME_FindItemBack(tmp, diStartRow);
           pSizeRun = run = tmp;
-          sz = ME_GetRunSize(&c, &run->member.run, ME_StrLen(run->member.run.strText));
+          sz = ME_GetRunSize(&c, &para->member.para, &run->member.run, ME_StrLen(run->member.run.strText));
         }
       }
       if (pCursor->nOffset && !(run->member.run.nFlags & MERF_SKIPPED)) {
-        sz = ME_GetRunSize(&c, &run->member.run, pCursor->nOffset);
+        sz = ME_GetRunSize(&c, &para->member.para, &run->member.run, pCursor->nOffset);
       }
       CreateCaret(editor->hWnd, NULL, 0, pSizeRun->member.run.nAscent+pSizeRun->member.run.nDescent);
       SetCaretPos(run->member.run.pt.x+sz.cx,
@@ -311,10 +311,30 @@
     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')
+  while(pos-str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
     pos++;
-  /* handle EOLs */
-  if (pos-str < len) {   
+  if (pos-str < len && *pos == '\t') { /* handle tabs */
+    ME_DisplayItem *pNewRun = NULL;
+    WCHAR tab = '\t';
+
+    if (pos!=str)
+      ME_InsertTextFromCursor(editor, nCursor, str, pos-str, style);
+    
+    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);
+    }
+    return;
+  }
+  if (pos-str < len) {   /* handle EOLs */
     ME_DisplayItem *tp, *end_run;
     ME_Paragraph *para;
     ME_Style *tmp_style;
Index: dlls/riched20/editor.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editor.c,v
retrieving revision 1.23
diff -u -r1.23 editor.c
--- dlls/riched20/editor.c	13 Apr 2005 11:11:03 -0000	1.23
+++ dlls/riched20/editor.c	15 Apr 2005 06:41:52 -0000
@@ -304,7 +304,7 @@
     case rtfStrikeThru:
       fmt.dwMask = CFM_STRIKEOUT;
       fmt.dwEffects = info->rtfParam ? fmt.dwMask : 0;
-      break;
+      break;
     case rtfBackColor:
       fmt.dwMask = CFM_BACKCOLOR;
       fmt.dwEffects = 0;
@@ -356,17 +356,41 @@
   }
 }
 
+/* FIXME this function doesn't get any information about context of the RTF tag, which is very bad,
+   the same tags mean different things in different contexts */
 void ME_RTFParAttrHook(RTF_Info *info)
 {
-  PARAFORMAT2 fmt;
+  PARAFORMAT2 fmt;
   fmt.cbSize = sizeof(fmt);
   fmt.dwMask = 0;
   
   switch(info->rtfMinor)
   {
   case rtfParDef: /* I'm not 100% sure what does it do, but I guess it restores default paragraph attributes */
-    fmt.dwMask = PFM_ALIGNMENT;
+    fmt.dwMask = PFM_ALIGNMENT | PFM_TABSTOPS | PFM_OFFSET | PFM_STARTINDENT;
     fmt.wAlignment = PFA_LEFT;
+    fmt.cTabCount = 0;
+    fmt.dxOffset = fmt.dxStartIndent = 0;
+    break;
+  case rtfFirstIndent:
+    ME_GetSelectionParaFormat(info->editor, &fmt);
+    fmt.dwMask = PFM_STARTINDENT;
+    fmt.dxStartIndent = info->rtfParam + fmt.dxOffset;
+    break;
+  case rtfLeftIndent:
+  {
+    int first, left;
+    ME_GetSelectionParaFormat(info->editor, &fmt);
+    first = fmt.dxStartIndent;
+    left = info->rtfParam;
+    fmt.dwMask = PFM_STARTINDENT|PFM_OFFSET;
+    fmt.dxStartIndent = first + left;
+    fmt.dxOffset = -first;
+    break;
+  }
+  case rtfRightIndent:
+    fmt.dwMask = PFM_RIGHTINDENT;
+    fmt.dxRightIndent = info->rtfParam;
     break;
   case rtfQuadLeft:
   case rtfQuadJust:
@@ -381,6 +405,16 @@
     fmt.dwMask = PFM_ALIGNMENT;
     fmt.wAlignment = PFA_CENTER;
     break;
+  case rtfTabPos:
+    ME_GetSelectionParaFormat(info->editor, &fmt);
+    if (!(fmt.dwMask & PFM_TABSTOPS))
+    {
+      fmt.dwMask |= PFM_TABSTOPS;
+      fmt.cTabCount = 0;
+    }
+    if (fmt.cTabCount < MAX_TAB_STOPS)
+      fmt.rgxTabs[fmt.cTabCount++] = info->rtfParam;
+    break;
   }  
   if (fmt.dwMask) {
     RTFFlushOutputBuffer(info);
@@ -1160,7 +1194,7 @@
       return 0; /* FIXME really 0 ? */
     }
     wstr = LOWORD(wParam);
-    if (((unsigned)wstr)>=' ' || wstr=='\r') {
+    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);
       ME_SaveTempStyle(editor);
Index: dlls/riched20/paint.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/paint.c,v
retrieving revision 1.8
diff -u -r1.8 paint.c
--- dlls/riched20/paint.c	21 Mar 2005 10:27:24 -0000	1.8
+++ dlls/riched20/paint.c	15 Apr 2005 06:41:52 -0000
@@ -251,7 +251,7 @@
   int runofs = run->nCharOfs+para->nCharOfs;
   
   /* you can always comment it out if you need visible paragraph marks */
-  if (run->nFlags & MERF_ENDPARA) 
+  if (run->nFlags & (MERF_ENDPARA|MERF_TAB)) 
     return;
   if (run->nFlags & MERF_GRAPHICS) {
     int blfrom, blto;
@@ -311,19 +311,19 @@
         visible = RectVisible(c->hDC, &rcPara);
         if (visible) {
           HBRUSH hbr;
+          hbr = CreateSolidBrush(ME_GetBackColor(c->editor));
           /* left margin */
           rc.left = c->rcView.left;
           rc.right = c->rcView.left+nMargWidth;
           rc.top = y;
           rc.bottom = y+p->member.row.nHeight;
-          FillRect(c->hDC, &rc, c->hbrMargin);
+          FillRect(c->hDC, &rc, hbr/* c->hbrMargin */);
           /* right margin */
           rc.left = xe;
           rc.right = c->rcView.right;
-          FillRect(c->hDC, &rc, c->hbrMargin);
-          rc.left = c->rcView.left+para->nLeftMargin;
+          FillRect(c->hDC, &rc, hbr/* c->hbrMargin */);
+          rc.left = c->rcView.left+nMargWidth;
           rc.right = xe;
-          hbr = CreateSolidBrush(ME_GetBackColor(c->editor));
           FillRect(c->hDC, &rc, hbr);
           DeleteObject(hbr);
         }
Index: dlls/riched20/para.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/para.c,v
retrieving revision 1.3
diff -u -r1.3 para.c
--- dlls/riched20/para.c	17 Mar 2005 10:23:40 -0000	1.3
+++ dlls/riched20/para.c	15 Apr 2005 06:41:52 -0000
@@ -57,7 +57,7 @@
   
   ZeroMemory(&fmt, sizeof(fmt));
   fmt.cbSize = sizeof(fmt);
-  fmt.dwMask = PFM_ALIGNMENT | PFM_OFFSET | PFM_STARTINDENT | PFM_RIGHTINDENT;
+  fmt.dwMask = PFM_ALIGNMENT | PFM_OFFSET | PFM_STARTINDENT | PFM_RIGHTINDENT | PFM_TABSTOPS;
 
   CopyMemory(para->member.para.pFmt, &fmt, sizeof(PARAFORMAT2));
   
@@ -282,6 +282,18 @@
 
   if (pFmt->dwMask & PFM_ALIGNMENT)
     para->member.para.pFmt->wAlignment = pFmt->wAlignment;
+  if (pFmt->dwMask & PFM_STARTINDENT)
+    para->member.para.pFmt->dxStartIndent = pFmt->dxStartIndent;
+  if (pFmt->dwMask & PFM_OFFSET)
+    para->member.para.pFmt->dxOffset = pFmt->dxOffset;
+  if (pFmt->dwMask & PFM_OFFSETINDENT)
+    para->member.para.pFmt->dxStartIndent += pFmt->dxStartIndent;
+    
+  if (pFmt->dwMask & PFM_TABSTOPS)
+  {
+    para->member.para.pFmt->cTabCount = pFmt->cTabCount;
+    memcpy(para->member.para.pFmt->rgxTabs, pFmt->rgxTabs, pFmt->cTabCount*sizeof(int));
+  }
     
   /* FIXME to be continued (indents, bulleting and such) */
 
@@ -345,11 +357,28 @@
     ZeroMemory(&tmp, sizeof(tmp));
     tmp.cbSize = sizeof(tmp);
     ME_GetParaFormat(editor, para, &tmp);
-    assert(tmp.dwMask & PFM_ALIGNMENT);
     
+    assert(tmp.dwMask & PFM_ALIGNMENT);    
     if (pFmt->wAlignment != tmp.wAlignment)
       pFmt->dwMask &= ~PFM_ALIGNMENT;
     
+    assert(tmp.dwMask & PFM_STARTINDENT);
+    if (pFmt->dxStartIndent != tmp.dxStartIndent)
+      pFmt->dwMask &= ~PFM_STARTINDENT;
+    
+    assert(tmp.dwMask & PFM_OFFSET);
+    if (pFmt->dxOffset != tmp.dxOffset)
+      pFmt->dwMask &= ~PFM_OFFSET;
+    
+    assert(tmp.dwMask & PFM_TABSTOPS);    
+    if (pFmt->dwMask & PFM_TABSTOPS) {
+      if (pFmt->cTabCount != tmp.cTabCount)
+        pFmt->dwMask &= ~PFM_TABSTOPS;
+      else
+      if (memcmp(pFmt->rgxTabs, tmp.rgxTabs, tmp.cTabCount*sizeof(int)))
+        pFmt->dwMask &= ~PFM_TABSTOPS;
+    }
+    
     if (para == para_end)
       return;
     para = para->member.para.next_para;
Index: dlls/riched20/run.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/run.c,v
retrieving revision 1.7
diff -u -r1.7 run.c
--- dlls/riched20/run.c	19 Mar 2005 17:06:17 -0000	1.7
+++ dlls/riched20/run.c	15 Apr 2005 06:41:52 -0000
@@ -26,7 +26,7 @@
 
 int ME_CanJoinRuns(ME_Run *run1, ME_Run *run2)
 {
-  if ((run1->nFlags | run2->nFlags) & (MERF_ENDPARA | MERF_GRAPHICS))
+  if ((run1->nFlags | run2->nFlags) & MERF_NOJOIN)
     return 0;
   if (run1->style != run2->style)
     return 0;
@@ -91,8 +91,8 @@
         ofs = 0;
         break;
       case diRun:
-        TRACE("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = \"%s\", flags=%08x, fx&mask = %08lx\n", 
-          p->member.run.nCharOfs, p->member.run.nCharOfs+ofsp, ofsp+ofs, 
+        TRACE("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = \"%s\", flags=%08x, fx&mask = %08lx\n",
+          p->member.run.nCharOfs, p->member.run.nCharOfs+ofsp, ofsp+ofs,
           p->member.run.strText->nLen, debugstr_w(p->member.run.strText->szData),
           p->member.run.nFlags,
           p->member.run.style->fmt.dwMask & p->member.run.style->fmt.dwEffects);
@@ -108,14 +108,14 @@
 int ME_CharOfsFromRunOfs(ME_TextEditor *editor, ME_DisplayItem *pRun, int nOfs)
 {
   ME_DisplayItem *pPara;
-  
+
   assert(pRun->type == diRun);
   assert(pRun->member.run.nCharOfs != -1);
 
   pPara = ME_FindItemBack(pRun, diParagraph);
   assert(pPara);
   assert(pPara->type==diParagraph);
-  return pPara->member.para.nCharOfs + pRun->member.run.nCharOfs 
+  return pPara->member.para.nCharOfs + pRun->member.run.nCharOfs
     + ME_VPosToPos(pRun->member.run.strText, nOfs);
 }
 
@@ -128,7 +128,7 @@
 {
   ME_DisplayItem *pPara;
   int nParaOfs;
-  
+
   pPara = editor->pBuffer->pFirst->member.para.next_para;
   assert(pPara);
   assert(ppRun);
@@ -137,18 +137,18 @@
   {
     nParaOfs = pPara->member.para.nCharOfs;
     assert(nCharOfs >= nParaOfs);
-    
+
     if (nCharOfs < pPara->member.para.next_para->member.para.nCharOfs)
     {
       *ppRun = ME_FindItemFwd(pPara, diRun);
-      assert(*ppRun);      
+      assert(*ppRun);
       while (!((*ppRun)->member.run.nFlags & MERF_ENDPARA))
       {
         ME_DisplayItem *pNext = ME_FindItemFwd(*ppRun, diRun);
         assert(pNext);
         assert(pNext->type == diRun);
         if (nCharOfs < nParaOfs + pNext->member.run.nCharOfs) {
-          *pOfs = ME_PosToVPos((*ppRun)->member.run.strText, 
+          *pOfs = ME_PosToVPos((*ppRun)->member.run.strText,
             nCharOfs - nParaOfs - (*ppRun)->member.run.nCharOfs);
           return;
         }
@@ -157,12 +157,12 @@
       if (nCharOfs == nParaOfs + (*ppRun)->member.run.nCharOfs) {
         *pOfs = 0;
         return;
-      }        
+      }
     }
     pPara = pPara->member.para.next_para;
   }
   *ppRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
-  *pOfs = 0;  
+  *pOfs = 0;
   assert((*ppRun)->member.run.nFlags & MERF_ENDPARA);
 }
 
@@ -182,7 +182,7 @@
       editor->pCursors[i].nOffset += ME_StrVLen(p->member.run.strText);
     }
   }
-  
+
   ME_AppendString(p->member.run.strText, pNext->member.run.strText);
   ME_Remove(pNext);
   ME_DestroyDisplayItem(pNext);
@@ -200,7 +200,8 @@
   ME_TextEditor *editor = c->editor;
   ME_DisplayItem *item2 = NULL;
   ME_Run *run, *run2;
-  
+  ME_Paragraph *para = &ME_GetParagraph(item)->member.para;
+
   assert(item->member.run.nCharOfs != -1);
   if(TRACE_ON(richedit))
   {
@@ -215,28 +216,28 @@
         run->pt.x, run->pt.y);
 
   item2 = ME_SplitRunSimple(editor, item, nVChar);
-  
+
   run2 = &item2->member.run;
-  
-  ME_CalcRunExtent(c, run);
-  ME_CalcRunExtent(c, run2);
-    
+
+  ME_CalcRunExtent(c, para, run);
+  ME_CalcRunExtent(c, para, run2);
+
   run2->pt.x = run->pt.x+run->nWidth;
   run2->pt.y = run->pt.y;
-  
+
   if(TRACE_ON(richedit))
   {
     TRACE("Before check after split\n");
     ME_CheckCharOffsets(editor);
     TRACE("After check after split\n");
-    TRACE("After split: %s(%ld, %ld), %s(%ld, %ld)\n", 
+    TRACE("After split: %s(%ld, %ld), %s(%ld, %ld)\n",
       debugstr_w(run->strText->szData), run->pt.x, run->pt.y,
       debugstr_w(run2->strText->szData), run2->pt.x, run2->pt.y);
   }
 
   return item2;
 }
-  
+
 /* split a run starting from voffset */
 ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, int nVChar)
 {
@@ -246,22 +247,22 @@
   int i;
   assert(nVChar > 0 && nVChar < ME_StrVLen(run->strText));
   assert(item->type == diRun);
-  assert(!(item->member.run.nFlags & MERF_GRAPHICS));
+  assert(!(item->member.run.nFlags & (MERF_GRAPHICS | MERF_TAB)));
   assert(item->member.run.nCharOfs != -1);
 
-  item2 = ME_MakeRun(run->style, 
+  item2 = ME_MakeRun(run->style,
       ME_VSplitString(run->strText, nVChar), run->nFlags&MERF_SPLITMASK);
-  
+
   item2->member.run.nCharOfs = item->member.run.nCharOfs+
     ME_VPosToPos(item->member.run.strText, nVChar);
 
   run2 = &item2->member.run;
   ME_InsertBefore(item->next, item2);
-  
+
   ME_UpdateRunFlags(editor, run);
   ME_UpdateRunFlags(editor, run2);
   for (i=0; i<editor->nCursors; i++) {
-    if (editor->pCursors[i].pRun == item && 
+    if (editor->pCursors[i].pRun == item &&
         editor->pCursors[i].nOffset >= nVChar) {
       assert(item2->type == diRun);
       editor->pCursors[i].pRun = item2;
@@ -272,18 +273,6 @@
   return item2;
 }
 
-/* split the start and final whitespace into separate runs */
-/* returns the last run added */
-/*
-ME_DisplayItem *ME_SplitFurther(ME_TextEditor *editor, ME_DisplayItem *item)
-{
-  int i, nVLen, nChanged;
-  assert(item->type == diRun);
-  assert(!(item->member.run.nFlags & MERF_GRAPHICS));
-  return item;
-}
-*/
-
 ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags)
 {
   ME_DisplayItem *item = ME_MakeDI(diRun);
@@ -300,9 +289,9 @@
   ME_Cursor tmp;
   ME_DisplayItem *pDI;
   ME_UndoItem *pUI;
-  
+
   assert(pItem->type == diRun || pItem->type == diUndoInsertRun);
-  
+
   pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL);
   if (pUI) {
     pUI->nStart = nCharOfs;
@@ -319,7 +308,7 @@
   TRACE("Shift length:%d\n", pDI->member.run.strText->nLen);
   ME_PropagateCharOffset(tmp.pRun, pDI->member.run.strText->nLen);
   ME_GetParagraph(tmp.pRun)->member.para.nFlags |= MEPF_REWRAP;
-  
+
   return pDI;
 }
 
@@ -330,19 +319,19 @@
     run->nFlags |= MERF_SPLITTABLE;
   else
     run->nFlags &= ~MERF_SPLITTABLE;
-    
-  if (!(run->nFlags & MERF_GRAPHICS)) {
+
+  if (!(run->nFlags & MERF_NOTEXT)) {
     if (ME_IsWhitespaces(run->strText))
       run->nFlags |= MERF_WHITESPACE | MERF_STARTWHITE | MERF_ENDWHITE;
     else
     {
       run->nFlags &= ~MERF_WHITESPACE;
-    
+
       if (ME_IsWSpace(ME_GetCharFwd(run->strText,0)))
         run->nFlags |= MERF_STARTWHITE;
       else
         run->nFlags &= ~MERF_STARTWHITE;
-    
+
       if (ME_IsWSpace(ME_GetCharBack(run->strText,0)))
         run->nFlags |= MERF_ENDWHITE;
       else
@@ -360,7 +349,7 @@
   pSize->cy = 64;
 }
 
-int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run)
+int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Paragraph *para, ME_Run *run)
 {
   int fit = 0;
   HGDIOBJ hOldFont;
@@ -369,6 +358,12 @@
   if (!run->strText->nLen)
     return 0;
 
+  if (run->nFlags & MERF_TAB)
+  {
+    if (cx < run->nWidth/2)
+      return 0;
+    return 1;
+  }
   if (run->nFlags & MERF_GRAPHICS)
   {
     SIZE sz;
@@ -379,9 +374,9 @@
   }
   hDC = GetDC(editor->hWnd);
   hOldFont = ME_SelectStyleFont(editor, hDC, run->style);
-  GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen, 
+  GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
     cx, &fit, NULL, &sz);
-  ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);  
+  ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
   ReleaseDC(editor->hWnd, hDC);
   return fit;
 }
@@ -395,6 +390,12 @@
   if (!run->strText->nLen)
     return 0;
 
+  if (run->nFlags & MERF_TAB)
+  {
+    if (cx < run->nWidth/2)
+      return 0;
+    return 1;
+  }
   if (run->nFlags & MERF_GRAPHICS)
   {
     SIZE sz;
@@ -406,19 +407,19 @@
 
   hDC = GetDC(editor->hWnd);
   hOldFont = ME_SelectStyleFont(editor, hDC, run->style);
-  GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen, 
+  GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
     cx, &fit, NULL, &sz);
   if (fit != run->strText->nLen)
   {
     int chars = 1;
-    
+
     GetTextExtentPoint32W(hDC, run->strText->szData, fit, &sz2);
     fit1 = ME_StrRelPos(run->strText, fit, &chars);
     GetTextExtentPoint32W(hDC, run->strText->szData, fit1, &sz3);
     if (cx >= (sz2.cx+sz3.cx)/2)
       fit = fit1;
   }
-  ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);  
+  ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
   ReleaseDC(editor->hWnd, hDC);
   return fit;
 }
@@ -428,7 +429,7 @@
   SIZE size;
   HDC hDC = GetDC(editor->hWnd);
   HGDIOBJ hOldFont;
-  
+
   if (pRun->nFlags & MERF_GRAPHICS)
   {
     if (!nOffset) return 0;
@@ -437,56 +438,88 @@
   }
   hOldFont = ME_SelectStyleFont(editor, hDC, pRun->style);
   GetTextExtentPoint32W(hDC, pRun->strText->szData, nOffset, &size);
-  ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont);  
+  ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont);
   ReleaseDC(editor->hWnd, hDC);
   return size.cx;
 }
 
-void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, 
+void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s,
   SIZE *size)
 {
   HDC hDC = c->hDC;
   HGDIOBJ hOldFont;
   hOldFont = ME_SelectStyleFont(c->editor, hDC, s);
   GetTextExtentPoint32W(hDC, szText, nChars, size);
-  ME_UnselectStyleFont(c->editor, hDC, s, hOldFont);  
+  ME_UnselectStyleFont(c->editor, hDC, s, hOldFont);
 }
 
-SIZE ME_GetRunSize(ME_Context *c, ME_Run *run, int nLen)
+SIZE ME_GetRunSizeCommon(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLen, int *pAscent, int *pDescent)
 {
   SIZE size;
   int nMaxLen = ME_StrVLen(run->strText);
 
   if (nLen>nMaxLen)
     nLen = nMaxLen;
-    
+
+  /* FIXME the following call also ensures that TEXTMETRIC structure is filled
+   * this is wasteful for graphics and TAB runs, but that shouldn't matter
+   * in practice
+   */
+  ME_GetTextExtent(c, run->strText->szData, nLen, run->style, &size);
+  assert(run->style->tm.tmAscent>0);
+  assert(run->style->tm.tmDescent>0);
+  *pAscent = run->style->tm.tmAscent;
+  *pDescent = run->style->tm.tmDescent;
+  size.cy = *pAscent + *pDescent;
+
+  if (run->nFlags & MERF_TAB)
+  {
+    int pos = 0, i = 0, ppos;
+    int lpsx = GetDeviceCaps(c->hDC, LOGPIXELSX);
+    PARAFORMAT2 *pFmt = para->pFmt;
+    do {
+      if (i < pFmt->cTabCount)
+      {
+        pos = pFmt->rgxTabs[i]&0x00FFFFFF;
+        i++;
+      }
+      else
+      {
+        pos += 720-(pos%720);
+      }
+      ppos = pos*lpsx/1440;
+      if (ppos>run->pt.x) {
+        size.cx = ppos - run->pt.x;
+        break;
+      }
+    } while(1);
+    size.cy = *pAscent + *pDescent;
+    return size;
+  }
   if (run->nFlags & MERF_GRAPHICS)
   {
     ME_GetGraphicsSize(c->editor, run, &size);
+    if (size.cy > *pAscent)
+      *pAscent = size.cy;
+    /* descent is unchanged */
     return size;
   }
 
-  ME_GetTextExtent(c, run->strText->szData, nLen, run->style, &size);
-
   return size;
 }
 
-void ME_CalcRunExtent(ME_Context *c, ME_Run *run)
+SIZE ME_GetRunSize(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLen)
+{
+  int asc, desc;
+  return ME_GetRunSizeCommon(c, para, run, nLen, &asc, &desc);
+}
+
+void ME_CalcRunExtent(ME_Context *c, ME_Paragraph *para, ME_Run *run)
 {
-  SIZE size;
   int nEnd = ME_StrVLen(run->strText);
-  
-  if (run->nFlags & MERF_GRAPHICS) {
-    ME_GetGraphicsSize(c->editor, run, &size);
-    run->nWidth = size.cx;
-    run->nAscent = size.cy;
-    run->nDescent = 0;
-    return;
-  }
-  ME_GetTextExtent(c, run->strText->szData, nEnd, run->style, &size);
+  SIZE size = ME_GetRunSizeCommon(c, para, run, nEnd, &run->nAscent, &run->nDescent);
   run->nWidth = size.cx;
-  run->nAscent = run->style->tm.tmAscent;
-  run->nDescent = run->style->tm.tmDescent;
+  assert(size.cx);
 }
 
 void ME_MustBeWrapped(ME_Context *c, ME_DisplayItem *para)
@@ -516,7 +549,7 @@
 {
   ME_Cursor tmp, tmp2;
   ME_DisplayItem *para;
-  
+
   ME_CursorFromCharOfs(editor, nOfs, &tmp);
   if (tmp.nOffset)
     tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
@@ -527,7 +560,7 @@
 
   para = ME_GetParagraph(tmp.pRun);
   para->member.para.nFlags |= MEPF_REWRAP;
-    
+
   while(tmp.pRun != tmp2.pRun)
   {
     ME_UndoItem *undo = NULL;
@@ -558,9 +591,9 @@
 
 void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod)
 {
-  ME_Style *style; 
+  ME_Style *style;
   ME_UndoItem *undo;
-  
+
   assert(mod->cbSize == sizeof(CHARFORMAT2W));
   undo = ME_AddUndoItem(editor, diUndoSetDefaultCharFormat, NULL);
   if (undo) {
@@ -606,10 +639,10 @@
   ME_DisplayItem *run, *run_end;
   int nOffset, nOffset2;
   CHARFORMAT2W tmp;
-  
+
   if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */
     nTo--;
-  
+
   ME_RunOfsFromCharOfs(editor, nFrom, &run, &nOffset);
   if (nFrom == nTo) /* special case - if selection is empty, take previous char's formatting */
   {
@@ -625,22 +658,22 @@
     return;
   }
   ME_RunOfsFromCharOfs(editor, nTo, &run_end, &nOffset2);
-  
+
   ME_GetRunCharFormat(editor, run, pFmt);
-  
+
   if (run == run_end) return;
-  
+
   do {
     /* FIXME add more style feature comparisons */
     int nAttribs = CFM_SIZE | CFM_FACE | CFM_COLOR;
     int nEffects = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE;
 
     run = ME_FindItemFwd(run, diRun);
-    
+
     ZeroMemory(&tmp, sizeof(tmp));
     tmp.cbSize = sizeof(tmp);
     ME_GetRunCharFormat(editor, run, &tmp);
-    
+
     assert((tmp.dwMask & nAttribs) == nAttribs);
     assert((tmp.dwMask & nEffects) == nEffects);
     /* reset flags that differ */
@@ -664,8 +697,8 @@
           pFmt->dwMask &= ~CFM_COLOR;
       }
     }
-      
+
     pFmt->dwMask &= ~((pFmt->dwEffects ^ tmp.dwEffects) & nEffects);
-    
+
   } while(run != run_end);
 }
Index: dlls/riched20/style.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/style.c,v
retrieving revision 1.3
diff -u -r1.3 style.c
--- dlls/riched20/style.c	11 Mar 2005 10:24:56 -0000	1.3
+++ dlls/riched20/style.c	15 Apr 2005 06:41:52 -0000
@@ -124,6 +124,7 @@
   s->nSequence = -2;
   s->nRefs = 1;
   s->hFont = NULL;
+  s->tm.tmAscent = -1;
   all_refs++;
   return s;
 }
Index: dlls/riched20/wrap.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/wrap.c,v
retrieving revision 1.6
diff -u -r1.6 wrap.c
--- dlls/riched20/wrap.c	19 Mar 2005 17:06:17 -0000	1.6
+++ dlls/riched20/wrap.c	15 Apr 2005 06:41:52 -0000
@@ -26,16 +26,16 @@
 
 /*
  * Unsolved problems:
- *  
+ *
  * - center and right align in WordPad omits all spaces at the start, we don't
  * - objects/images are not handled yet
- * - no tabs 
- */ 
- 
+ * - no tabs
+ */
+
 ME_DisplayItem *ME_MakeRow(int height, int baseline, int width)
 {
   ME_DisplayItem *item = ME_MakeDI(diStartRow);
-  
+
   item->member.row.nHeight = height;
   item->member.row.nBaseline = baseline;
   item->member.row.nWidth = width;
@@ -49,7 +49,7 @@
   wc->pLastSplittableRun = NULL;
   wc->nAvailWidth = wc->nTotalWidth - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin;
   wc->pt.x = 0;
-}  
+}
 
 void ME_InsertRowStart(ME_WrapContext *wc, ME_DisplayItem *pEnd)
 {
@@ -95,7 +95,7 @@
 {
   if (wc->pRowStart)
     ME_InsertRowStart(wc, p->next);
-    
+
   /*
   p = p->member.para.prev_para->next;
   while(p) {
@@ -109,15 +109,15 @@
     p = p->next;
   }
   */
-}  
+}
 
 void ME_WrapSizeRun(ME_WrapContext *wc, ME_DisplayItem *p)
 {
   /* FIXME compose style (out of character and paragraph styles) here */
-  
+
   ME_UpdateRunFlags(wc->context->editor, &p->member.run);
-  
-  ME_CalcRunExtent(wc->context, &p->member.run);
+
+  ME_CalcRunExtent(wc->context, &ME_GetParagraph(p)->member.para, &p->member.run);
 }
 
 ME_DisplayItem *ME_MaximizeSplit(ME_WrapContext *wc, ME_DisplayItem *p, int i)
@@ -139,7 +139,7 @@
     while(piter != wc->pRowStart)
     {
       piter = ME_FindItemBack(piter, diRun);
-      if (piter->member.run.nFlags & MERF_WHITESPACE) 
+      if (piter->member.run.nFlags & MERF_WHITESPACE)
       {
         pp = piter;
         continue;
@@ -167,8 +167,8 @@
   ME_DisplayItem *piter = p, *pp;
   int i, idesp, len;
   ME_Run *run = &p->member.run;
-  
-  idesp = i = ME_CharFromPoint(wc->context->editor, loc, run);
+
+  idesp = i = ME_CharFromPoint(wc->context->editor, loc, &ME_GetParagraph(p)->member.para, run);
   len = ME_StrVLen(run->strText);
   assert(len>0);
   assert(i<len);
@@ -182,7 +182,7 @@
   TRACE("Must backtrack to split at: %s\n", debugstr_w(p->member.run.strText->szData));
   if (wc->pLastSplittableRun)
   {
-    if (wc->pLastSplittableRun->member.run.nFlags & MERF_GRAPHICS)
+    if (wc->pLastSplittableRun->member.run.nFlags & (MERF_GRAPHICS|MERF_TAB))
     {
       wc->pt = wc->ptLastSplittableRun;
       return wc->pLastSplittableRun;
@@ -193,7 +193,7 @@
          they serve no other purpose */
       ME_UpdateRunFlags(wc->context->editor, run);
       assert((wc->pLastSplittableRun->member.run.nFlags & MERF_SPLITTABLE));
-      
+
       piter = wc->pLastSplittableRun;
       run = &piter->member.run;
       len = ME_StrVLen(run->strText);
@@ -201,7 +201,7 @@
       i = ME_ReverseFindWhitespaceV(run->strText, len);
       if (i == len)
         i = ME_ReverseFindNonWhitespaceV(run->strText, len);
-      if (i) {        
+      if (i) {
         ME_DisplayItem *piter2 = ME_SplitRun(wc->context, piter, i);
         wc->pt = piter2->member.run.pt;
         return piter2;
@@ -239,7 +239,7 @@
     }
     /* the run is one char, can't split it */
     return piter;
-  }  
+  }
 }
 
 ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p)
@@ -248,24 +248,24 @@
   ME_Run *run;
   int len;
 
-  assert(p->type == diRun);  
+  assert(p->type == diRun);
   if (!wc->pRowStart)
     wc->pRowStart = p;
-  ME_WrapSizeRun(wc, p);
   run = &p->member.run;
   run->pt.x = wc->pt.x;
   run->pt.y = wc->pt.y;
-  len = ME_StrVLen(run->strText);  
-  
+  ME_WrapSizeRun(wc, p);
+  len = ME_StrVLen(run->strText);
+
   if (wc->bOverflown) /* just skipping final whitespaces */
-  {    
-    if (run->nFlags & MERF_WHITESPACE) {
+  {
+    if (run->nFlags & (MERF_WHITESPACE|MERF_TAB)) {
       p->member.run.nFlags |= MERF_SKIPPED;
       /* wc->pt.x += run->nWidth; */
       /* skip runs consisting of only whitespaces */
       return p->next;
     }
-    
+
     if (run->nFlags & MERF_STARTWHITE) {
       /* try to split the run at the first non-white char */
       int black;
@@ -286,15 +286,15 @@
   /* will current run fit? */
   if (wc->pt.x + run->nWidth > wc->nAvailWidth)
   {
-    int loc = wc->nAvailWidth - wc->pt.x;    
+    int loc = wc->nAvailWidth - wc->pt.x;
     /* total white run ? */
     if (run->nFlags & MERF_WHITESPACE) {
       /* let the overflow logic handle it */
       wc->bOverflown = TRUE;
       return p;
     }
-    /* graphics - we can split before */
-    if (run->nFlags & MERF_GRAPHICS) {
+    /* graphics or TAB - we can split before */
+    if (run->nFlags & (MERF_GRAPHICS|MERF_TAB)) {
       wc->bOverflown = TRUE;
       return p;
     }
@@ -326,8 +326,8 @@
     ERR("failure!\n");
     /* not found anything - writing over margins is the only option left */
   }
-  if ((run->nFlags & (MERF_SPLITTABLE | MERF_STARTWHITE)) 
-    || ((run->nFlags & MERF_GRAPHICS) && (p != wc->pRowStart)))
+  if ((run->nFlags & (MERF_SPLITTABLE | MERF_STARTWHITE))
+    || ((run->nFlags & (MERF_GRAPHICS|MERF_TAB)) && (p != wc->pRowStart)))
   {
     wc->pLastSplittableRun = p;
     wc->ptLastSplittableRun = wc->pt;
@@ -335,20 +335,24 @@
   wc->pt.x += run->nWidth;
   return p->next;
 }
-  
+
 void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
   ME_DisplayItem *p;
   ME_WrapContext wc;
+  int dpi = GetDeviceCaps(c->hDC, LOGPIXELSX);
 
-  assert(tp->type == diParagraph);  
+  assert(tp->type == diParagraph);
   if (!(tp->member.para.nFlags & MEPF_REWRAP)) {
     return;
   }
   ME_PrepareParagraphForWrapping(c, tp);
-  
+
   wc.context = c;
 /*   wc.para_style = tp->member.para.style; */
   wc.style = NULL;
+  tp->member.para.nRightMargin = tp->member.para.pFmt->dxRightIndent*dpi/1440;
+  tp->member.para.nFirstMargin = tp->member.para.pFmt->dxStartIndent*dpi/1440;
+  tp->member.para.nLeftMargin = (tp->member.para.pFmt->dxStartIndent+tp->member.para.pFmt->dxOffset)*dpi/1440;
   wc.nFirstMargin = tp->member.para.nFirstMargin;
   wc.nLeftMargin = tp->member.para.nLeftMargin;
   wc.nRightMargin = tp->member.para.nRightMargin;
@@ -358,7 +362,7 @@
   wc.nTotalWidth = c->rcView.right - c->rcView.left;
   wc.nAvailWidth = wc.nTotalWidth - wc.nFirstMargin - wc.nRightMargin;
   wc.pRowStart = NULL;
-  
+
   ME_BeginRow(&wc);
   for (p = tp->next; p!=tp->member.para.next_para; ) {
     assert(p->type != diStartRow);
@@ -415,20 +419,20 @@
   ME_DisplayItem *item;
   ME_Context c;
   BOOL bModified = FALSE;
-  
+
   ME_InitContext(&c, editor, hDC);
   c.pt.x = 0;
   c.pt.y = 0;
   item = editor->pBuffer->pFirst->next;
   while(item != editor->pBuffer->pLast) {
     BOOL bRedraw = FALSE;
-    
+
     assert(item->type == diParagraph);
     if ((item->member.para.nFlags & MEPF_REWRAP)
      || (item->member.para.nYPos != c.pt.y))
       bRedraw = TRUE;
     item->member.para.nYPos = c.pt.y;
-    
+
     ME_WrapTextParagraph(&c, item);
 
     if (bRedraw)
@@ -442,7 +446,7 @@
   editor->sizeWindow.cx = c.rcView.right-c.rcView.left;
   editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top;
   editor->nTotalLength = c.pt.y;
-  
+
   ME_DestroyContext(&c);
   ReleaseDC(hWnd, hDC);
   return bModified;
Index: dlls/riched20/editor.h
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editor.h,v
retrieving revision 1.13
diff -u -r1.13 editor.h
--- dlls/riched20/editor.h	13 Apr 2005 11:11:03 -0000	1.13
+++ dlls/riched20/editor.h	15 Apr 2005 06:41:52 -0000
@@ -108,7 +108,7 @@
 void ME_CheckCharOffsets(ME_TextEditor *editor);
 void ME_PropagateCharOffset(ME_DisplayItem *p, int shift);
 void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize);
-int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run);
+int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Paragraph *para, ME_Run *run);
 /* this one accounts for 1/2 char tolerance */
 int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run);
 int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset);
@@ -120,8 +120,8 @@
 int ME_FindSplitPoint(ME_Context *c, POINT *pt, ME_Run *run, int desperate);
 void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run);
 ME_DisplayItem *ME_SplitFurther(ME_TextEditor *editor, ME_DisplayItem *run);
-void ME_CalcRunExtent(ME_Context *c, ME_Run *run);
-SIZE ME_GetRunSize(ME_Context *c, ME_Run *run, int nLen);
+void ME_CalcRunExtent(ME_Context *c, ME_Paragraph *para, ME_Run *run);
+SIZE ME_GetRunSize(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLen);
 void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor);
 void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppRun, int *pOfs);
 int ME_CharOfsFromRunOfs(ME_TextEditor *editor, ME_DisplayItem *pRun, int nOfs);
Index: dlls/riched20/editstr.h
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editstr.h,v
retrieving revision 1.9
diff -u -r1.9 editstr.h
--- dlls/riched20/editstr.h	13 Apr 2005 11:11:03 -0000	1.9
+++ dlls/riched20/editstr.h	15 Apr 2005 06:41:52 -0000
@@ -86,6 +86,8 @@
 #define MERF_STYLEFLAGS 0x0FFF
 /* run contains non-text content, which has its own rules for wrapping, sizing etc */
 #define MERF_GRAPHICS 1
+/* run is a tab (or, in future, any kind of content whose size is dependent on run position) */
+#define MERF_TAB 2
 
 /* run is splittable (contains white spaces in the middle or end) */
 #define MERF_SPLITTABLE 0x001000
@@ -102,6 +104,11 @@
 /* the "end of paragraph" run, contains 1 character */
 #define MERF_ENDPARA    0x100000
 
+/* runs with any of these flags set cannot be joined */
+#define MERF_NOJOIN (MERF_GRAPHICS|MERF_TAB|MERF_ENDPARA)
+/* runs that don't contain real text */
+#define MERF_NOTEXT (MERF_GRAPHICS|MERF_TAB|MERF_ENDPARA)
+
 /* those flags are kept when the row is split */
 #define MERF_SPLITMASK (~(0))
 


More information about the wine-patches mailing list