Commit e6fedf87 authored by Dylan Smith's avatar Dylan Smith Committed by Alexandre Julliard

richedit: Implemented the horizontal scrollbar.

parent 01ee55a8
......@@ -168,7 +168,7 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
assert(!(ME_GetParagraph(pCursorRun)->member.para.nFlags & MEPF_REWRAP));
assert(pCursor->pRun);
assert(pCursor->pRun->type == diRun);
if (pCursorRun->type == diRun) {
ME_DisplayItem *row = ME_FindItemBack(pCursorRun, diStartRowOrParagraph);
......@@ -178,9 +178,9 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
ME_DisplayItem *run = pCursorRun;
ME_DisplayItem *para = NULL;
SIZE sz = {0, 0};
ME_InitContext(&c, editor, hDC);
if (!pCursor->nOffset)
{
ME_DisplayItem *prev = ME_FindItemBack(pCursorRun, diRunOrParagraph);
......@@ -192,7 +192,7 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
para = ME_FindItemBack(row, diParagraph);
assert(para);
assert(para->type == diParagraph);
if (editor->bCaretAtEnd && !pCursor->nOffset &&
if (editor->bCaretAtEnd && !pCursor->nOffset &&
run == ME_FindItemFwd(row, diRun))
{
ME_DisplayItem *tmp = ME_FindItemBack(row, diRunOrParagraph);
......@@ -214,9 +214,9 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
}
*height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent;
*x = c.rcView.left + run->member.run.pt.x + sz.cx;
*x = c.rcView.left + run->member.run.pt.x + sz.cx - editor->horz_si.nPos;
*y = c.rcView.top + para->member.para.pt.y + row->member.row.nBaseline
+ run->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor);
+ run->member.run.pt.y - pSizeRun->member.run.nAscent - editor->vert_si.nPos;
ME_DestroyContext(&c, editor->hWnd);
return;
}
......@@ -1025,7 +1025,8 @@ int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact)
if (isExact) *isExact = FALSE;
return -1;
}
y += ME_GetYScrollPos(editor);
x += editor->horz_si.nPos;
y += editor->vert_si.nPos;
bResult = ME_FindPixelPos(editor, x, y, &cursor, NULL);
if (isExact) *isExact = bResult;
return (ME_GetParagraph(cursor.pRun)->member.para.nCharOfs
......@@ -1099,10 +1100,11 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
ME_Cursor tmp_cursor;
int is_selection = 0;
BOOL is_shift;
editor->nUDArrowX = -1;
y += ME_GetYScrollPos(editor);
x += editor->horz_si.nPos;
y += editor->vert_si.nPos;
tmp_cursor = editor->pCursors[0];
is_selection = ME_IsSelection(editor);
......@@ -1161,10 +1163,11 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
void ME_MouseMove(ME_TextEditor *editor, int x, int y)
{
ME_Cursor tmp_cursor;
if (editor->nSelectionType == stDocument)
return;
y += ME_GetYScrollPos(editor);
x += editor->horz_si.nPos;
y += editor->vert_si.nPos;
tmp_cursor = editor->pCursors[0];
/* FIXME: do something with the return value of ME_FindPixelPos */
......@@ -1179,9 +1182,9 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y)
{
/* The scroll the cursor towards the other end, since it was the one
* extended by ME_ExtendAnchorSelection */
ME_EnsureVisible(editor, editor->pCursors[1].pRun);
ME_EnsureVisible(editor, &editor->pCursors[1]);
} else {
ME_EnsureVisible(editor, editor->pCursors[0].pRun);
ME_EnsureVisible(editor, &editor->pCursors[0]);
}
ME_InvalidateSelection(editor);
......@@ -1367,18 +1370,18 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
ME_DisplayItem *pLast, *p;
int x, y, ys, yd, yp, yprev;
ME_Cursor tmp_curs = *pCursor;
x = ME_GetXForArrow(editor, pCursor);
if (!pCursor->nOffset && editor->bCaretAtEnd)
pRun = ME_FindItemBack(pRun, diRun);
p = ME_FindItemBack(pRun, diStartRowOrParagraph);
assert(p->type == diStartRow);
yp = ME_FindItemBack(p, diParagraph)->member.para.pt.y;
yprev = ys = y = yp + p->member.row.pt.y;
yd = y - editor->sizeWindow.cy;
pLast = p;
do {
p = ME_FindItemBack(p, diStartRowOrParagraph);
if (!p)
......@@ -1395,15 +1398,16 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
pLast = p;
yprev = y;
} while(1);
pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd);
ME_UpdateSelection(editor, &tmp_curs);
if (yprev < editor->sizeWindow.cy)
{
ME_EnsureVisible(editor, ME_FindItemFwd(editor->pBuffer->pFirst, diRun));
ME_Cursor startCursor = {ME_FindItemFwd(editor->pBuffer->pFirst, diRun), 0};
ME_EnsureVisible(editor, &startCursor);
ME_Repaint(editor);
}
else
else
{
ME_ScrollUp(editor, ys-yprev);
}
......@@ -1422,18 +1426,18 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
ME_DisplayItem *pLast, *p;
int x, y, ys, yd, yp, yprev;
ME_Cursor tmp_curs = *pCursor;
x = ME_GetXForArrow(editor, pCursor);
if (!pCursor->nOffset && editor->bCaretAtEnd)
pRun = ME_FindItemBack(pRun, diRun);
p = ME_FindItemBack(pRun, diStartRowOrParagraph);
assert(p->type == diStartRow);
yp = ME_FindItemBack(p, diParagraph)->member.para.pt.y;
yprev = ys = y = yp + p->member.row.pt.y;
yd = y + editor->sizeWindow.cy;
pLast = p;
do {
p = ME_FindItemFwd(p, diStartRowOrParagraph);
if (!p)
......@@ -1448,15 +1452,16 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
pLast = p;
yprev = y;
} while(1);
pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd);
ME_UpdateSelection(editor, &tmp_curs);
if (yprev >= editor->nTotalLength-editor->sizeWindow.cy)
{
ME_EnsureVisible(editor, ME_FindItemBack(editor->pBuffer->pLast, diRun));
ME_Cursor endCursor = {ME_FindItemBack(editor->pBuffer->pLast, diRun), 0};
ME_EnsureVisible(editor, &endCursor);
ME_Repaint(editor);
}
else
else
{
ME_ScrollUp(editor,ys-yprev);
}
......@@ -1593,7 +1598,7 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
ME_Cursor *p = &editor->pCursors[nCursor];
ME_Cursor tmp_curs = *p;
BOOL success = FALSE;
ME_CheckCharOffsets(editor);
switch(nVKey) {
case VK_LEFT:
......@@ -1630,22 +1635,22 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
editor->bCaretAtEnd = 0;
break;
}
case VK_END:
case VK_END:
if (ctrl)
ME_ArrowCtrlEnd(editor, &tmp_curs);
else
ME_ArrowEnd(editor, &tmp_curs);
break;
}
if (!extend)
editor->pCursors[1] = tmp_curs;
*p = tmp_curs;
ME_InvalidateSelection(editor);
ME_Repaint(editor);
HideCaret(editor->hWnd);
ME_EnsureVisible(editor, tmp_curs.pRun);
ME_EnsureVisible(editor, &tmp_curs);
ME_ShowCaret(editor);
ME_SendSelChange(editor);
return success;
......
......@@ -65,7 +65,7 @@
- EM_GETREDONAME 2.0
+ EM_GETSEL
+ EM_GETSELTEXT (ANSI&Unicode)
+ EM_GETSCROLLPOS 3.0 (only Y value valid)
+ EM_GETSCROLLPOS 3.0
! - EM_GETTHUMB
+ EM_GETTEXTEX 2.0
+ EM_GETTEXTLENGTHEX (GTL_PRECISE unimplemented)
......@@ -137,12 +137,14 @@
+ WM_GETDLGCODE (the current implementation is incomplete)
+ WM_GETTEXT (ANSI&Unicode)
+ WM_GETTEXTLENGTH (ANSI version sucks)
+ WM_HSCROLL
+ WM_PASTE
+ WM_SETFONT
+ WM_SETTEXT (resets undo stack !) (proper style?) ANSI&Unicode
- WM_STYLECHANGING
- WM_STYLECHANGED (things like read-only flag)
+ WM_UNICHAR
+ WM_VSCROLL
Notifications
......@@ -184,7 +186,7 @@
- ES_VERTICAL
- ES_WANTRETURN (don't know how to do WM_GETDLGCODE part)
- WS_SETFONT
- WS_HSCROLL
+ WS_HSCROLL
+ WS_VSCROLL
*/
......@@ -197,7 +199,6 @@
* - pictures/OLE objects (not just smiling faces that lack API support ;-) )
* - COM interface (looks like a major pain in the TODO list)
* - calculate heights of pictures (half-done)
* - horizontal scrolling (not even started)
* - hysteresis during wrapping (related to scrollbars appearing/disappearing)
* - find/replace
* - how to implement EM_FORMATRANGE and EM_DISPLAYBAND ? (Mission Impossible)
......@@ -2681,6 +2682,7 @@ static ME_TextEditor *ME_MakeEditor(HWND hWnd, BOOL bEmulateVersion10)
ed->pCursors[2] = ed->pCursors[0];
ed->pCursors[3] = ed->pCursors[1];
ed->nLastTotalLength = ed->nTotalLength = 0;
ed->nLastTotalWidth = ed->nTotalWidth = 0;
ed->nUDArrowX = -1;
ed->nSequence = 0;
ed->rgbBackColor = -1;
......@@ -2730,13 +2732,19 @@ static ME_TextEditor *ME_MakeEditor(HWND hWnd, BOOL bEmulateVersion10)
ed->notified_cr.cpMin = ed->notified_cr.cpMax = 0;
/* Default vertical scrollbar information */
/* Default scrollbar information */
ed->vert_si.cbSize = sizeof(SCROLLINFO);
ed->vert_si.nMin = 0;
ed->vert_si.nMax = 0;
ed->vert_si.nPage = 0;
ed->vert_si.nPos = 0;
ed->horz_si.cbSize = sizeof(SCROLLINFO);
ed->horz_si.nMin = 0;
ed->horz_si.nMax = 0;
ed->horz_si.nPage = 0;
ed->horz_si.nPos = 0;
OleInitialize(NULL);
return ed;
......@@ -3156,12 +3164,12 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
case EM_SETSCROLLPOS:
{
POINT *point = (POINT *)lParam;
ME_ScrollAbs(editor, point->y);
ME_ScrollAbs(editor, point->x, point->y);
return 0;
}
case EM_AUTOURLDETECT:
{
if (wParam==1 || wParam ==0)
if (wParam==1 || wParam ==0)
{
editor->AutoURLDetect_bEnable = (BOOL)wParam;
return 0;
......@@ -3363,7 +3371,7 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
case EM_GETFIRSTVISIBLELINE:
{
ME_DisplayItem *p = editor->pBuffer->pFirst;
int y = ME_GetYScrollPos(editor);
int y = editor->vert_si.nPos;
int ypara = 0;
int count = 0;
int ystart, yend;
......@@ -3433,7 +3441,7 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
return len;
}
case EM_SCROLLCARET:
ME_EnsureVisible(editor, editor->pCursors[0].pRun);
ME_EnsureVisible(editor, &editor->pCursors[0]);
return 0;
case WM_SETFONT:
{
......@@ -3587,10 +3595,10 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
}
case EM_GETSCROLLPOS:
{
POINT *point = (POINT *)lParam;
point->x = 0; /* FIXME side scrolling not implemented */
point->y = ME_GetYScrollPos(editor);
return 1;
POINT *point = (POINT *)lParam;
point->x = editor->horz_si.nPos;
point->y = editor->vert_si.nPos;
return 1;
}
case EM_GETTEXTRANGE:
{
......@@ -3837,9 +3845,8 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
ME_DisplayItem *pRun;
int nCharOfs, nOffset, nLength;
POINTL pt = {0,0};
SCROLLINFO si;
nCharOfs = wParam;
nCharOfs = wParam;
/* detect which API version we're dealing with */
if (wParam >= 0x40000)
nCharOfs = lParam;
......@@ -3854,10 +3861,8 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
pt.y += ME_GetParagraph(pRun)->member.para.pt.y + editor->rcFormat.top;
pt.x += editor->rcFormat.left;
pt.x -= editor->horz_si.nPos;
pt.y -= editor->vert_si.nPos;
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
if (GetScrollInfo(editor->hWnd, SB_HORZ, &si)) pt.x -= si.nPos;
if (wParam >= 0x40000) {
*(POINTL *)wParam = pt;
......@@ -3869,10 +3874,6 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
SCROLLINFO si;
ME_SetDefaultFormatRect(editor);
if (GetWindowLongW(editor->hWnd, GWL_STYLE) & WS_HSCROLL)
{ /* Squelch the default horizontal scrollbar it would make */
ShowScrollBar(editor->hWnd, SB_HORZ, FALSE);
}
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_RANGE;
......@@ -3882,6 +3883,7 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
si.nMin = 0;
si.nPage = 0;
SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE);
ME_CommitUndo(editor);
ME_WrapMarkedParagraphs(editor);
......@@ -4046,21 +4048,72 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
case EM_STOPGROUPTYPING:
ME_CommitUndo(editor); /* End coalesced undos for typed characters */
return 0;
case WM_HSCROLL:
{
const int scrollUnit = 7;
switch(LOWORD(wParam))
{
case SB_LEFT:
ME_ScrollAbs(editor, 0, 0);
break;
case SB_RIGHT:
ME_ScrollAbs(editor,
editor->horz_si.nMax - (int)editor->horz_si.nPage,
editor->vert_si.nMax - (int)editor->vert_si.nPage);
break;
case SB_LINELEFT:
ME_ScrollLeft(editor, scrollUnit);
break;
case SB_LINERIGHT:
ME_ScrollRight(editor, scrollUnit);
break;
case SB_PAGELEFT:
ME_ScrollLeft(editor, editor->sizeWindow.cx);
break;
case SB_PAGERIGHT:
ME_ScrollRight(editor, editor->sizeWindow.cx);
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
{
SCROLLINFO sbi;
sbi.cbSize = sizeof(sbi);
sbi.fMask = SIF_TRACKPOS;
/* Try to get 32-bit track position value. */
if (!GetScrollInfo(editor->hWnd, SB_HORZ, &sbi))
/* GetScrollInfo failed, settle for 16-bit value in wParam. */
sbi.nTrackPos = HIWORD(wParam);
ME_HScrollAbs(editor, sbi.nTrackPos);
break;
}
}
break;
}
case EM_SCROLL: /* fall through */
case WM_VSCROLL:
case WM_VSCROLL:
{
int origNPos;
int lineHeight;
origNPos = ME_GetYScrollPos(editor);
origNPos = editor->vert_si.nPos;
lineHeight = 24;
if (editor && editor->pBuffer && editor->pBuffer->pDefaultStyle)
lineHeight = editor->pBuffer->pDefaultStyle->tm.tmHeight;
if (lineHeight <= 0) lineHeight = 24;
switch(LOWORD(wParam))
switch(LOWORD(wParam))
{
case SB_TOP:
ME_ScrollAbs(editor, 0, 0);
break;
case SB_BOTTOM:
ME_ScrollAbs(editor,
editor->horz_si.nMax - (int)editor->horz_si.nPage,
editor->vert_si.nMax - (int)editor->vert_si.nPage);
break;
case SB_LINEUP:
ME_ScrollUp(editor,lineHeight);
break;
......@@ -4084,12 +4137,12 @@ static LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
/* GetScrollInfo failed, settle for 16-bit value in wParam. */
sbi.nTrackPos = HIWORD(wParam);
ME_ScrollAbs(editor, sbi.nTrackPos);
ME_VScrollAbs(editor, sbi.nTrackPos);
break;
}
}
if (msg == EM_SCROLL)
return 0x00010000 | (((ME_GetYScrollPos(editor) - origNPos)/lineHeight) & 0xffff);
return 0x00010000 | (((editor->vert_si.nPos - origNPos)/lineHeight) & 0xffff);
break;
}
case WM_MOUSEWHEEL:
......
......@@ -233,7 +233,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
void ME_Repaint(ME_TextEditor *editor);
void ME_RewrapRepaint(ME_TextEditor *editor);
void ME_UpdateRepaint(ME_TextEditor *editor);
void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun);
void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor);
void ME_InvalidateSelection(ME_TextEditor *editor);
void ME_QueueInvalidateFromCursor(ME_TextEditor *editor, int nCursor);
BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator);
......@@ -242,11 +242,14 @@ int ME_twips2pointsY(ME_Context *c, int y);
/* scroll functions in paint.c */
void ME_ScrollAbs(ME_TextEditor *editor, int absY);
void ME_ScrollAbs(ME_TextEditor *editor, int x, int y);
void ME_HScrollAbs(ME_TextEditor *editor, int x);
void ME_VScrollAbs(ME_TextEditor *editor, int y);
void ME_ScrollUp(ME_TextEditor *editor, int cy);
void ME_ScrollDown(ME_TextEditor *editor, int cy);
void ME_ScrollLeft(ME_TextEditor *editor, int cx);
void ME_ScrollRight(ME_TextEditor *editor, int cx);
void ME_UpdateScrollBar(ME_TextEditor *editor);
int ME_GetYScrollPos(ME_TextEditor *editor);
/* other functions in paint.c */
int ME_GetParaBorderWidth(ME_TextEditor *editor, int);
......
......@@ -189,7 +189,7 @@ typedef struct tagME_Paragraph
int nCharOfs;
int nFlags;
POINT pt;
int nHeight;
int nHeight, nWidth;
int nLastPaintYPos, nLastPaintHeight;
int nRows;
struct tagME_DisplayItem *prev_para, *next_para, *document;
......@@ -333,6 +333,7 @@ typedef struct tagME_TextEditor
int nCursors;
SIZE sizeWindow;
int nTotalLength, nLastTotalLength;
int nTotalWidth, nLastTotalWidth;
int nUDArrowX;
int nSequence;
COLORREF rgbBackColor;
......@@ -374,8 +375,8 @@ typedef struct tagME_TextEditor
/* Track previous notified selection */
CHARRANGE notified_cr;
/* Cache previously set vertical scrollbar info */
SCROLLINFO vert_si;
/* Cache previously set scrollbar info */
SCROLLINFO vert_si, horz_si;
BOOL bMouseCaptured;
} ME_TextEditor;
......
......@@ -29,7 +29,6 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
{
ME_DisplayItem *item;
ME_Context c;
int yoffset;
int ys, ye;
HRGN oldRgn;
......@@ -43,15 +42,14 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
rcUpdate->right, rcUpdate->bottom);
editor->nSequence++;
yoffset = ME_GetYScrollPos(editor);
ME_InitContext(&c, editor, hDC);
SetBkMode(hDC, TRANSPARENT);
ME_MoveCaret(editor); /* Calls ME_WrapMarkedParagraphs */
item = editor->pBuffer->pFirst->next;
/* This context point is an offset for the paragraph positions stored
* during wrapping. It shouldn't be modified during painting. */
c.pt.x = c.rcView.left;
c.pt.y = c.rcView.top - yoffset;
c.pt.x = c.rcView.left - editor->horz_si.nPos;
c.pt.y = c.rcView.top - editor->vert_si.nPos;
while(item != editor->pBuffer->pLast)
{
assert(item->type == diParagraph);
......@@ -113,9 +111,11 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
if (!IsRectEmpty(&rc))
FillRect(hDC, &rc, c.editor->hbrBackground);
}
if (editor->nTotalLength != editor->nLastTotalLength)
if (editor->nTotalLength != editor->nLastTotalLength ||
editor->nTotalWidth != editor->nLastTotalWidth)
ME_SendRequestResize(editor, FALSE);
editor->nLastTotalLength = editor->nTotalLength;
editor->nLastTotalWidth = editor->nTotalWidth;
ME_DestroyContext(&c, NULL);
SelectClipRgn(hDC, oldRgn);
......@@ -146,11 +146,11 @@ void ME_UpdateRepaint(ME_TextEditor *editor)
wrappedParagraphs = ME_WrapMarkedParagraphs(editor);
if (wrappedParagraphs)
ME_UpdateScrollBar(editor);
/* Ensure that the cursor is visible */
pCursor = &editor->pCursors[0];
ME_EnsureVisible(editor, pCursor->pRun);
ME_EnsureVisible(editor, pCursor);
/* send EN_CHANGE if the event mask asks for it */
if(editor->nEventMask & ENM_CHANGE)
{
......@@ -164,7 +164,7 @@ void ME_UpdateRepaint(ME_TextEditor *editor)
void
ME_RewrapRepaint(ME_TextEditor *editor)
{
{
/* RewrapRepaint should be called whenever the control has changed in
* looks, but not content. Like resizing. */
......@@ -619,7 +619,7 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
/* Native richedit doesn't support paragraph borders in v1.0 - 4.1,
* but might support it in later versions. */
if (hasParaBorder) {
int pen_width;
int pen_width, rightEdge;
COLORREF pencr;
HPEN pen = NULL, oldpen = NULL;
POINT pt;
......@@ -629,6 +629,9 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
else
pencr = pen_colors[(para->pFmt->wBorders >> 12) & 0xF];
rightEdge = c->pt.x + max(c->editor->sizeWindow.cx,
c->editor->nTotalWidth);
pen_width = ME_GetBorderPenWidth(c->editor, idx);
pen = CreatePen(border_details[idx].pen_style, pen_width, pencr);
oldpen = SelectObject(c->hDC, pen);
......@@ -641,51 +644,51 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
if (para->pFmt->wBorders & 1)
{
MoveToEx(c->hDC, c->rcView.left, y + bounds->top, NULL);
LineTo(c->hDC, c->rcView.left, y + para->nHeight - bounds->bottom);
MoveToEx(c->hDC, c->pt.x, y + bounds->top, NULL);
LineTo(c->hDC, c->pt.x, y + para->nHeight - bounds->bottom);
if (border_details[idx].dble) {
rc.left = c->rcView.left + 1;
rc.left = c->pt.x + 1;
rc.right = rc.left + border_width;
rc.top = y + bounds->top;
rc.bottom = y + para->nHeight - bounds->bottom;
FillRect(c->hDC, &rc, c->editor->hbrBackground);
MoveToEx(c->hDC, c->rcView.left + pen_width + 1, y + bounds->top + DD(4), NULL);
LineTo(c->hDC, c->rcView.left + pen_width + 1, y + para->nHeight - bounds->bottom - DD(8));
MoveToEx(c->hDC, c->pt.x + pen_width + 1, y + bounds->top + DD(4), NULL);
LineTo(c->hDC, c->pt.x + pen_width + 1, y + para->nHeight - bounds->bottom - DD(8));
}
bounds->left += border_width;
}
if (para->pFmt->wBorders & 2)
{
MoveToEx(c->hDC, c->rcView.right - 1, y + bounds->top, NULL);
LineTo(c->hDC, c->rcView.right - 1, y + para->nHeight - bounds->bottom);
MoveToEx(c->hDC, rightEdge - 1, y + bounds->top, NULL);
LineTo(c->hDC, rightEdge - 1, y + para->nHeight - bounds->bottom);
if (border_details[idx].dble) {
rc.left = c->rcView.right - pen_width - 1;
rc.right = c->rcView.right - 1;
rc.left = rightEdge - pen_width - 1;
rc.right = rc.left + pen_width;
rc.top = y + bounds->top;
rc.bottom = y + para->nHeight - bounds->bottom;
FillRect(c->hDC, &rc, c->editor->hbrBackground);
MoveToEx(c->hDC, c->rcView.right - 1 - pen_width - 1, y + bounds->top + DD(4), NULL);
LineTo(c->hDC, c->rcView.right - 1 - pen_width - 1, y + para->nHeight - bounds->bottom - DD(8));
MoveToEx(c->hDC, rightEdge - 1 - pen_width - 1, y + bounds->top + DD(4), NULL);
LineTo(c->hDC, rightEdge - 1 - pen_width - 1, y + para->nHeight - bounds->bottom - DD(8));
}
bounds->right += border_width;
}
if (para->pFmt->wBorders & 4)
{
MoveToEx(c->hDC, c->rcView.left, y + bounds->top, NULL);
LineTo(c->hDC, c->rcView.right, y + bounds->top);
MoveToEx(c->hDC, c->pt.x, y + bounds->top, NULL);
LineTo(c->hDC, rightEdge, y + bounds->top);
if (border_details[idx].dble) {
MoveToEx(c->hDC, c->rcView.left + DD(1), y + bounds->top + pen_width + 1, NULL);
LineTo(c->hDC, c->rcView.right - DD(2), y + bounds->top + pen_width + 1);
MoveToEx(c->hDC, c->pt.x + DD(1), y + bounds->top + pen_width + 1, NULL);
LineTo(c->hDC, rightEdge - DD(2), y + bounds->top + pen_width + 1);
}
bounds->top += border_width;
}
if (para->pFmt->wBorders & 8)
{
MoveToEx(c->hDC, c->rcView.left, y + para->nHeight - bounds->bottom - 1, NULL);
LineTo(c->hDC, c->rcView.right, y + para->nHeight - bounds->bottom - 1);
MoveToEx(c->hDC, c->pt.x, y + para->nHeight - bounds->bottom - 1, NULL);
LineTo(c->hDC, rightEdge, y + para->nHeight - bounds->bottom - 1);
if (border_details[idx].dble) {
MoveToEx(c->hDC, c->rcView.left + DD(1), y + para->nHeight - bounds->bottom - 1 - pen_width - 1, NULL);
LineTo(c->hDC, c->rcView.right - DD(2), y + para->nHeight - bounds->bottom - 1 - pen_width - 1);
MoveToEx(c->hDC, c->pt.x + DD(1), y + para->nHeight - bounds->bottom - 1 - pen_width - 1, NULL);
LineTo(c->hDC, rightEdge - DD(2), y + para->nHeight - bounds->bottom - 1 - pen_width - 1);
}
bounds->bottom += border_width;
}
......@@ -926,8 +929,12 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
}
ME_DrawParaDecoration(c, para, y, &bounds);
y += bounds.top;
rc.left += bounds.left;
rc.right -= bounds.right;
if (bounds.left || bounds.right) {
rc.left = max(rc.left, c->pt.x + bounds.left);
rc.right = min(rc.right, c->pt.x - bounds.right
+ max(c->editor->sizeWindow.cx,
c->editor->nTotalWidth));
}
for (p = paragraph->next; p != para->next_para; p = p->next)
{
......@@ -947,6 +954,16 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
if (visible) {
FillRect(c->hDC, &rc, c->editor->hbrBackground);
}
if (bounds.right)
{
/* If scrolled to the right past the end of the text, then
* there may be space to the right of the paragraph border. */
RECT rcAfterBrdr = rc;
rcAfterBrdr.left = rc.right + bounds.right;
rcAfterBrdr.right = c->rcView.right;
if (RectVisible(c->hDC, &rcAfterBrdr))
FillRect(c->hDC, &rcAfterBrdr, c->editor->hbrBackground);
}
if (me_debug)
{
const WCHAR wszRowDebug[] = {'r','o','w','[','%','d',']',0};
......@@ -1013,157 +1030,192 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
SetTextAlign(c->hDC, align);
}
static void ME_Scroll(ME_TextEditor *editor, int value, int type)
void ME_ScrollAbs(ME_TextEditor *editor, int x, int y)
{
SCROLLINFO si;
int nOrigPos, nNewPos, nActualScroll;
HWND hWnd;
LONG winStyle;
BOOL bScrollBarIsVisible, bScrollBarWillBeVisible;
int scrollX = 0, scrollY = 0;
if (editor->horz_si.nPos != x) {
x = min(x, editor->horz_si.nMax);
x = max(x, editor->horz_si.nMin);
SetScrollPos(editor->hWnd, SB_HORZ, x, TRUE);
scrollX = editor->horz_si.nPos - x;
editor->horz_si.nPos = x;
}
nOrigPos = ME_GetYScrollPos(editor);
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS;
switch (type)
{
case 1:
/*Scroll absolutely*/
si.nPos = value;
break;
case 2:
/* Scroll up - towards the beginning of the document */
si.nPos = nOrigPos - value;
break;
case 3:
/* Scroll down - towards the end of the document */
si.nPos = nOrigPos + value;
break;
default:
FIXME("ME_Scroll called incorrectly\n");
si.nPos = 0;
if (editor->vert_si.nPos != y) {
y = min(y, editor->vert_si.nMax - (int)editor->vert_si.nPage);
y = max(y, editor->vert_si.nMin);
SetScrollPos(editor->hWnd, SB_VERT, y, TRUE);
scrollY = editor->vert_si.nPos - y;
editor->vert_si.nPos = y;
}
nNewPos = SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
editor->vert_si.nPos = nNewPos;
nActualScroll = nOrigPos - nNewPos;
if (abs(nActualScroll) > editor->sizeWindow.cy)
if (abs(scrollX) > editor->sizeWindow.cx ||
abs(scrollY) > editor->sizeWindow.cy)
InvalidateRect(editor->hWnd, NULL, TRUE);
else
ScrollWindowEx(editor->hWnd, 0, nActualScroll, &editor->rcFormat,
ScrollWindowEx(editor->hWnd, scrollX, scrollY, &editor->rcFormat,
&editor->rcFormat, NULL, NULL, SW_INVALIDATE);
ME_Repaint(editor);
hWnd = editor->hWnd;
winStyle = GetWindowLongW(hWnd, GWL_STYLE);
winStyle = GetWindowLongW(editor->hWnd, GWL_STYLE);
bScrollBarIsVisible = (winStyle & WS_HSCROLL) != 0;
bScrollBarWillBeVisible = (editor->nTotalWidth > editor->sizeWindow.cx)
|| (winStyle & ES_DISABLENOSCROLL);
if (bScrollBarIsVisible != bScrollBarWillBeVisible)
ShowScrollBar(editor->hWnd, SB_HORZ, bScrollBarWillBeVisible);
bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0;
bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy)
|| (winStyle & ES_DISABLENOSCROLL);
if (bScrollBarIsVisible != bScrollBarWillBeVisible)
{
ShowScrollBar(hWnd, SB_VERT, bScrollBarWillBeVisible);
}
ShowScrollBar(editor->hWnd, SB_VERT, bScrollBarWillBeVisible);
ME_UpdateScrollBar(editor);
}
void ME_ScrollAbs(ME_TextEditor *editor, int absY)
void ME_HScrollAbs(ME_TextEditor *editor, int x)
{
ME_Scroll(editor, absY, 1);
ME_ScrollAbs(editor, x, editor->vert_si.nPos);
}
void ME_VScrollAbs(ME_TextEditor *editor, int y)
{
ME_ScrollAbs(editor, editor->horz_si.nPos, y);
}
void ME_ScrollUp(ME_TextEditor *editor, int cy)
{
ME_Scroll(editor, cy, 2);
ME_VScrollAbs(editor, editor->vert_si.nPos - cy);
}
void ME_ScrollDown(ME_TextEditor *editor, int cy)
{
ME_Scroll(editor, cy, 3);
ME_VScrollAbs(editor, editor->vert_si.nPos + cy);
}
static BOOL ME_GetYScrollVisible(ME_TextEditor *editor)
{ /* Returns true if the scrollbar is visible */
return (editor->vert_si.nMax - editor->vert_si.nMin > editor->vert_si.nPage);
void ME_ScrollLeft(ME_TextEditor *editor, int cx)
{
ME_HScrollAbs(editor, editor->horz_si.nPos - cx);
}
void ME_ScrollRight(ME_TextEditor *editor, int cx)
{
ME_HScrollAbs(editor, editor->horz_si.nPos + cx);
}
void ME_UpdateScrollBar(ME_TextEditor *editor)
{
/* Note that this is the only function that should ever call SetScrolLInfo
* with SIF_PAGE or SIF_RANGE. SetScrollPos and SetScrollRange should never
* be used at all. */
HWND hWnd;
{
/* Note that this is the only function that should ever call
* SetScrollInfo with SIF_PAGE or SIF_RANGE. */
SCROLLINFO si;
BOOL bScrollBarWasVisible,bScrollBarWillBeVisible;
BOOL bScrollBarWasVisible, bScrollBarWillBeVisible;
if (ME_WrapMarkedParagraphs(editor))
FIXME("ME_UpdateScrollBar had to call ME_WrapMarkedParagraphs\n");
hWnd = editor->hWnd;
si.cbSize = sizeof(si);
bScrollBarWasVisible = ME_GetYScrollVisible(editor);
bScrollBarWillBeVisible = editor->nTotalLength > editor->sizeWindow.cy;
si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
si.fMask |= SIF_DISABLENOSCROLL;
if (editor->vert_si.nPos && !bScrollBarWillBeVisible)
/* Update horizontal scrollbar */
bScrollBarWasVisible = editor->horz_si.nMax > editor->horz_si.nPage;
bScrollBarWillBeVisible = editor->nTotalWidth > editor->sizeWindow.cx;
if (editor->horz_si.nPos && !bScrollBarWillBeVisible)
{
ME_ScrollAbs(editor, 0);
/* ME_ScrollAbs will call this function,
ME_HScrollAbs(editor, 0);
/* ME_HScrollAbs will call this function,
* so nothing else needs to be done here. */
return;
}
si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
if (GetWindowLongW(hWnd, GWL_STYLE) & ES_DISABLENOSCROLL)
si.nMin = 0;
si.nMax = editor->nTotalWidth;
si.nPos = editor->horz_si.nPos;
si.nPage = editor->sizeWindow.cx;
if (si.nMin != editor->horz_si.nMin ||
si.nMax != editor->horz_si.nMax ||
si.nPage != editor->horz_si.nPage)
{
si.fMask |= SIF_DISABLENOSCROLL;
TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage);
editor->horz_si.nMin = si.nMin;
editor->horz_si.nMax = si.nMax;
editor->horz_si.nPage = si.nPage;
if (bScrollBarWillBeVisible || bScrollBarWasVisible)
SetScrollInfo(editor->hWnd, SB_HORZ, &si, TRUE);
}
if (si.fMask & SIF_DISABLENOSCROLL)
bScrollBarWillBeVisible = TRUE;
if (bScrollBarWasVisible != bScrollBarWillBeVisible)
ShowScrollBar(editor->hWnd, SB_HORZ, bScrollBarWillBeVisible);
/* Update vertical scrollbar */
bScrollBarWasVisible = editor->vert_si.nMax > editor->vert_si.nPage;
bScrollBarWillBeVisible = editor->nTotalLength > editor->sizeWindow.cy;
if (editor->vert_si.nPos && !bScrollBarWillBeVisible)
{
ME_VScrollAbs(editor, 0);
/* ME_VScrollAbs will call this function,
* so nothing else needs to be done here. */
return;
}
si.nMin = 0;
si.nMax = editor->nTotalLength;
si.nPos = editor->vert_si.nPos;
si.nPage = editor->sizeWindow.cy;
if (!(si.nMin == editor->vert_si.nMin &&
si.nMax == editor->vert_si.nMax &&
si.nPage == editor->vert_si.nPage))
if (si.nMin != editor->vert_si.nMin ||
si.nMax != editor->vert_si.nMax ||
si.nPage != editor->vert_si.nPage)
{
TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage);
editor->vert_si.nMin = si.nMin;
editor->vert_si.nMax = si.nMax;
editor->vert_si.nPage = si.nPage;
if (bScrollBarWillBeVisible || bScrollBarWasVisible)
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
SetScrollInfo(editor->hWnd, SB_VERT, &si, TRUE);
}
if (si.fMask & SIF_DISABLENOSCROLL)
bScrollBarWillBeVisible = TRUE;
if (bScrollBarWasVisible != bScrollBarWillBeVisible)
ShowScrollBar(hWnd, SB_VERT, bScrollBarWillBeVisible);
ShowScrollBar(editor->hWnd, SB_VERT, bScrollBarWillBeVisible);
}
int ME_GetYScrollPos(ME_TextEditor *editor)
void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor)
{
return editor->vert_si.nPos;
}
ME_Run *pRun = &pCursor->pRun->member.run;
ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow);
ME_DisplayItem *pPara = ME_FindItemBack(pCursor->pRun, diParagraph);
int x, y, yheight;
void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
{
ME_DisplayItem *pRow = ME_FindItemBack(pRun, diStartRow);
ME_DisplayItem *pPara = ME_FindItemBack(pRun, diParagraph);
int y, yrel, yheight, yold;
assert(pRow);
assert(pPara);
y = pPara->member.para.pt.y+pRow->member.row.pt.y;
x = pRun->pt.x + ME_PointFromChar(editor, pRun, pCursor->nOffset);
if (x > editor->horz_si.nPos + editor->sizeWindow.cx)
x = x + 1 - editor->sizeWindow.cx;
else if (x > editor->horz_si.nPos)
x = editor->horz_si.nPos;
y = pPara->member.para.pt.y + pRow->member.row.pt.y;
yheight = pRow->member.row.nHeight;
yold = ME_GetYScrollPos(editor);
yrel = y - yold;
if (y < yold)
ME_ScrollAbs(editor,y);
else if (yrel + yheight > editor->sizeWindow.cy)
ME_ScrollAbs(editor,y+yheight-editor->sizeWindow.cy);
if (y < editor->vert_si.nPos)
ME_ScrollAbs(editor, x, y);
else if (y + yheight > editor->vert_si.nPos + editor->sizeWindow.cy)
ME_ScrollAbs(editor, x, y + yheight - editor->sizeWindow.cy);
else if (x != editor->horz_si.nPos)
ME_ScrollAbs(editor, x, editor->vert_si.nPos);
}
......
......@@ -621,12 +621,9 @@ static void test_EM_POSFROMCHAR(void)
SendMessage(hwndRichEdit, WM_HSCROLL, SB_LINERIGHT, 0);
result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 0, 0);
ok(HIWORD(result) == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", HIWORD(result));
todo_wine {
/* Fails on builtin because horizontal scrollbar is not being shown */
ok((signed short)(LOWORD(result)) < xpos,
"EM_POSFROMCHAR reports x=%hd, expected value less than %d\n",
(signed short)(LOWORD(result)), xpos);
}
SendMessage(hwndRichEdit, WM_HSCROLL, SB_LINELEFT, 0);
/* Test around end of text that doesn't end in a newline. */
......
......@@ -133,6 +133,7 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
}
}
para->member.para.nWidth = max(para->member.para.nWidth, width);
row = ME_MakeRow(ascent+descent, ascent, width);
if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
......@@ -536,6 +537,7 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) {
ME_DisplayItem *p, *pRow;
tp->member.para.nWidth = 0;
/* remove all items that will be reinserted by paragraph wrapper anyway */
tp->member.para.nRows = 0;
for (p = tp->next; p!=tp->member.para.next_para; p = p->next) {
......@@ -578,6 +580,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
ME_Context c;
BOOL bModified = FALSE;
int yStart = -1;
int totalWidth = 0;
ME_InitContext(&c, editor, GetDC(editor->hWnd));
c.pt.x = 0;
......@@ -638,6 +641,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
ME_DisplayItem *startRowPara;
int prevHeight, nHeight, bottomBorder = 0;
ME_DisplayItem *cell = ME_FindItemBack(item, diCell);
item->member.para.nWidth = cell->member.cell.pt.x + cell->member.cell.nWidth;
if (!(item->member.para.next_para->member.para.nFlags & MEPF_ROWSTART))
{
/* Last row, the bottom border is added to the height. */
......@@ -707,12 +711,15 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
}
c.pt.y += item->member.para.nHeight;
}
totalWidth = max(totalWidth, item->member.para.nWidth);
item = item->member.para.next_para;
}
editor->sizeWindow.cx = c.rcView.right-c.rcView.left;
editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top;
editor->nTotalLength = c.pt.y;
editor->nTotalWidth = totalWidth;
editor->pBuffer->pLast->member.para.pt.x = 0;
editor->pBuffer->pLast->member.para.pt.y = c.pt.y;
......@@ -732,7 +739,7 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor)
ME_InitContext(&c, editor, GetDC(editor->hWnd));
rc = c.rcView;
ofs = ME_GetYScrollPos(editor);
ofs = editor->vert_si.nPos;
item = editor->pBuffer->pFirst;
while(item != editor->pBuffer->pLast) {
......@@ -772,6 +779,7 @@ ME_SendRequestResize(ME_TextEditor *editor, BOOL force)
info.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID);
info.nmhdr.code = EN_REQUESTRESIZE;
info.rc = rc;
info.rc.right = editor->nTotalWidth;
info.rc.bottom = editor->nTotalLength;
editor->nEventMask &= ~ENM_REQUESTRESIZE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment