From a234db82eba410221cbee7ce62efcea0e20d1ca9 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Fri, 19 Jan 2001 20:49:54 +0000 Subject: [PATCH] Solve remaining problems with scroll bars in the edit control. --- controls/edit.c | 329 ++++++++++++++++++++-------------------------- controls/scroll.c | 2 +- 2 files changed, 147 insertions(+), 184 deletions(-) diff --git a/controls/edit.c b/controls/edit.c index 99e738c24f..57ed054ed4 100644 --- a/controls/edit.c +++ b/controls/edit.c @@ -46,8 +46,6 @@ DECLARE_DEBUG_CHANNEL(relay); #define EF_UPDATE 0x0004 /* notify parent of changed state on next WM_PAINT */ #define EF_VSCROLL_TRACK 0x0008 /* don't SetScrollPos() since we are tracking the thumb */ #define EF_HSCROLL_TRACK 0x0010 /* don't SetScrollPos() since we are tracking the thumb */ -#define EF_VSCROLL_HACK 0x0020 /* we already have informed the user of the hacked handler */ -#define EF_HSCROLL_HACK 0x0040 /* we already have informed the user of the hacked handler */ #define EF_AFTER_WRAP 0x0080 /* the caret is displayed after the last character of a wrapped line, instead of in front of the next character */ #define EF_USE_SOFTBRK 0x0100 /* Enable soft breaks in text. */ @@ -1030,6 +1028,10 @@ static LRESULT WINAPI EditWndProc_locked( WND *wnd, UINT msg, EDIT_WM_SetFont(wnd, es, (HFONT)wParam, LOWORD(lParam) != 0); break; + case WM_SETREDRAW: + /* FIXME: actually set an internal flag and behave accordingly */ + break; + case WM_SETTEXT: DPRINTF_EDIT_MSG32("WM_SETTEXT"); EDIT_WM_SetText(wnd, es, lParam, unicode); @@ -2128,6 +2130,9 @@ static void EDIT_SetRectNP(WND *wnd, EDITSTATE *es, LPRECT rc) if(max_y_offset < 0) max_y_offset = 0; if(es->y_offset > max_y_offset) es->y_offset = max_y_offset; + + /* force scroll info update */ + EDIT_UpdateScrollInfo(wnd, es); } else /* Windows doesn't care to fix text placement for SL controls */ @@ -2543,9 +2548,6 @@ static LRESULT EDIT_EM_GetSel(EDITSTATE *es, LPUINT start, LPUINT end) * own scrollbars) (and maybe only for multiline controls ?) * All in all: very poorly documented * - * FIXME: now it's also broken, because of the new WM_HSCROLL / - * WM_VSCROLL handlers - * */ static LRESULT EDIT_EM_GetThumb(WND *wnd, EDITSTATE *es) { @@ -2715,6 +2717,8 @@ static BOOL EDIT_EM_LineScroll_internal(WND *wnd, EDITSTATE *es, INT dx, INT dy) IntersectRect(&rc, &rc1, &es->format_rect); ScrollWindowEx(wnd->hwndSelf, -dx, dy, NULL, &rc, (HRGN)NULL, NULL, SW_INVALIDATE); + /* force scroll info update */ + EDIT_UpdateScrollInfo(wnd, es); } if (dx && !(es->flags & EF_HSCROLL_TRACK)) EDIT_NOTIFY_PARENT(wnd, EN_HSCROLL, "EN_HSCROLL"); @@ -2893,6 +2897,9 @@ static void EDIT_EM_ReplaceSel(WND *wnd, EDITSTATE *es, BOOL can_undo, LPCWSTR l es->flags |= EF_MODIFIED; if (send_update) es->flags |= EF_UPDATE; EDIT_EM_ScrollCaret(wnd, es); + + /* force scroll info update */ + EDIT_UpdateScrollInfo(wnd, es); /* FIXME: really inefficient */ EDIT_UpdateText(wnd, NULL, TRUE); @@ -3095,6 +3102,8 @@ static void EDIT_EM_SetHandle(WND *wnd, EDITSTATE *es, HLOCAL hloc) EDIT_BuildLineDefs_ML(wnd, es); EDIT_UpdateText(wnd, NULL, TRUE); EDIT_EM_ScrollCaret(wnd, es); + /* force scroll info update */ + EDIT_UpdateScrollInfo(wnd, es); } @@ -3159,6 +3168,8 @@ static void EDIT_EM_SetHandle16(WND *wnd, EDITSTATE *es, HLOCAL16 hloc) EDIT_BuildLineDefs_ML(wnd, es); EDIT_UpdateText(wnd, NULL, TRUE); EDIT_EM_ScrollCaret(wnd, es); + /* force scroll info update */ + EDIT_UpdateScrollInfo(wnd, es); } @@ -3632,6 +3643,8 @@ static LRESULT EDIT_WM_Create(WND *wnd, EDITSTATE *es, LPCWSTR name) EDIT_NOTIFY_PARENT(wnd, EN_CHANGE, "EN_CHANGE"); } } + /* force scroll info update */ + EDIT_UpdateScrollInfo(wnd, es); return 0; } @@ -3718,96 +3731,6 @@ static INT EDIT_WM_GetText(EDITSTATE *es, INT count, LPARAM lParam, BOOL unicode } } - -/********************************************************************* - * - * EDIT_HScroll_Hack - * - * 16 bit notepad needs this. Actually it is not _our_ hack, - * it is notepad's. Notepad is sending us scrollbar messages with - * undocumented parameters without us even having a scrollbar ... !?!? - * - */ -static LRESULT EDIT_HScroll_Hack(WND *wnd, EDITSTATE *es, INT action, INT pos) -{ - INT dx = 0; - INT fw = es->format_rect.right - es->format_rect.left; - LRESULT ret = 0; - - if (!(es->flags & EF_HSCROLL_HACK)) { - ERR("hacked WM_HSCROLL handler invoked\n"); - ERR(" if you are _not_ running 16 bit notepad, please report\n"); - ERR(" (this message is only displayed once per edit control)\n"); - es->flags |= EF_HSCROLL_HACK; - } - - switch (action) { - case SB_LINELEFT: - if (es->x_offset) - dx = -es->char_width; - break; - case SB_LINERIGHT: - if (es->x_offset < es->text_width) - dx = es->char_width; - break; - case SB_PAGELEFT: - if (es->x_offset) - dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width; - break; - case SB_PAGERIGHT: - if (es->x_offset < es->text_width) - dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width; - break; - case SB_LEFT: - if (es->x_offset) - dx = -es->x_offset; - break; - case SB_RIGHT: - if (es->x_offset < es->text_width) - dx = es->text_width - es->x_offset; - break; - case SB_THUMBTRACK: - es->flags |= EF_HSCROLL_TRACK; - dx = pos * es->text_width / 100 - es->x_offset; - break; - case SB_THUMBPOSITION: - es->flags &= ~EF_HSCROLL_TRACK; - if (!(dx = pos * es->text_width / 100 - es->x_offset)) - EDIT_NOTIFY_PARENT(wnd, EN_HSCROLL, "EN_HSCROLL"); - break; - case SB_ENDSCROLL: - break; - - /* - * FIXME : the next two are undocumented ! - * Are we doing the right thing ? - * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way, - * although it's also a regular control message. - */ - case EM_GETTHUMB16: - ret = es->text_width ? es->x_offset * 100 / es->text_width : 0; - break; - case EM_LINESCROLL16: - dx = pos; - break; - - default: - ERR("undocumented (hacked) WM_HSCROLL parameter, please report\n"); - return 0; - } - if (dx) - { - INT fw = es->format_rect.right - es->format_rect.left; - /* check if we are going to move too far */ - if(es->x_offset + dx + fw > es->text_width) - dx = es->text_width - fw - es->x_offset; - if(dx) - EDIT_EM_LineScroll_internal(wnd, es, dx, 0); - } - return ret; -} - - /********************************************************************* * * WM_HSCROLL @@ -3824,52 +3747,108 @@ static LRESULT EDIT_WM_HScroll(WND *wnd, EDITSTATE *es, INT action, INT pos) if (!(es->style & ES_AUTOHSCROLL)) return 0; - if (!(es->style & WS_HSCROLL)) - return EDIT_HScroll_Hack(wnd, es, action, pos); - dx = 0; fw = es->format_rect.right - es->format_rect.left; switch (action) { case SB_LINELEFT: + TRACE("SB_LINELEFT\n"); if (es->x_offset) dx = -es->char_width; break; case SB_LINERIGHT: + TRACE("SB_LINERIGHT\n"); if (es->x_offset < es->text_width) dx = es->char_width; break; case SB_PAGELEFT: + TRACE("SB_PAGELEFT\n"); if (es->x_offset) dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width; break; case SB_PAGERIGHT: + TRACE("SB_PAGERIGHT\n"); if (es->x_offset < es->text_width) dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width; break; case SB_LEFT: + TRACE("SB_LEFT\n"); if (es->x_offset) dx = -es->x_offset; break; case SB_RIGHT: + TRACE("SB_RIGHT\n"); if (es->x_offset < es->text_width) dx = es->text_width - es->x_offset; break; case SB_THUMBTRACK: + TRACE("SB_THUMBTRACK %d\n", pos); es->flags |= EF_HSCROLL_TRACK; - dx = pos - es->x_offset; + if(es->style & WS_HSCROLL) + dx = pos - es->x_offset; + else + { + INT fw, new_x; + /* Sanity check */ + if(pos < 0 || pos > 100) return 0; + /* Assume default scroll range 0-100 */ + fw = es->format_rect.right - es->format_rect.left; + new_x = pos * (es->text_width - fw) / 100; + dx = es->text_width ? (new_x - es->x_offset) : 0; + } break; case SB_THUMBPOSITION: + TRACE("SB_THUMBPOSITION %d\n", pos); es->flags &= ~EF_HSCROLL_TRACK; - if (!(dx = pos - es->x_offset)) { - SetScrollPos(wnd->hwndSelf, SB_HORZ, pos, TRUE); + if(wnd->dwStyle & WS_HSCROLL) + dx = pos - es->x_offset; + else + { + INT fw, new_x; + /* Sanity check */ + if(pos < 0 || pos > 100) return 0; + /* Assume default scroll range 0-100 */ + fw = es->format_rect.right - es->format_rect.left; + new_x = pos * (es->text_width - fw) / 100; + dx = es->text_width ? (new_x - es->x_offset) : 0; + } + if (!dx) { + /* force scroll info update */ + EDIT_UpdateScrollInfo(wnd, es); EDIT_NOTIFY_PARENT(wnd, EN_HSCROLL, "EN_HSCROLL"); } break; case SB_ENDSCROLL: + TRACE("SB_ENDSCROLL\n"); + break; + /* + * FIXME : the next two are undocumented ! + * Are we doing the right thing ? + * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way, + * although it's also a regular control message. + */ + case EM_GETTHUMB: /* this one is used by NT notepad */ + case EM_GETTHUMB16: + { + LRESULT ret; + if(wnd->dwStyle & WS_HSCROLL) + ret = GetScrollPos(wnd->hwndSelf, SB_HORZ); + else + { + /* Assume default scroll range 0-100 */ + INT fw = es->format_rect.right - es->format_rect.left; + ret = es->text_width ? es->x_offset * 100 / (es->text_width - fw) : 0; + } + TRACE("EM_GETTHUMB: returning %ld\n", ret); + return ret; + } + case EM_LINESCROLL16: + TRACE("EM_LINESCROLL16\n"); + dx = pos; break; default: - ERR("undocumented WM_HSCROLL parameter, please report\n"); + ERR("undocumented WM_HSCROLL action %d (0x%04x), please report\n", + action, action); return 0; } if (dx) @@ -4357,8 +4336,6 @@ static void EDIT_WM_Paint(WND *wnd, EDITSTATE *es, WPARAM wParam) if (!wParam) EndPaint(wnd->hwndSelf, &ps); - - EDIT_UpdateScrollInfo(wnd, es); } @@ -4559,76 +4536,6 @@ static void EDIT_WM_Timer(WND *wnd, EDITSTATE *es) */ } - -/********************************************************************* - * - * EDIT_VScroll_Hack - * - * 16 bit notepad needs this. Actually it is not _our_ hack, - * it is notepad's. Notepad is sending us scrollbar messages with - * undocumented parameters without us even having a scrollbar ... !?!? - * - */ -static LRESULT EDIT_VScroll_Hack(WND *wnd, EDITSTATE *es, INT action, INT pos) -{ - INT dy = 0; - LRESULT ret = 0; - - if (!(es->flags & EF_VSCROLL_HACK)) { - ERR("hacked WM_VSCROLL handler invoked\n"); - ERR(" if you are _not_ running 16 bit notepad, please report\n"); - ERR(" (this message is only displayed once per edit control)\n"); - es->flags |= EF_VSCROLL_HACK; - } - - switch (action) { - case SB_LINEUP: - case SB_LINEDOWN: - case SB_PAGEUP: - case SB_PAGEDOWN: - EDIT_EM_Scroll(wnd, es, action); - return 0; - case SB_TOP: - dy = -es->y_offset; - break; - case SB_BOTTOM: - dy = es->line_count - 1 - es->y_offset; - break; - case SB_THUMBTRACK: - es->flags |= EF_VSCROLL_TRACK; - dy = (pos * (es->line_count - 1) + 50) / 100 - es->y_offset; - break; - case SB_THUMBPOSITION: - es->flags &= ~EF_VSCROLL_TRACK; - if (!(dy = (pos * (es->line_count - 1) + 50) / 100 - es->y_offset)) - EDIT_NOTIFY_PARENT(wnd, EN_VSCROLL, "EN_VSCROLL"); - break; - case SB_ENDSCROLL: - break; - - /* - * FIXME : the next two are undocumented ! - * Are we doing the right thing ? - * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way, - * although it's also a regular control message. - */ - case EM_GETTHUMB16: - ret = (es->line_count > 1) ? es->y_offset * 100 / (es->line_count - 1) : 0; - break; - case EM_LINESCROLL16: - dy = pos; - break; - - default: - ERR("undocumented (hacked) WM_VSCROLL parameter, please report\n"); - return 0; - } - if (dy) - EDIT_EM_LineScroll(wnd, es, 0, dy); - return ret; -} - - /********************************************************************* * * WM_VSCROLL @@ -4644,41 +4551,97 @@ static LRESULT EDIT_WM_VScroll(WND *wnd, EDITSTATE *es, INT action, INT pos) if (!(es->style & ES_AUTOVSCROLL)) return 0; - if (!(es->style & WS_VSCROLL)) - return EDIT_VScroll_Hack(wnd, es, action, pos); - dy = 0; switch (action) { case SB_LINEUP: case SB_LINEDOWN: case SB_PAGEUP: case SB_PAGEDOWN: + TRACE("action %d\n", action); EDIT_EM_Scroll(wnd, es, action); return 0; - case SB_TOP: + TRACE("SB_TOP\n"); dy = -es->y_offset; break; case SB_BOTTOM: + TRACE("SB_BOTTOM\n"); dy = es->line_count - 1 - es->y_offset; break; case SB_THUMBTRACK: + TRACE("SB_THUMBTRACK %d\n", pos); es->flags |= EF_VSCROLL_TRACK; - dy = pos - es->y_offset; + if(es->style & WS_VSCROLL) + dy = pos - es->y_offset; + else + { + /* Assume default scroll range 0-100 */ + INT vlc, new_y; + /* Sanity check */ + if(pos < 0 || pos > 100) return 0; + vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + new_y = pos * (es->line_count - vlc) / 100; + dy = es->line_count ? (new_y - es->y_offset) : 0; + TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n", + es->line_count, es->y_offset, pos, dy); + } break; case SB_THUMBPOSITION: + TRACE("SB_THUMBPOSITION %d\n", pos); es->flags &= ~EF_VSCROLL_TRACK; - if (!(dy = pos - es->y_offset)) { - SetScrollPos(wnd->hwndSelf, SB_VERT, pos, TRUE); + if(es->style & WS_VSCROLL) + dy = pos - es->y_offset; + else + { + /* Assume default scroll range 0-100 */ + INT vlc, new_y; + /* Sanity check */ + if(pos < 0 || pos > 100) return 0; + vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + new_y = pos * (es->line_count - vlc) / 100; + dy = es->line_count ? (new_y - es->y_offset) : 0; + TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n", + es->line_count, es->y_offset, pos, dy); + } + if (!dy) + { + /* force scroll info update */ + EDIT_UpdateScrollInfo(wnd, es); EDIT_NOTIFY_PARENT(wnd, EN_VSCROLL, "EN_VSCROLL"); } break; case SB_ENDSCROLL: + TRACE("SB_ENDSCROLL\n"); + break; + /* + * FIXME : the next two are undocumented ! + * Are we doing the right thing ? + * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way, + * although it's also a regular control message. + */ + case EM_GETTHUMB: /* this one is used by NT notepad */ + case EM_GETTHUMB16: + { + LRESULT ret; + if(wnd->dwStyle & WS_VSCROLL) + ret = GetScrollPos(wnd->hwndSelf, SB_VERT); + else + { + /* Assume default scroll range 0-100 */ + INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height; + ret = es->line_count ? es->y_offset * 100 / (es->line_count - vlc) : 0; + } + TRACE("EM_GETTHUMB: returning %ld\n", ret); + return ret; + } + case EM_LINESCROLL16: + TRACE("EM_LINESCROLL16 %d\n", pos); + dy = pos; break; default: - ERR("undocumented WM_VSCROLL action %d, please report\n", - action); + ERR("undocumented WM_VSCROLL action %d (0x%04x), please report\n", + action, action); return 0; } if (dy) diff --git a/controls/scroll.c b/controls/scroll.c index bc0706b97d..b270424718 100644 --- a/controls/scroll.c +++ b/controls/scroll.c @@ -1372,7 +1372,7 @@ INT SCROLL_SetScrollInfo( HWND hwnd, INT nBar, if (TRACE_ON(scroll)) { - DPRINTF( "hwnd=%04x bar=%d", hwnd, nBar); + TRACE("hwnd=%04x bar=%d", hwnd, nBar); if (info->fMask & SIF_PAGE) DPRINTF( " page=%d", info->nPage ); if (info->fMask & SIF_POS) DPRINTF( " pos=%d", info->nPos ); if (info->fMask & SIF_RANGE) DPRINTF( " min=%d max=%d", info->nMin, info->nMax ); -- 2.32.0.93.g670b81a890