| /* |
| * Edit control |
| * |
| * Copyright David W. Metcalfe, 1994 |
| * Copyright William Magro, 1995, 1996 |
| * Copyright Frans van Dorsselaer, 1996 |
| * |
| */ |
| |
| /* |
| * UNDER CONSTRUCTION, please read EDIT.TODO |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <windows.h> |
| #include "win.h" |
| #include "local.h" |
| #include "stackframe.h" |
| #include "stddebug.h" |
| #include "debug.h" |
| #include "xmalloc.h" |
| #include "callback.h" |
| |
| #define BUFLIMIT_MULTI 65534 /* maximum text buffer length (not including '\0') */ |
| #define BUFLIMIT_SINGLE 32766 |
| #define BUFSTART_MULTI 1024 /* starting length for multi-line control */ |
| #define BUFSTART_SINGLE 256 /* starting length for single line control */ |
| #define GROWLENGTH 64 /* buffers grow by this much */ |
| #define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */ |
| |
| typedef enum |
| { |
| END_0 = 0, |
| END_DELIMIT, |
| END_NONE, |
| END_HARD, |
| END_SOFT, |
| } LINE_END; |
| |
| typedef struct { |
| UINT offset; |
| UINT length; |
| LINE_END ending; |
| } LINEDEF; |
| |
| typedef struct |
| { |
| UINT TextWidth; /* width of the widest line in pixels */ |
| HLOCAL16 hBuf; |
| char *text; |
| HFONT hFont; |
| LINEDEF *LineDefs; |
| UINT XOffset; /* offset of the viewport in pixels */ |
| UINT FirstVisibleLine; |
| UINT LineCount; |
| UINT LineHeight; /* height of a screen line in pixels */ |
| UINT AveCharWidth; /* average character width in pixels */ |
| UINT BufLimit; |
| UINT BufSize; |
| BOOL TextChanged; |
| BOOL Redraw; |
| UINT SelStart; /* offset of selection start, == SelEnd if no selection */ |
| UINT SelEnd; /* offset of selection end == current caret position */ |
| UINT NumTabStops; |
| LPINT16 TabStops; |
| EDITWORDBREAKPROC WordBreakProc; |
| char PasswordChar; |
| } EDITSTATE; |
| |
| |
| #define SWAP_UINT(x,y) do { UINT temp = (UINT)(x); (x) = (UINT)(y); (y) = temp; } while(0) |
| #define ORDER_UINT(x,y) do { if ((UINT)(y) < (UINT)(x)) SWAP_UINT((x),(y)); } while(0) |
| |
| /* macros to access window styles */ |
| #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE) |
| #define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL) |
| #define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL) |
| #define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY) |
| #define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0) |
| #define IsPassword(wndPtr) ((wndPtr)->dwStyle & ES_PASSWORD) |
| #define IsLower(wndPtr) ((wndPtr)->dwStyle & ES_LOWERCASE) |
| #define IsUpper(wndPtr) ((wndPtr)->dwStyle & ES_UPPERCASE) |
| |
| #define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra)) |
| |
| #ifdef WINELIB32 |
| #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \ |
| SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \ |
| (WPARAM)(hdc), (LPARAM)(wndPtr)->hwndSelf) |
| #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \ |
| SendMessage32A((wndPtr)->parent->hwndSelf, WM_COMMAND, \ |
| MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \ |
| (LPARAM)(wndPtr)->hwndSelf ) |
| #define DPRINTF_EDIT_MSG(str) \ |
| dprintf_edit(stddeb, \ |
| "edit: " str ": hwnd=%08x, wParam=%08x, lParam=%08lx\n", \ |
| (UINT)hwnd, (UINT)wParam, (DWORD)lParam) |
| #else |
| #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \ |
| SendMessage16((wndPtr)->parent->hwndSelf, WM_CTLCOLOR, \ |
| (WPARAM)(hdc), MAKELPARAM((wndPtr)->hwndSelf, CTLCOLOR_EDIT)) |
| #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \ |
| SendMessage16((wndPtr)->parent->hwndSelf, WM_COMMAND, \ |
| (wndPtr)->wIDmenu, \ |
| MAKELPARAM((wndPtr)->hwndSelf, wNotifyCode)) |
| #define DPRINTF_EDIT_MSG(str) \ |
| dprintf_edit(stddeb, \ |
| "edit: " str ": hwnd=%04x, wParam=%04x, lParam=%08lx\n", \ |
| (UINT)hwnd, (UINT)wParam, (DWORD)lParam) |
| #endif |
| |
| /********************************************************************* |
| * |
| * Declarations |
| * |
| * Files like these should really be kept in alphabetical order. |
| * |
| */ |
| LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); |
| |
| static void EDIT_BuildLineDefs(WND *wndPtr); |
| static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action); |
| static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x); |
| static void EDIT_DelEnd(WND *wndPtr); |
| static void EDIT_DelLeft(WND *wndPtr); |
| static void EDIT_DelRight(WND *wndPtr); |
| static UINT EDIT_GetAveCharWidth(WND *wndPtr); |
| static UINT EDIT_GetLineHeight(WND *wndPtr); |
| static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc); |
| static char * EDIT_GetPointer(WND *wndPtr); |
| static char * EDIT_GetPasswordPointer(WND *wndPtr); |
| static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static BOOL EDIT_GetRedraw(WND *wndPtr); |
| static UINT EDIT_GetTextWidth(WND *wndPtr); |
| static UINT EDIT_GetVisibleLineCount(WND *wndPtr); |
| static UINT EDIT_GetWndWidth(WND *wndPtr); |
| static UINT EDIT_GetXOffset(WND *wndPtr); |
| static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end); |
| static UINT EDIT_LineFromWndY(WND *wndPtr, INT y); |
| static BOOL EDIT_MakeFit(WND *wndPtr, UINT size); |
| static void EDIT_MoveBackward(WND *wndPtr, BOOL extend); |
| static void EDIT_MoveDownward(WND *wndPtr, BOOL extend); |
| static void EDIT_MoveEnd(WND *wndPtr, BOOL extend); |
| static void EDIT_MoveForward(WND *wndPtr, BOOL extend); |
| static void EDIT_MoveHome(WND *wndPtr, BOOL extend); |
| static void EDIT_MovePageDown(WND *wndPtr, BOOL extend); |
| static void EDIT_MovePageUp(WND *wndPtr, BOOL extend); |
| static void EDIT_MoveUpward(WND *wndPtr, BOOL extend); |
| static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend); |
| static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend); |
| static void EDIT_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev); |
| static UINT EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev); |
| static void EDIT_ReleasePointer(WND *wndPtr); |
| static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static void EDIT_ScrollIntoView(WND *wndPtr); |
| static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col); |
| static INT EDIT_WndYFromLine(WND *wndPtr, UINT line); |
| static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action); |
| |
| static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| |
| static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam); |
| |
| |
| /********************************************************************* |
| * |
| * General shortcuts for variable names: |
| * |
| * UINT l; line |
| * UINT c; column |
| * UINT s; offset of selection start |
| * UINT e; offset of selection end |
| * UINT sl; line on which the selection starts |
| * UINT el; line on which the selection ends |
| * UINT sc; column on which the selection starts |
| * UINT ec; column on which the selection ends |
| * UINT li; line index (offset) |
| * UINT fv; first visible line |
| * UINT vlc; vissible line count |
| * UINT lc; line count |
| * UINT lh; line height (in pixels) |
| * UINT tw; text width (in pixels) |
| * UINT ww; window width (in pixels) |
| * UINT cw; character width (average, in pixels) |
| * |
| */ |
| |
| |
| /********************************************************************* |
| * |
| * EditWndProc() |
| * |
| */ |
| LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) |
| { |
| LRESULT lResult = 0L; |
| WND *wndPtr = WIN_FindWndPtr(hwnd); |
| |
| switch (msg) { |
| case EM_CANUNDO: |
| DPRINTF_EDIT_MSG("EM_CANUNDO"); |
| lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam); |
| break; |
| case EM_EMPTYUNDOBUFFER: |
| DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER"); |
| lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam); |
| break; |
| case EM_FMTLINES: |
| DPRINTF_EDIT_MSG("EM_FMTLINES"); |
| lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam); |
| break; |
| case EM_GETFIRSTVISIBLELINE: |
| DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE"); |
| lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam); |
| break; |
| case EM_GETHANDLE: |
| DPRINTF_EDIT_MSG("EM_GETHANDLE"); |
| lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam); |
| break; |
| case EM_GETLINE: |
| DPRINTF_EDIT_MSG("EM_GETLINE"); |
| lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam); |
| break; |
| case EM_GETLINECOUNT: |
| DPRINTF_EDIT_MSG("EM_GETLINECOUNT"); |
| lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam); |
| break; |
| case EM_GETMODIFY: |
| DPRINTF_EDIT_MSG("EM_GETMODIFY"); |
| lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam); |
| break; |
| case EM_GETPASSWORDCHAR: |
| DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR"); |
| lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam); |
| break; |
| case EM_GETRECT: |
| DPRINTF_EDIT_MSG("EM_GETRECT"); |
| lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam); |
| break; |
| case EM_GETSEL: |
| DPRINTF_EDIT_MSG("EM_GETSEL"); |
| lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam); |
| break; |
| case EM_GETTHUMB: |
| DPRINTF_EDIT_MSG("EM_GETTHUMB"); |
| lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam); |
| break; |
| case EM_GETWORDBREAKPROC: |
| DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC"); |
| lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam); |
| break; |
| case EM_LIMITTEXT: |
| DPRINTF_EDIT_MSG("EM_LIMITTEXT"); |
| lResult = EDIT_EM_LimitText(wndPtr, wParam, lParam); |
| break; |
| case EM_LINEFROMCHAR: |
| DPRINTF_EDIT_MSG("EM_LINEFROMCHAR"); |
| lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam); |
| break; |
| case EM_LINEINDEX: |
| DPRINTF_EDIT_MSG("EM_LINEINDEX"); |
| lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam); |
| break; |
| case EM_LINELENGTH: |
| DPRINTF_EDIT_MSG("EM_LINELENGTH"); |
| lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam); |
| break; |
| case EM_LINESCROLL: |
| DPRINTF_EDIT_MSG("EM_LINESCROLL"); |
| lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam); |
| break; |
| case EM_REPLACESEL: |
| DPRINTF_EDIT_MSG("EM_REPLACESEL"); |
| lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam); |
| break; |
| case EM_SCROLL: |
| DPRINTF_EDIT_MSG("EM_SCROLL"); |
| lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam); |
| break; |
| case EM_SETHANDLE: |
| DPRINTF_EDIT_MSG("EM_SETHANDLE"); |
| lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam); |
| break; |
| case EM_SETMODIFY: |
| DPRINTF_EDIT_MSG("EM_SETMODIFY"); |
| lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam); |
| break; |
| case EM_SETPASSWORDCHAR: |
| DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR"); |
| lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam); |
| break; |
| case EM_SETREADONLY: |
| DPRINTF_EDIT_MSG("EM_SETREADONLY"); |
| lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam); |
| break; |
| case EM_SETRECT: |
| DPRINTF_EDIT_MSG("EM_SETRECT"); |
| lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam); |
| break; |
| case EM_SETRECTNP: |
| DPRINTF_EDIT_MSG("EM_SETRECTNP"); |
| lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam); |
| break; |
| case EM_SETSEL: |
| DPRINTF_EDIT_MSG("EM_SETSEL"); |
| lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam); |
| break; |
| case EM_SETTABSTOPS: |
| DPRINTF_EDIT_MSG("EM_SETTABSTOPS"); |
| lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam); |
| break; |
| case EM_SETWORDBREAKPROC: |
| DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC"); |
| lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam); |
| break; |
| case EM_UNDO: |
| case WM_UNDO: |
| DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO"); |
| lResult = EDIT_EM_Undo(wndPtr, wParam, lParam); |
| break; |
| case WM_GETDLGCODE: |
| DPRINTF_EDIT_MSG("WM_GETDLGCODE"); |
| lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam); |
| break; |
| case WM_CHAR: |
| DPRINTF_EDIT_MSG("WM_CHAR"); |
| lResult = EDIT_WM_Char(wndPtr, wParam, lParam); |
| break; |
| case WM_CLEAR: |
| DPRINTF_EDIT_MSG("WM_CLEAR"); |
| lResult = EDIT_WM_Clear(wndPtr, wParam, lParam); |
| break; |
| case WM_COPY: |
| DPRINTF_EDIT_MSG("WM_COPY"); |
| lResult = EDIT_WM_Copy(wndPtr, wParam, lParam); |
| break; |
| case WM_CREATE: |
| DPRINTF_EDIT_MSG("WM_CREATE"); |
| lResult = EDIT_WM_Create(wndPtr, wParam, lParam); |
| break; |
| case WM_CUT: |
| DPRINTF_EDIT_MSG("WM_CUT"); |
| lResult = EDIT_WM_Cut(wndPtr, wParam, lParam); |
| break; |
| case WM_DESTROY: |
| DPRINTF_EDIT_MSG("WM_DESTROY"); |
| lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam); |
| break; |
| case WM_ENABLE: |
| DPRINTF_EDIT_MSG("WM_ENABLE"); |
| lResult = EDIT_WM_Enable(wndPtr, wParam, lParam); |
| break; |
| case WM_ERASEBKGND: |
| DPRINTF_EDIT_MSG("WM_ERASEBKGND"); |
| lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam); |
| break; |
| case WM_GETFONT: |
| DPRINTF_EDIT_MSG("WM_GETFONT"); |
| lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam); |
| break; |
| case WM_GETTEXT: |
| DPRINTF_EDIT_MSG("WM_GETTEXT"); |
| lResult = EDIT_WM_GetText(wndPtr, wParam, lParam); |
| break; |
| case WM_GETTEXTLENGTH: |
| DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH"); |
| lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam); |
| break; |
| case WM_HSCROLL: |
| DPRINTF_EDIT_MSG("WM_HSCROLL"); |
| lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam); |
| break; |
| case WM_KEYDOWN: |
| DPRINTF_EDIT_MSG("WM_KEYDOWN"); |
| lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam); |
| break; |
| case WM_KILLFOCUS: |
| DPRINTF_EDIT_MSG("WM_KILLFOCUS"); |
| lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam); |
| break; |
| case WM_LBUTTONDBLCLK: |
| DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK"); |
| lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam); |
| break; |
| case WM_LBUTTONDOWN: |
| DPRINTF_EDIT_MSG("WM_LBUTTONDOWN"); |
| lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam); |
| break; |
| case WM_LBUTTONUP: |
| DPRINTF_EDIT_MSG("WM_LBUTTONUP"); |
| lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam); |
| break; |
| case WM_MOUSEMOVE: |
| /* |
| * DPRINTF_EDIT_MSG("WM_MOUSEMOVE"); |
| */ |
| lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam); |
| break; |
| case WM_PAINT: |
| DPRINTF_EDIT_MSG("WM_PAINT"); |
| lResult = EDIT_WM_Paint(wndPtr, wParam, lParam); |
| break; |
| case WM_PASTE: |
| DPRINTF_EDIT_MSG("WM_PASTE"); |
| lResult = EDIT_WM_Paste(wndPtr, wParam, lParam); |
| break; |
| case WM_SETCURSOR: |
| /* |
| * DPRINTF_EDIT_MSG("WM_SETCURSOR"); |
| */ |
| lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam); |
| break; |
| case WM_SETFOCUS: |
| DPRINTF_EDIT_MSG("WM_SETFOCUS"); |
| lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam); |
| break; |
| case WM_SETFONT: |
| DPRINTF_EDIT_MSG("WM_SETFONT"); |
| lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam); |
| break; |
| case WM_SETREDRAW: |
| DPRINTF_EDIT_MSG("WM_SETREDRAW"); |
| lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam); |
| break; |
| case WM_SETTEXT: |
| DPRINTF_EDIT_MSG("WM_SETTEXT"); |
| lResult = EDIT_WM_SetText(wndPtr, wParam, lParam); |
| break; |
| case WM_SIZE: |
| DPRINTF_EDIT_MSG("WM_SIZE"); |
| lResult = EDIT_WM_Size(wndPtr, wParam, lParam); |
| break; |
| case WM_VSCROLL: |
| DPRINTF_EDIT_MSG("WM_VSCROLL"); |
| lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam); |
| break; |
| default: |
| if (msg >= WM_USER) |
| fprintf(stdnimp, "edit: undocumented message %d >= WM_USER, please report.\n", msg); |
| lResult = DefWindowProc16(hwnd, msg, wParam, lParam); |
| break; |
| } |
| EDIT_ReleasePointer(wndPtr); |
| return lResult; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_BuildLineDefs |
| * |
| * Build array of pointers to text lines. |
| * Lines can end with '\0' (last line), nothing (if it is too long), |
| * a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n' |
| * |
| */ |
| static void EDIT_BuildLineDefs(WND *wndPtr) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| char *text = EDIT_GetPasswordPointer(wndPtr); |
| int ww = EDIT_GetWndWidth(wndPtr); |
| HDC hdc; |
| HFONT hFont; |
| HFONT oldFont = 0; |
| char *start, *cp; |
| int prev, next; |
| int width; |
| int length; |
| LINE_END ending; |
| |
| hdc = GetDC(wndPtr->hwndSelf); |
| hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L); |
| if (hFont) |
| oldFont = SelectObject(hdc, hFont); |
| |
| if (!IsMultiLine(wndPtr)) { |
| es->LineCount = 1; |
| es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF)); |
| es->LineDefs[0].offset = 0; |
| es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0L); |
| es->LineDefs[0].ending = END_0; |
| es->TextWidth = LOWORD(GetTabbedTextExtent(hdc, text, |
| es->LineDefs[0].length, |
| es->NumTabStops, es->TabStops)); |
| } else { |
| es->LineCount = 0; |
| start = text; |
| do { |
| if (!(cp = strstr(start, "\r\n"))) { |
| ending = END_0; |
| length = strlen(start); |
| } else if ((cp > start) && (*(cp - 1) == '\r')) { |
| ending = END_SOFT; |
| length = cp - start - 1; |
| } else { |
| ending = END_HARD; |
| length = cp - start; |
| } |
| width = LOWORD(GetTabbedTextExtent(hdc, start, length, |
| es->NumTabStops, es->TabStops)); |
| |
| if (IsWordWrap(wndPtr) && (width > ww)) { |
| next = 0; |
| do { |
| prev = next; |
| next = EDIT_CallWordBreakProc(wndPtr, start, |
| prev + 1, length, WB_RIGHT); |
| width = LOWORD(GetTabbedTextExtent(hdc, start, next, |
| es->NumTabStops, es->TabStops)); |
| } while (width <= ww); |
| if (!prev) { |
| next = 0; |
| do { |
| prev = next; |
| next++; |
| width = LOWORD(GetTabbedTextExtent(hdc, start, next, |
| es->NumTabStops, es->TabStops)); |
| } while (width <= ww); |
| if(!prev) prev = 1; |
| } |
| length = prev; |
| if (EDIT_CallWordBreakProc(wndPtr, start, length - 1, |
| length, WB_ISDELIMITER)) { |
| length--; |
| ending = END_DELIMIT; |
| } else |
| ending = END_NONE; |
| width = LOWORD(GetTabbedTextExtent(hdc, start, length, |
| es->NumTabStops, es->TabStops)); |
| } |
| |
| es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF)); |
| es->LineDefs[es->LineCount].offset = start - text; |
| es->LineDefs[es->LineCount].length = length; |
| es->LineDefs[es->LineCount].ending = ending; |
| es->LineCount++; |
| es->TextWidth = MAX(es->TextWidth, width); |
| |
| start += length; |
| switch (ending) { |
| case END_SOFT: |
| start += 3; |
| break; |
| case END_HARD: |
| start += 2; |
| break; |
| case END_DELIMIT: |
| start++; |
| break; |
| default: |
| break; |
| } |
| } while (*start || (ending == END_SOFT) || (ending == END_HARD)); |
| } |
| if (hFont) |
| SelectObject(hdc, oldFont); |
| ReleaseDC(wndPtr->hwndSelf, hdc); |
| |
| free(text); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_CallWordBreakProc |
| * |
| * Call appropriate WordBreakProc (internal or external). |
| * |
| */ |
| static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action) |
| { |
| EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0L); |
| |
| if (wbp) { |
| return CallWordBreakProc((FARPROC)wbp, |
| (LONG)MAKE_SEGPTR(s), index, count, action); |
| } else |
| return EDIT_WordBreakProc(s, index, count, action); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_ColFromWndX |
| * |
| * Calculates, for a given line and X-coordinate on the screen, the column. |
| * |
| */ |
| static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x) |
| { |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L); |
| UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L); |
| UINT i; |
| |
| line = MAX(0, MIN(line, lc - 1)); |
| for (i = 0 ; i < ll ; i++) |
| if (EDIT_WndXFromCol(wndPtr, line, i) >= x) |
| break; |
| return i; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_DelEnd |
| * |
| * Delete all characters on this line to right of cursor. |
| * |
| */ |
| static void EDIT_DelEnd(WND *wndPtr) |
| { |
| EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0)); |
| EDIT_MoveEnd(wndPtr, TRUE); |
| EDIT_WM_Clear(wndPtr, 0, 0L); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_DelLeft |
| * |
| * Delete character to left of cursor. |
| * |
| */ |
| static void EDIT_DelLeft(WND *wndPtr) |
| { |
| EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0)); |
| EDIT_MoveBackward(wndPtr, TRUE); |
| EDIT_WM_Clear(wndPtr, 0, 0L); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_DelRight |
| * |
| * Delete character to right of cursor. |
| * |
| */ |
| static void EDIT_DelRight(WND *wndPtr) |
| { |
| EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0)); |
| EDIT_MoveForward(wndPtr, TRUE); |
| EDIT_WM_Clear(wndPtr, 0, 0L); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetAveCharWidth |
| * |
| */ |
| static UINT EDIT_GetAveCharWidth(WND *wndPtr) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return es->AveCharWidth; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetLineHeight |
| * |
| */ |
| static UINT EDIT_GetLineHeight(WND *wndPtr) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return es->LineHeight; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetLineRect |
| * |
| * Calculates the bounding rectangle for a line from a starting |
| * column to an ending column. |
| * |
| */ |
| static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc) |
| { |
| rc->top = EDIT_WndYFromLine(wndPtr, line); |
| rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr); |
| rc->left = EDIT_WndXFromCol(wndPtr, line, scol); |
| rc->right = ((INT)ecol == -1) ? EDIT_GetWndWidth(wndPtr) : |
| EDIT_WndXFromCol(wndPtr, line, ecol); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetPointer |
| * |
| * This acts as a LOCAL_Lock(), but it locks only once. This way |
| * you can call it whenever you like, without unlocking. |
| * |
| */ |
| static char *EDIT_GetPointer(WND *wndPtr) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| if (!es->text && es->hBuf) |
| es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf); |
| return es->text; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetPasswordPointer |
| * |
| * |
| */ |
| static char *EDIT_GetPasswordPointer(WND *wndPtr) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| char *text = xstrdup(EDIT_GetPointer(wndPtr)); |
| char *p; |
| |
| if(es->PasswordChar) { |
| p = text; |
| while(*p != '\0') { |
| if(*p != '\r' && *p != '\n') |
| *p = es->PasswordChar; |
| p++; |
| } |
| } |
| return text; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetRect |
| * |
| * Beware: This is not the function called on EM_GETRECT. |
| * It expects a (LPRECT) in lParam, not a (SEGPTR). |
| * It is used internally, as if there were no pointer difficulties. |
| * |
| */ |
| static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| GetClientRect16( wndPtr->hwndSelf, (LPRECT16)lParam ); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetRedraw |
| * |
| */ |
| static BOOL EDIT_GetRedraw(WND *wndPtr) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return es->Redraw; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetTextWidth |
| * |
| */ |
| static UINT EDIT_GetTextWidth(WND *wndPtr) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return es->TextWidth; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetVisibleLineCount |
| * |
| */ |
| static UINT EDIT_GetVisibleLineCount(WND *wndPtr) |
| { |
| RECT16 rc; |
| |
| EDIT_GetRect(wndPtr, 0, (LPARAM)&rc); |
| return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetWndWidth |
| * |
| */ |
| static UINT EDIT_GetWndWidth(WND *wndPtr) |
| { |
| RECT16 rc; |
| |
| EDIT_GetRect(wndPtr, 0, (LPARAM)&rc); |
| return rc.right - rc.left; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_GetXOffset |
| * |
| */ |
| static UINT EDIT_GetXOffset(WND *wndPtr) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return es->XOffset; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_InvalidateText |
| * |
| * Invalidate the text from offset start upto, but not including, |
| * offset end. Useful for (re)painting the selection. |
| * Regions outside the linewidth are not invalidated. |
| * end == -1 means end == TextLength. |
| * start and end need not be ordered. |
| * |
| */ |
| static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end) |
| { |
| UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| UINT vlc = EDIT_GetVisibleLineCount(wndPtr); |
| UINT sl; |
| UINT el; |
| UINT sc; |
| UINT ec; |
| RECT16 rcWnd; |
| RECT16 rcLine; |
| RECT16 rcUpdate; |
| UINT l; |
| |
| if (end == start ) |
| return; |
| |
| if ((INT)end == -1) |
| end = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L); |
| ORDER_UINT(start, end); |
| sl = (UINT)EDIT_EM_LineFromChar(wndPtr, start, 0L); |
| el = (UINT)EDIT_EM_LineFromChar(wndPtr, end, 0L); |
| if ((el < fv) || (sl > fv + vlc)) |
| return; |
| |
| sc = start - (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L); |
| ec = end - (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L); |
| if (sl < fv) { |
| sl = fv; |
| sc = 0; |
| } |
| if (el > fv + vlc) { |
| el = fv + vlc; |
| ec = (UINT)EDIT_EM_LineLength(wndPtr, |
| (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L), 0L); |
| } |
| EDIT_GetRect(wndPtr, 0, (LPARAM)&rcWnd); |
| if (sl == el) { |
| EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine); |
| if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine)) |
| InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE ); |
| } else { |
| EDIT_GetLineRect(wndPtr, sl, sc, |
| (UINT)EDIT_EM_LineLength(wndPtr, |
| (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L), 0L), |
| &rcLine); |
| if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine)) |
| InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE ); |
| for (l = sl + 1 ; l < el ; l++) { |
| EDIT_GetLineRect(wndPtr, l, 0, |
| (UINT)EDIT_EM_LineLength(wndPtr, |
| (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L), 0L), |
| &rcLine); |
| if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine)) |
| InvalidateRect16(wndPtr->hwndSelf, &rcUpdate, FALSE); |
| } |
| EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine); |
| if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine)) |
| InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE ); |
| } |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_LineFromWndY |
| * |
| * Calculates, for a given Y-coordinate on the screen, the line. |
| * |
| */ |
| static UINT EDIT_LineFromWndY(WND *wndPtr, INT y) |
| { |
| UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| UINT lh = EDIT_GetLineHeight(wndPtr); |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L); |
| |
| return MAX(0, MIN(lc - 1, y / lh + fv)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MakeFit |
| * |
| * Try to fit size + 1 bytes in the buffer. Constrain to limits. |
| * |
| */ |
| static BOOL EDIT_MakeFit(WND *wndPtr, UINT size) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| if (size <= es->BufSize) |
| return TRUE; |
| if (size > es->BufLimit) |
| return FALSE; |
| size = ((size / GROWLENGTH) + 1) * GROWLENGTH; |
| if (size > es->BufLimit) |
| size = es->BufLimit; |
| |
| dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size); |
| |
| if (LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, size + 1, LMEM_MOVEABLE)) { |
| es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1, es->BufLimit); |
| return TRUE; |
| } else |
| return FALSE; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MoveBackward |
| * |
| */ |
| static void EDIT_MoveBackward(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| |
| if (e - li == 0) { |
| if (l) { |
| li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L); |
| e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L); |
| } |
| } else |
| e--; |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MoveDownward |
| * |
| */ |
| static void EDIT_MoveDownward(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| INT x; |
| |
| if (l < lc - 1) { |
| x = EDIT_WndXFromCol(wndPtr, l, e - li); |
| l++; |
| e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) + |
| EDIT_ColFromWndX(wndPtr, l, x); |
| } |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MoveEnd |
| * |
| */ |
| static void EDIT_MoveEnd(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| |
| e = li + ll; |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MoveForward |
| * |
| */ |
| static void EDIT_MoveForward(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L); |
| UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| |
| if (e - li == ll) { |
| if (l != lc - 1) |
| e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L); |
| } else |
| e++; |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MoveHome |
| * |
| * Home key: move to beginning of line. |
| * |
| */ |
| static void EDIT_MoveHome(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| |
| e = li; |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MovePageDown |
| * |
| */ |
| static void EDIT_MovePageDown(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| INT x; |
| |
| if (l < lc - 1) { |
| x = EDIT_WndXFromCol(wndPtr, l, e - li); |
| l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr)); |
| e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) + |
| EDIT_ColFromWndX(wndPtr, l, x); |
| } |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MovePageUp |
| * |
| */ |
| static void EDIT_MovePageUp(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| INT x; |
| |
| if (l) { |
| x = EDIT_WndXFromCol(wndPtr, l, e - li); |
| l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr)); |
| e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) + |
| EDIT_ColFromWndX(wndPtr, l, x); |
| } |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MoveUpward |
| * |
| */ |
| static void EDIT_MoveUpward(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| INT x; |
| |
| if (l) { |
| x = EDIT_WndXFromCol(wndPtr, l, e - li); |
| l--; |
| e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) + |
| EDIT_ColFromWndX(wndPtr, l, x); |
| } |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MoveWordBackward |
| * |
| */ |
| static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| char *text; |
| |
| if (e - li == 0) { |
| if (l) { |
| li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L); |
| e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L); |
| } |
| } else { |
| text = EDIT_GetPointer(wndPtr); |
| e = li + (UINT)EDIT_CallWordBreakProc(wndPtr, |
| text + li, e - li, ll, WB_LEFT); |
| } |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_MoveWordForward |
| * |
| */ |
| static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L); |
| UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| char *text; |
| |
| if (e - li == ll) { |
| if (l != lc - 1) |
| e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L); |
| } else { |
| text = EDIT_GetPointer(wndPtr); |
| e = li + (UINT)EDIT_CallWordBreakProc(wndPtr, |
| text + li, e - li + 1, ll, WB_RIGHT); |
| } |
| if (!extend) |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_PaintLine |
| * |
| */ |
| static void EDIT_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev) |
| { |
| UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| UINT vlc = EDIT_GetVisibleLineCount(wndPtr); |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L); |
| UINT li; |
| UINT ll; |
| UINT s; |
| UINT e; |
| INT x; |
| INT y; |
| |
| if ((line < fv) || (line > fv + vlc) || (line >= lc)) |
| return; |
| |
| dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line); |
| |
| x = EDIT_WndXFromCol(wndPtr, line, 0); |
| y = EDIT_WndYFromLine(wndPtr, line); |
| li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L); |
| ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L); |
| s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| ORDER_UINT(s, e); |
| s = MIN(li + ll, MAX(li, s)); |
| e = MIN(li + ll, MAX(li, e)); |
| if (rev && (s != e) && |
| ((GetFocus() == wndPtr->hwndSelf) || |
| (wndPtr->dwStyle & ES_NOHIDESEL))) { |
| x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE); |
| x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE); |
| x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE); |
| } else |
| x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_PaintText |
| * |
| */ |
| static UINT EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| COLORREF BkColor; |
| COLORREF TextColor; |
| UINT ret; |
| char *text; |
| UINT li; |
| UINT xoff; |
| |
| if (!count) |
| return 0; |
| BkColor = GetBkColor(hdc); |
| TextColor = GetTextColor(hdc); |
| if (rev) { |
| SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); |
| SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); |
| } |
| text = EDIT_GetPasswordPointer(wndPtr); |
| li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L); |
| xoff = EDIT_GetXOffset(wndPtr); |
| ret = LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count, |
| es->NumTabStops, es->TabStops, -xoff)); |
| free(text); |
| if (rev) { |
| SetBkColor(hdc, BkColor); |
| SetTextColor(hdc, TextColor); |
| } |
| return ret; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_ReleasePointer |
| * |
| * This is the only helper function that can be called with es = NULL. |
| * It is called at the end of EditWndProc() to unlock the buffer. |
| * |
| */ |
| static void EDIT_ReleasePointer(WND *wndPtr) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| if (!es) |
| return; |
| if (es->text && es->hBuf) |
| LOCAL_Unlock(wndPtr->hInstance, es->hBuf); |
| es->text = NULL; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_ReplaceSel |
| * |
| * Beware: This is not the function called on EM_REPLACESEL. |
| * It expects a (char *) in lParam, not a (SEGPTR). |
| * It is used internally, as if there were no pointer difficulties. |
| * |
| */ |
| static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| const char *str = (char *)lParam; |
| int strl = strlen(str); |
| UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L); |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| int i; |
| char *p; |
| char *text; |
| BOOL redraw; |
| |
| ORDER_UINT(s,e); |
| if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) { |
| EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT); |
| return 0L; |
| } |
| redraw = EDIT_GetRedraw(wndPtr); |
| EDIT_WM_SetRedraw(wndPtr, FALSE, 0L); |
| EDIT_WM_Clear(wndPtr, 0, 0L); |
| tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L); |
| e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| text = EDIT_GetPointer(wndPtr); |
| for (p = text + tl ; p >= text + e ; p--) |
| p[strl] = p[0]; |
| for (i = 0 , p = text + e ; i < strl ; i++) |
| p[i] = str[i]; |
| if(IsUpper(wndPtr)) |
| AnsiUpperBuff(p, strl); |
| else if(IsLower(wndPtr)) |
| AnsiLowerBuff(p, strl); |
| EDIT_BuildLineDefs(wndPtr); |
| e += strl; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(e, e)); |
| EDIT_EM_SetModify(wndPtr, TRUE, 0L); |
| EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE); |
| EDIT_WM_SetRedraw(wndPtr, redraw, 0L); |
| if (redraw) { |
| InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); |
| EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE); |
| } |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_ScrollIntoView |
| * |
| * Makes sure the caret is visible. |
| * |
| */ |
| static void EDIT_ScrollIntoView(WND *wndPtr) |
| { |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| UINT vlc = EDIT_GetVisibleLineCount(wndPtr); |
| UINT ww = EDIT_GetWndWidth(wndPtr); |
| UINT cw = EDIT_GetAveCharWidth(wndPtr); |
| INT x = EDIT_WndXFromCol(wndPtr, l, e - li); |
| int dy = 0; |
| int dx = 0; |
| |
| if (l >= fv + vlc) |
| dy = l - vlc + 1 - fv; |
| if (l < fv) |
| dy = l - fv; |
| if (x < 0) |
| dx = x - ww / HSCROLL_FRACTION / cw * cw; |
| if (x > ww) |
| dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw; |
| if (dy || dx) { |
| EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, dx)); |
| if (dy) |
| EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL); |
| if (dx) |
| EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL); |
| } |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_WndXFromCol |
| * |
| * Calculates, for a given line and column, the X-coordinate on the screen. |
| * |
| */ |
| static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| char *text = EDIT_GetPasswordPointer(wndPtr); |
| INT ret; |
| HDC hdc; |
| HFONT hFont; |
| HFONT oldFont = 0; |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L); |
| UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L); |
| UINT xoff = EDIT_GetXOffset(wndPtr); |
| |
| hdc = GetDC(wndPtr->hwndSelf); |
| hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L); |
| if (hFont) |
| oldFont = SelectObject(hdc, hFont); |
| line = MAX(0, MIN(line, lc - 1)); |
| col = MIN(col, ll); |
| ret = LOWORD(GetTabbedTextExtent(hdc, |
| text + li, col, |
| es->NumTabStops, es->TabStops)) - xoff; |
| if (hFont) |
| SelectObject(hdc, oldFont); |
| ReleaseDC(wndPtr->hwndSelf, hdc); |
| free(text); |
| return ret; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_WndYFromLine |
| * |
| * Calculates, for a given line, the Y-coordinate on the screen. |
| * |
| */ |
| static INT EDIT_WndYFromLine(WND *wndPtr, UINT line) |
| { |
| UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| UINT lh = EDIT_GetLineHeight(wndPtr); |
| |
| return (line - fv) * lh; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EDIT_WordBreakProc |
| * |
| * Find the beginning of words. |
| * Note: unlike the specs for a WordBreakProc, this function only |
| * allows to be called without linebreaks between s[0] upto |
| * s[count - 1]. Remember it is only called |
| * internally, so we can decide this for ourselves. |
| * |
| */ |
| static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action) |
| { |
| INT ret = 0; |
| |
| dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%d" |
| ", count=%d, action=%d\n", s, index, count, action); |
| |
| switch (action) { |
| case WB_LEFT: |
| if (!count) |
| break; |
| if (index) |
| index--; |
| if (s[index] == ' ') { |
| while (index && (s[index] == ' ')) |
| index--; |
| if (index) { |
| while (index && (s[index] != ' ')) |
| index--; |
| if (s[index] == ' ') |
| index++; |
| } |
| } else { |
| while (index && (s[index] != ' ')) |
| index--; |
| if (s[index] == ' ') |
| index++; |
| } |
| ret = index; |
| break; |
| case WB_RIGHT: |
| if (!count) |
| break; |
| if (index) |
| index--; |
| if (s[index] == ' ') |
| while ((index < count) && (s[index] == ' ')) index++; |
| else { |
| while (s[index] && (s[index] != ' ') && (index < count)) |
| index++; |
| while ((s[index] == ' ') && (index < count)) index++; |
| } |
| ret = index; |
| break; |
| case WB_ISDELIMITER: |
| ret = (s[index] == ' '); |
| break; |
| default: |
| fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n"); |
| break; |
| } |
| return ret; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_CANUNDO |
| * |
| */ |
| static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_EMPTYUNDOBUFFER |
| * |
| */ |
| static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_FMTLINES |
| * |
| */ |
| static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented.\n"); |
| return wParam ? -1L : 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETFIRSTVISIBLELINE |
| * |
| */ |
| static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return (LRESULT)es->FirstVisibleLine; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETHANDLE |
| * |
| */ |
| static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return (LRESULT)es->hBuf; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETLINE |
| * |
| */ |
| static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| char *text; |
| char *src; |
| char *dst; |
| UINT len; |
| UINT i; |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L); |
| |
| if (!IsMultiLine(wndPtr)) |
| wParam = 0; |
| if ((UINT)wParam >= lc) |
| return 0L; |
| text = EDIT_GetPointer(wndPtr); |
| src = text + (UINT)EDIT_EM_LineIndex(wndPtr, wParam, 0L); |
| dst = (char *)PTR_SEG_TO_LIN(lParam); |
| len = MIN(*(WORD *)dst, (UINT)EDIT_EM_LineLength(wndPtr, wParam, 0L)); |
| for (i = 0 ; i < len ; i++) { |
| *dst = *src; |
| src++; |
| dst++; |
| } |
| return (LRESULT)len; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETLINECOUNT |
| * |
| */ |
| static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return (LRESULT)es->LineCount; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETMODIFY |
| * |
| */ |
| static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return (LRESULT)es->TextChanged; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETPASSWORDCHAR |
| * |
| */ |
| static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return (LRESULT)es->PasswordChar; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETRECT |
| * |
| */ |
| static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| return EDIT_GetRect(wndPtr, wParam, (LPARAM)PTR_SEG_TO_LIN(lParam)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETSEL |
| * |
| */ |
| static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return MAKELONG(es->SelStart, es->SelEnd); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETTHUMB |
| * |
| * FIXME: undocumented: is this right ? |
| * |
| */ |
| static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), |
| EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_GETWORDBREAKPROC |
| * |
| */ |
| static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return (LRESULT)es->WordBreakProc; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_LIMITTEXT |
| * |
| */ |
| static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| if (IsMultiLine(wndPtr)) { |
| if (wParam) |
| es->BufLimit = MIN((UINT)wParam, BUFLIMIT_MULTI); |
| else |
| es->BufLimit = BUFLIMIT_MULTI; |
| } else { |
| if (wParam) |
| es->BufLimit = MIN((UINT)wParam, BUFLIMIT_SINGLE); |
| else |
| es->BufLimit = BUFLIMIT_SINGLE; |
| } |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_LINEFROMCHAR |
| * |
| */ |
| static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| UINT l; |
| |
| if (!IsMultiLine(wndPtr)) |
| return 0L; |
| if ((INT)wParam == -1) |
| wParam = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| l = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1; |
| while ((UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam) |
| l--; |
| return (LRESULT)l; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_LINEINDEX |
| * |
| */ |
| static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| UINT e; |
| UINT l; |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L); |
| |
| if ((INT)wParam == -1) { |
| e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| l = lc - 1; |
| while (es->LineDefs[l].offset > e) |
| l--; |
| return (LRESULT)es->LineDefs[l].offset; |
| } |
| if ((UINT)wParam >= lc) |
| return -1L; |
| return (LRESULT)es->LineDefs[(UINT)wParam].offset; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_LINELENGTH |
| * |
| */ |
| static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| UINT s; |
| UINT e; |
| UINT sl; |
| UINT el; |
| |
| if (!IsMultiLine(wndPtr)) |
| return (LRESULT)es->LineDefs[0].length; |
| if ((INT)wParam == -1) { |
| s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| sl = (UINT)EDIT_EM_LineFromChar(wndPtr, s, 0L); |
| el = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| return (LRESULT)(s - es->LineDefs[sl].offset + |
| es->LineDefs[el].offset + |
| es->LineDefs[el].length - e); |
| } |
| return (LRESULT)es->LineDefs[(UINT)EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_LINESCROLL |
| * |
| */ |
| static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L); |
| UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| UINT nfv = MAX(0, fv + (INT)LOWORD(lParam)); |
| UINT xoff = EDIT_GetXOffset(wndPtr); |
| UINT nxoff = MAX(0, xoff + (INT)HIWORD(lParam)); |
| UINT tw = EDIT_GetTextWidth(wndPtr); |
| INT dx; |
| INT dy; |
| POINT16 pos; |
| HRGN hRgn; |
| |
| if (nfv >= lc) |
| nfv = lc - 1; |
| |
| if (nxoff >= tw) |
| nxoff = tw; |
| dx = xoff - nxoff; |
| dy = EDIT_WndYFromLine(wndPtr, fv) - EDIT_WndYFromLine(wndPtr, nfv); |
| if (dx || dy) { |
| if (wndPtr->hwndSelf == GetFocus()) |
| HideCaret(wndPtr->hwndSelf); |
| if (EDIT_GetRedraw(wndPtr)) { |
| hRgn = CreateRectRgn(0, 0, 0, 0); |
| GetUpdateRgn(wndPtr->hwndSelf, hRgn, FALSE); |
| ValidateRgn(wndPtr->hwndSelf, 0); |
| OffsetRgn(hRgn, dx, dy); |
| InvalidateRgn( wndPtr->hwndSelf, hRgn, TRUE ); |
| DeleteObject(hRgn); |
| ScrollWindow(wndPtr->hwndSelf, dx, dy, NULL, NULL); |
| } |
| es->FirstVisibleLine = nfv; |
| es->XOffset = nxoff; |
| if (IsVScrollBar(wndPtr)) |
| SetScrollPos(wndPtr->hwndSelf, SB_VERT, |
| EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE); |
| if (IsHScrollBar(wndPtr)) |
| SetScrollPos(wndPtr->hwndSelf, SB_HORZ, |
| EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE); |
| if (wndPtr->hwndSelf == GetFocus()) { |
| GetCaretPos16(&pos); |
| SetCaretPos(pos.x + dx, pos.y + dy); |
| ShowCaret(wndPtr->hwndSelf); |
| } |
| } |
| return -1L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_REPLACESEL |
| * |
| */ |
| static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| return (LRESULT)EDIT_ReplaceSel(wndPtr, wParam, |
| (LPARAM)(char *)PTR_SEG_TO_LIN(lParam)); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SCROLL |
| * |
| * FIXME: undocumented message. |
| * |
| */ |
| static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| fprintf(stdnimp, "edit: EM_SCROLL: message not implemented (undocumented), please report.\n"); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SETHANDLE |
| * |
| */ |
| static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| if (IsMultiLine(wndPtr)) { |
| EDIT_ReleasePointer(wndPtr); |
| /* |
| * old buffer is freed by caller |
| */ |
| es->hBuf = (HLOCAL16)wParam; |
| es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1; |
| es->LineCount = 0; |
| es->FirstVisibleLine = 0; |
| es->SelStart = es->SelEnd = 0; |
| EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L); |
| EDIT_EM_SetModify(wndPtr, FALSE, 0L); |
| EDIT_BuildLineDefs(wndPtr); |
| if (EDIT_GetRedraw(wndPtr)) |
| InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); |
| EDIT_ScrollIntoView(wndPtr); |
| } |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SETMODIFY |
| * |
| */ |
| static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| es->TextChanged = (BOOL)wParam; |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SETPASSWORDCHAR |
| * |
| */ |
| static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| es->PasswordChar = (char)wParam; |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SETREADONLY |
| * |
| */ |
| static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| if ((BOOL)wParam) |
| wndPtr->dwStyle |= ES_READONLY; |
| else |
| wndPtr->dwStyle &= ~(DWORD)ES_READONLY; |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SETRECT |
| * |
| */ |
| static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| fprintf(stdnimp,"edit: EM_SETRECT: message not implemented, please report.\n"); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SETRECTNP |
| * |
| */ |
| static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented, please report.\n"); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SETSEL |
| * |
| */ |
| static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| UINT ns = LOWORD(lParam); |
| UINT ne = HIWORD(lParam); |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT el; |
| UINT eli; |
| UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L); |
| |
| if ((INT)ns == -1) { |
| ns = e; |
| ne = e; |
| } |
| else { |
| ns = MIN(ns, tl); |
| ne = MIN(ne, tl); |
| } |
| es->SelStart = ns; |
| es->SelEnd = ne; |
| if (wndPtr->hwndSelf == GetFocus()) { |
| el = (UINT)EDIT_EM_LineFromChar(wndPtr, ne, 0L); |
| eli = (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L); |
| SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - eli), |
| EDIT_WndYFromLine(wndPtr, el)); |
| } |
| if (!wParam) |
| EDIT_ScrollIntoView(wndPtr); |
| if (EDIT_GetRedraw(wndPtr)) { |
| ORDER_UINT(s, e); |
| ORDER_UINT(s, ns); |
| ORDER_UINT(s, ne); |
| ORDER_UINT(e, ns); |
| ORDER_UINT(e, ne); |
| ORDER_UINT(ns, ne); |
| if (e != ns) { |
| EDIT_InvalidateText(wndPtr, s, e); |
| EDIT_InvalidateText(wndPtr, ns, ne); |
| } else |
| EDIT_InvalidateText(wndPtr, s, ne); |
| } |
| return -1L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SETTABSTOPS |
| * |
| */ |
| static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| if (!IsMultiLine(wndPtr)) |
| return 0L; |
| if (es->TabStops) |
| free(es->TabStops); |
| es->NumTabStops = (UINT)wParam; |
| if (!wParam) |
| es->TabStops = NULL; |
| else { |
| es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16)); |
| memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam), |
| (UINT)wParam * sizeof(INT16)); |
| } |
| return 1L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_SETWORDBREAKPROC |
| * |
| */ |
| static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| es->WordBreakProc = (EDITWORDBREAKPROC)lParam; |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * EM_UNDO |
| * |
| */ |
| static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_CHAR |
| * |
| */ |
| static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| char str[2]; |
| char c = (char)wParam; |
| |
| switch (c) { |
| case '\r': |
| case '\n': |
| if (IsMultiLine(wndPtr)) { |
| if (IsReadOnly(wndPtr)) { |
| EDIT_MoveHome(wndPtr, FALSE); |
| EDIT_MoveDownward(wndPtr, FALSE); |
| } else |
| EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n"); |
| } |
| break; |
| case '\t': |
| if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr)) |
| EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\t"); |
| break; |
| default: |
| if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) { |
| str[0] = c; |
| str[1] = '\0'; |
| EDIT_ReplaceSel(wndPtr, 0, (LPARAM)str); |
| } |
| break; |
| } |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_CLEAR |
| * |
| */ |
| static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| char *text; |
| BOOL redraw; |
| |
| if (s != e) { |
| redraw = EDIT_GetRedraw(wndPtr); |
| EDIT_WM_SetRedraw(wndPtr, FALSE, 0L); |
| ORDER_UINT(s, e); |
| text = EDIT_GetPointer(wndPtr); |
| strcpy(text + s, text + e); |
| EDIT_BuildLineDefs(wndPtr); |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, s)); |
| EDIT_EM_SetModify(wndPtr, TRUE, 0L); |
| EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE); |
| EDIT_WM_SetRedraw(wndPtr, redraw, 0L); |
| if (redraw) { |
| InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); |
| EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE); |
| } |
| } |
| return -1L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_COPY |
| * |
| */ |
| static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| HGLOBAL hdst; |
| char *text; |
| char *dst; |
| char *src; |
| int i; |
| |
| if (e == s) |
| return -1L; |
| ORDER_UINT(s, e); |
| hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1)); |
| dst = GlobalLock16(hdst); |
| text = EDIT_GetPointer(wndPtr); |
| src = text + s; |
| for (i = 0 ; i < e - s ; i++) |
| *dst++ = *src++; |
| *dst = '\0'; |
| GlobalUnlock16(hdst); |
| OpenClipboard(wndPtr->hwndSelf); |
| EmptyClipboard(); |
| SetClipboardData(CF_TEXT, hdst); |
| CloseClipboard(); |
| return -1L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_CREATE |
| * |
| */ |
| static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam); |
| EDITSTATE *es; |
| char *text; |
| |
| es = xmalloc(sizeof(EDITSTATE)); |
| memset(es, 0, sizeof(EDITSTATE)); |
| *(EDITSTATE **)wndPtr->wExtra = es; |
| |
| if (cs->style & WS_VSCROLL) |
| cs->style |= ES_AUTOVSCROLL; |
| if (cs->style & WS_HSCROLL) |
| cs->style |= ES_AUTOHSCROLL; |
| |
| /* remove the WS_CAPTION style if it has been set - this is really a */ |
| /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */ |
| if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME)) |
| cs->style ^= WS_DLGFRAME; |
| |
| if (IsMultiLine(wndPtr)) { |
| es->BufSize = BUFSTART_MULTI; |
| es->BufLimit = BUFLIMIT_MULTI; |
| es->PasswordChar = '\0'; |
| } else { |
| es->BufSize = BUFSTART_SINGLE; |
| es->BufLimit = BUFLIMIT_SINGLE; |
| es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0'; |
| } |
| if (!LOCAL_HeapSize(wndPtr->hInstance)) { |
| if (!LocalInit(wndPtr->hInstance, 0, |
| GlobalSize16(wndPtr->hInstance))) { |
| fprintf(stderr, "edit: WM_CREATE: could not initialize local heap\n"); |
| return -1L; |
| } |
| dprintf_edit(stddeb, "edit: WM_CREATE: local heap initialized\n"); |
| } |
| if (!(es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1))) { |
| fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n"); |
| return -1L; |
| } |
| es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1; |
| text = EDIT_GetPointer(wndPtr); |
| *text = '\0'; |
| EDIT_BuildLineDefs(wndPtr); |
| EDIT_WM_SetFont(wndPtr, 0, 0L); |
| if (cs->lpszName) |
| EDIT_EM_ReplaceSel(wndPtr, FALSE, (LPARAM)cs->lpszName); |
| EDIT_WM_SetRedraw(wndPtr, TRUE, 0L); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_CUT |
| * |
| */ |
| static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDIT_WM_Copy(wndPtr, 0, 0L); |
| EDIT_WM_Clear(wndPtr, 0, 0L); |
| return -1L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_DESTROY |
| * |
| */ |
| static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| free(es->LineDefs); |
| if (es->TabStops) |
| free(es->TabStops); |
| EDIT_ReleasePointer(wndPtr); |
| LOCAL_Free(wndPtr->hInstance, es->hBuf); |
| free(es); |
| *(EDITSTATE **)&wndPtr->wExtra = NULL; |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_ENABLE |
| * |
| */ |
| static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDIT_InvalidateText(wndPtr, 0, -1); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_ERASEBKGND |
| * |
| */ |
| static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| HBRUSH hBrush; |
| RECT16 rc; |
| |
| hBrush = (HBRUSH)EDIT_SEND_CTLCOLOR(wndPtr, wParam); |
| if (!hBrush) |
| hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); |
| |
| GetClientRect16(wndPtr->hwndSelf, &rc); |
| IntersectClipRect((HDC)wParam, rc.left, rc.top, rc.right, rc.bottom); |
| GetClipBox16((HDC)wParam, &rc); |
| /* |
| * FIXME: specs say that we should UnrealizeObject() the brush, |
| * but the specs of UnrealizeObject() say that we shouldn't |
| * unrealize a stock object. The default brush that |
| * DefWndProc() returns is ... a stock object. |
| */ |
| FillRect16((HDC)wParam, &rc, hBrush); |
| return -1L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_GETDLGCODE |
| * |
| */ |
| static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_GETFONT |
| * |
| */ |
| static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| return (LRESULT)es->hFont; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_GETTEXT |
| * |
| */ |
| static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| char *text = EDIT_GetPointer(wndPtr); |
| int len; |
| LRESULT lResult = 0L; |
| |
| len = strlen(text); |
| if ((UINT)wParam > len) { |
| strcpy((char *)PTR_SEG_TO_LIN(lParam), text); |
| lResult = (LRESULT)len ; |
| } |
| return lResult; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_GETTEXTLENGTH |
| * |
| */ |
| static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| char *text = EDIT_GetPointer(wndPtr); |
| |
| return (LRESULT)strlen(text); |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_HSCROLL |
| * |
| * FIXME: scrollbar code itself is broken, so this one is a hack. |
| * |
| */ |
| static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| UINT ww = EDIT_GetWndWidth(wndPtr); |
| UINT tw = EDIT_GetTextWidth(wndPtr); |
| UINT cw = EDIT_GetAveCharWidth(wndPtr); |
| UINT xoff = EDIT_GetXOffset(wndPtr); |
| INT dx = 0; |
| BOOL not = TRUE; |
| LRESULT ret = 0L; |
| |
| switch (wParam) { |
| case SB_LINELEFT: |
| dx = -cw; |
| break; |
| case SB_LINERIGHT: |
| dx = cw; |
| break; |
| case SB_PAGELEFT: |
| dx = -ww / HSCROLL_FRACTION / cw * cw; |
| break; |
| case SB_PAGERIGHT: |
| dx = ww / HSCROLL_FRACTION / cw * cw; |
| break; |
| case SB_LEFT: |
| dx = -xoff; |
| break; |
| case SB_RIGHT: |
| dx = tw - xoff; |
| break; |
| case SB_THUMBTRACK: |
| /* |
| * not = FALSE; |
| */ |
| case SB_THUMBPOSITION: |
| dx = LOWORD(lParam) * tw / 100 - xoff; |
| break; |
| /* The next two are undocumented ! */ |
| case EM_GETTHUMB: |
| ret = tw ? MAKELONG(xoff * 100 / tw, 0) : 0; |
| break; |
| case EM_LINESCROLL: |
| dx = LOWORD(lParam); |
| break; |
| case SB_ENDSCROLL: |
| default: |
| break; |
| } |
| if (dx) { |
| EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(0, dx)); |
| if (not) |
| EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL); |
| } |
| return ret; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_KEYDOWN |
| * |
| * Handling of special keys that don't produce a WM_CHAR |
| * (i.e. non-printable keys) & Backspace & Delete |
| * |
| */ |
| static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| BOOL shift; |
| BOOL control; |
| |
| if (GetKeyState(VK_MENU) & 0x8000) |
| return 0L; |
| |
| shift = GetKeyState(VK_SHIFT) & 0x8000; |
| control = GetKeyState(VK_CONTROL) & 0x8000; |
| |
| switch (wParam) { |
| case VK_LEFT: |
| case VK_UP: |
| if (IsMultiLine(wndPtr) && (wParam == VK_UP)) |
| EDIT_MoveUpward(wndPtr, shift); |
| else |
| if (control) |
| EDIT_MoveWordBackward(wndPtr, shift); |
| else |
| EDIT_MoveBackward(wndPtr, shift); |
| break; |
| case VK_RIGHT: |
| case VK_DOWN: |
| if (IsMultiLine(wndPtr) && (wParam == VK_DOWN)) |
| EDIT_MoveDownward(wndPtr, shift); |
| else if (control) |
| EDIT_MoveWordForward(wndPtr, shift); |
| else |
| EDIT_MoveForward(wndPtr, shift); |
| break; |
| case VK_HOME: |
| EDIT_MoveHome(wndPtr, shift); |
| break; |
| case VK_END: |
| EDIT_MoveEnd(wndPtr, shift); |
| break; |
| case VK_PRIOR: |
| if (IsMultiLine(wndPtr)) |
| EDIT_MovePageUp(wndPtr, shift); |
| break; |
| case VK_NEXT: |
| if (IsMultiLine(wndPtr)) |
| EDIT_MovePageDown(wndPtr, shift); |
| break; |
| case VK_BACK: |
| if (!IsReadOnly(wndPtr) && !control) |
| if (e != s) |
| EDIT_WM_Clear(wndPtr, 0, 0L); |
| else |
| EDIT_DelLeft(wndPtr); |
| break; |
| case VK_DELETE: |
| if (!IsReadOnly(wndPtr) && !(shift && control)) |
| if (e != s) { |
| if (shift) |
| EDIT_WM_Cut(wndPtr, 0, 0L); |
| else |
| EDIT_WM_Clear(wndPtr, 0, 0L); |
| } else { |
| if (shift) |
| EDIT_DelLeft(wndPtr); |
| else if (control) |
| EDIT_DelEnd(wndPtr); |
| else |
| EDIT_DelRight(wndPtr); |
| } |
| break; |
| case VK_INSERT: |
| if (shift) { |
| if (!IsReadOnly(wndPtr)) |
| EDIT_WM_Paste(wndPtr, 0, 0L); |
| } else if (control) |
| EDIT_WM_Copy(wndPtr, 0, 0L); |
| break; |
| } |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_KILLFOCUS |
| * |
| */ |
| static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| UINT s; |
| UINT e; |
| |
| DestroyCaret(); |
| if(!(wndPtr->dwStyle & ES_NOHIDESEL)) { |
| s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| EDIT_InvalidateText(wndPtr, s, e); |
| } |
| EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_LBUTTONDBLCLK |
| * |
| * The caret position has been set on the WM_LBUTTONDOWN message |
| * |
| */ |
| static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| UINT s; |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L); |
| UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L); |
| char *text = EDIT_GetPointer(wndPtr); |
| |
| s = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_LEFT); |
| e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT); |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_LBUTTONDOWN |
| * |
| */ |
| static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| INT x = (INT)LOWORD(lParam); |
| INT y = (INT)HIWORD(lParam); |
| UINT l = EDIT_LineFromWndY(wndPtr, y); |
| UINT c; |
| UINT s; |
| UINT e; |
| UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| UINT vlc = EDIT_GetVisibleLineCount(wndPtr); |
| UINT li; |
| |
| SetFocus(wndPtr->hwndSelf); |
| SetCapture(wndPtr->hwndSelf); |
| l = MIN(fv + vlc - 1, MAX(fv, l)); |
| x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x)); |
| c = EDIT_ColFromWndX(wndPtr, l, x); |
| li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| e = li + c; |
| if (GetKeyState(VK_SHIFT) & 0x8000) |
| s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| else |
| s = e; |
| EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e)); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_LBUTTONUP |
| * |
| */ |
| static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| if (GetCapture() == wndPtr->hwndSelf) |
| ReleaseCapture(); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_MOUSEMOVE |
| * |
| */ |
| static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| INT x; |
| INT y; |
| UINT l; |
| UINT c; |
| UINT s; |
| UINT fv; |
| UINT vlc; |
| UINT li; |
| |
| if (GetCapture() == wndPtr->hwndSelf) { |
| x = (INT)LOWORD(lParam); |
| y = (INT)HIWORD(lParam); |
| fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| vlc = EDIT_GetVisibleLineCount(wndPtr); |
| l = EDIT_LineFromWndY(wndPtr, y); |
| l = MIN(fv + vlc - 1, MAX(fv, l)); |
| x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x)); |
| c = EDIT_ColFromWndX(wndPtr, l, x); |
| s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L); |
| EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, li + c)); |
| } |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_PAINT |
| * |
| */ |
| static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| PAINTSTRUCT16 ps; |
| UINT i; |
| UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| UINT vlc = EDIT_GetVisibleLineCount(wndPtr); |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L); |
| HDC16 hdc; |
| HFONT hFont; |
| HFONT oldFont = 0; |
| RECT16 rc; |
| RECT16 rcLine; |
| RECT16 rcRgn; |
| BOOL rev = IsWindowEnabled(wndPtr->hwndSelf) && |
| ((GetFocus() == wndPtr->hwndSelf) || |
| (wndPtr->dwStyle & ES_NOHIDESEL)); |
| |
| hdc = BeginPaint16(wndPtr->hwndSelf, &ps); |
| GetClientRect16(wndPtr->hwndSelf, &rc); |
| IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); |
| hFont = EDIT_WM_GetFont(wndPtr, 0, 0L); |
| if (hFont) |
| oldFont = SelectObject(hdc, hFont); |
| EDIT_SEND_CTLCOLOR(wndPtr, hdc); |
| if (!IsWindowEnabled(wndPtr->hwndSelf)) |
| SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); |
| GetClipBox16(hdc, &rcRgn); |
| for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) { |
| EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine); |
| if (IntersectRect16(&rc, &rcRgn, &rcLine)) |
| EDIT_PaintLine(wndPtr, hdc, i, rev); |
| } |
| if (hFont) |
| SelectObject(hdc, oldFont); |
| EndPaint16(wndPtr->hwndSelf, &ps); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_PASTE |
| * |
| */ |
| static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| HGLOBAL hsrc; |
| char *src; |
| |
| OpenClipboard(wndPtr->hwndSelf); |
| if ((hsrc = GetClipboardData(CF_TEXT))) { |
| src = (char *)GlobalLock16(hsrc); |
| EDIT_ReplaceSel(wndPtr, 0, (LPARAM)src); |
| GlobalUnlock16(hsrc); |
| } |
| CloseClipboard(); |
| return -1L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_SETCURSOR |
| * |
| */ |
| static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| if (LOWORD(lParam) == HTCLIENT) { |
| SetCursor(LoadCursor(0, IDC_IBEAM)); |
| return -1L; |
| } else |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_SETFOCUS |
| * |
| */ |
| static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L)); |
| |
| CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr)); |
| EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, e)); |
| if(!(wndPtr->dwStyle & ES_NOHIDESEL)) |
| EDIT_InvalidateText(wndPtr, s, e); |
| ShowCaret(wndPtr->hwndSelf); |
| EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_SETFONT |
| * |
| */ |
| static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| TEXTMETRIC16 tm; |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L); |
| HDC hdc; |
| HFONT oldFont = 0; |
| |
| es->hFont = (HFONT)wParam; |
| hdc = GetDC(wndPtr->hwndSelf); |
| if (es->hFont) |
| oldFont = SelectObject(hdc, es->hFont); |
| GetTextMetrics16(hdc, &tm); |
| es->LineHeight = HIWORD(GetTextExtent(hdc, "X", 1)); |
| es->AveCharWidth = tm.tmAveCharWidth; |
| if (es->hFont) |
| SelectObject(hdc, oldFont); |
| ReleaseDC(wndPtr->hwndSelf, hdc); |
| EDIT_BuildLineDefs(wndPtr); |
| if ((BOOL)lParam && EDIT_GetRedraw(wndPtr)) |
| InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); |
| if (wndPtr->hwndSelf == GetFocus()) { |
| DestroyCaret(); |
| CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr)); |
| EDIT_EM_SetSel(wndPtr, 1, sel); |
| ShowCaret(wndPtr->hwndSelf); |
| } |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_SETREDRAW |
| * |
| */ |
| static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDITSTATE *es = EDITSTATEPTR(wndPtr); |
| |
| es->Redraw = (BOOL)wParam; |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_SETTEXT |
| * |
| */ |
| static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(0, -1)); |
| EDIT_WM_Clear(wndPtr, 0, 0L); |
| if (lParam) |
| EDIT_EM_ReplaceSel(wndPtr, 0, lParam); |
| EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L); |
| EDIT_EM_SetModify(wndPtr, TRUE, 0L); |
| EDIT_ScrollIntoView(wndPtr); |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_SIZE |
| * |
| */ |
| static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| if (EDIT_GetRedraw(wndPtr) && |
| ((wParam == SIZE_MAXIMIZED) || |
| (wParam == SIZE_RESTORED))) { |
| if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr)) |
| EDIT_BuildLineDefs(wndPtr); |
| InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); |
| } |
| return 0L; |
| } |
| |
| |
| /********************************************************************* |
| * |
| * WM_VSCROLL |
| * |
| * FIXME: scrollbar code itself is broken, so this one is a hack. |
| * |
| */ |
| static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam) |
| { |
| UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L); |
| UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L); |
| UINT vlc = EDIT_GetVisibleLineCount(wndPtr); |
| INT dy = 0; |
| BOOL not = TRUE; |
| LRESULT ret = 0L; |
| |
| switch (wParam) { |
| case SB_LINEUP: |
| dy = -1; |
| break; |
| case SB_LINEDOWN: |
| dy = 1; |
| break; |
| case SB_PAGEUP: |
| dy = -vlc; |
| break; |
| case SB_PAGEDOWN: |
| dy = vlc; |
| break; |
| case SB_TOP: |
| dy = -fv; |
| break; |
| case SB_BOTTOM: |
| dy = lc - 1 - fv; |
| break; |
| case SB_THUMBTRACK: |
| /* |
| * not = FALSE; |
| */ |
| case SB_THUMBPOSITION: |
| dy = LOWORD(lParam) * (lc - 1) / 100 - fv; |
| break; |
| /* The next two are undocumented ! */ |
| case EM_GETTHUMB: |
| ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0L; |
| break; |
| case EM_LINESCROLL: |
| dy = LOWORD(lParam); |
| break; |
| case SB_ENDSCROLL: |
| default: |
| break; |
| } |
| if (dy) { |
| EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, 0)); |
| if (not) |
| EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL); |
| } |
| return ret; |
| } |