diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index a2bc7c5..1aa10b1 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -160,14 +160,23 @@ int ME_twips2pointsY(ME_Context *c, int y) return y * c->dpi.cy * c->editor->nZoomNumerator / 1440 / c->editor->nZoomDenominator; } -static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChars, - ME_Style *s, int *width, int nSelFrom, int nSelTo, int ymin, int cy) { +static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, + int nChars, ME_Style *s, int width, + int nSelFrom, int nSelTo, int ymin, int cy) +{ HDC hDC = c->hDC; HGDIOBJ hOldFont; COLORREF rgbOld; int yOffset = 0, yTwipsOffset = 0; SIZE sz; COLORREF rgb; + int *lpDx = NULL; + /* lpDx is only needed for tabs to make sure the underline done automatically + * by the font extends to the end of the tab. Tabs are always stored as + * a single character run, so we can handle this case separately, since + * otherwise lpDx would need to specify the lengths of each character. */ + if (width && nChars == 1) + lpDx = &width; /* Make sure underline for tab extends across tab space */ hOldFont = ME_SelectStyleFont(c, s); if ((s->fmt.dwMask & CFM_LINK) && (s->fmt.dwEffects & CFE_LINK)) @@ -186,12 +195,15 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, in } if (yTwipsOffset) yOffset = ME_twips2pointsY(c, yTwipsOffset); - ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nChars, NULL); + ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nChars, lpDx); GetTextExtentPoint32W(hDC, szText, nChars, &sz); - if (width) *width = sz.cx; + /* Treat width as an optional parameter. We can get the width from the + * text extent of the string if it isn't specified. */ + if (!width) width = sz.cx; + if (s->fmt.dwMask & CFM_UNDERLINETYPE) { - HPEN hPen; + HPEN hPen = NULL; switch (s->fmt.bUnderlineType) { case CFU_UNDERLINE: @@ -215,22 +227,36 @@ static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, in HPEN hOldPen = SelectObject(hDC, hPen); /* FIXME: should use textmetrics info for Descent info */ MoveToEx(hDC, x, y - yOffset + 1, NULL); - LineTo(hDC, x + sz.cx, y - yOffset + 1); + LineTo(hDC, x + width, y - yOffset + 1); SelectObject(hDC, hOldPen); DeleteObject(hPen); } } - if (nSelFrom < nChars && nSelTo >= 0 && nSelFrom= 0 && nSelFrom < nSelTo + && !c->editor->bHideSelection) { - if (nSelFrom < 0) nSelFrom = 0; - if (nSelTo > nChars) nSelTo = nChars; - GetTextExtentPoint32W(hDC, szText, nSelFrom, &sz); - x += sz.cx; - GetTextExtentPoint32W(hDC, szText+nSelFrom, nSelTo-nSelFrom, &sz); - - /* Invert selection if not hidden by EM_HIDESELECTION */ - if (c->editor->bHideSelection == FALSE) - PatBlt(hDC, x, ymin, sz.cx, cy, DSTINVERT); + int xSelStart, xSelEnd; + if (nSelFrom <= 0) + { + nSelFrom = 0; + xSelStart = x; + } + else + { + GetTextExtentPoint32W(hDC, szText, nSelFrom, &sz); + xSelStart = x + sz.cx; + } + if (nSelTo >= nChars) + { + nSelTo = nChars; + xSelEnd = x + width; + } + else + { + GetTextExtentPoint32W(hDC, szText+nSelFrom, nSelTo-nSelFrom, &sz); + xSelEnd = xSelStart + sz.cx; + } + PatBlt(hDC, xSelStart, ymin, xSelEnd-xSelStart, cy, DSTINVERT); } SetTextColor(hDC, rgbOld); ME_UnselectStyleFont(c, s, hOldFont); @@ -262,14 +288,25 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa /* Draw selected end-of-paragraph mark */ if (run->nFlags & MERF_ENDPARA && runofs >= nSelFrom && runofs < nSelTo) - ME_DrawTextWithStyle(c, x, y, wszSpace, 1, run->style, NULL, 0, 1, + ME_DrawTextWithStyle(c, x, y, wszSpace, 1, run->style, 0, 0, 1, c->pt.y + start->member.row.nYPos, start->member.row.nHeight); - + /* you can always comment it out if you need visible paragraph marks */ - if (run->nFlags & (MERF_ENDPARA | MERF_TAB | MERF_CELL)) + if (run->nFlags & MERF_ENDPARA) return; + if (run->nFlags & (MERF_TAB | MERF_CELL)) + { + /* wszSpace is used instead of the tab character because otherwise + * an unwanted symbol can be inserted instead. */ + ME_DrawTextWithStyle(c, x, y, wszSpace, 1, run->style, run->nWidth, + nSelFrom-runofs,nSelTo-runofs, + c->pt.y + start->member.row.nYPos, + start->member.row.nHeight); + return; + } + if (run->nFlags & MERF_GRAPHICS) ME_DrawOLE(c, x, y, run, para, (runofs >= nSelFrom) && (runofs < nSelTo)); else @@ -277,16 +314,16 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa if (c->editor->cPasswordMask) { ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,ME_StrVLen(run->strText)); - ME_DrawTextWithStyle(c, x, y, - szMasked->szData, ME_StrVLen(szMasked), run->style, NULL, - nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight); + ME_DrawTextWithStyle(c, x, y, + szMasked->szData, ME_StrVLen(szMasked), run->style, run->nWidth, + nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight); ME_DestroyString(szMasked); } else - ME_DrawTextWithStyle(c, x, y, - run->strText->szData, ME_StrVLen(run->strText), run->style, NULL, - nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight); - } + ME_DrawTextWithStyle(c, x, y, + run->strText->szData, ME_StrVLen(run->strText), run->style, run->nWidth, + nSelFrom-runofs,nSelTo-runofs, c->pt.y+start->member.row.nYPos, start->member.row.nHeight); + } } static const struct {unsigned width_num : 4, width_den : 4, pen_style : 4, dble : 1;} border_details[] = {