/* * Edit control * * Copyright David W. Metcalfe, 1994 * Copyright William Magro, 1995, 1996 * Copyright Frans van Dorsselaer, 1996, 1997 * */ /* * please read EDIT.TODO (and update it when you change things) * It also contains a discussion about the 16 to 32 bit transition. * */ #define NO_TRANSITION_TYPES /* This file is Win32-clean */ #include #include #include #include "windows.h" #include "win.h" #include "local.h" #include "resource.h" #include "stddebug.h" #include "debug.h" #include "xmalloc.h" /* #include "callback.h" */ #define BUFLIMIT_MULTI 65534 /* maximum text buffer length (not including '\0') */ /* FIXME: BTW, new specs say 65535 (do you dare ???) */ #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 { INT32 offset; INT32 length; LINE_END ending; } LINEDEF; typedef struct { HLOCAL16 hBuf16; /* For when a 16-bit multiline edit * control gets a EM_GETHANDLE (which * should return 16-bit local heap). * From that point on we _have_ to keep * using 16-bit local heap (apps rely * on that ... bummer). */ HLOCAL32 hBuf32; /* Don't worry about 'LOCAL'. LOCAL32 is * identical to GLOBAL32, which is * essentially a HANDLE32 created with * HeapAlloc(GetProcessHeap(), ...) plus * a global32 (and thus local32) * descriptor, which we can return upon * EM_GETHANDLE32. * It is 32-bit linear addressing, so * everything is fine. */ LPSTR text; /* Depending on the fact that we are a * 16 or 32 bit control, this is the * pointer that we get after * LocalLock32(hBuf23) (which is a typecast :-) * or LOCAL_Lock(hBuf16). * This is always a 32-bit linear pointer. */ HFONT32 hFont; LINEDEF *LineDefs; /* Internal table for (soft) linebreaks */ INT32 TextWidth; /* width of the widest line in pixels */ INT32 XOffset; /* offset of the viewport in pixels */ INT32 FirstVisibleLine; INT32 LineCount; INT32 LineHeight; /* height of a screen line in pixels */ INT32 AveCharWidth; /* average character width in pixels */ INT32 BufLimit; INT32 BufSize; BOOL32 TextChanged; INT32 UndoInsertLen; INT32 UndoPos; INT32 UndoBufSize; HLOCAL32 hUndoBuf; LPSTR UndoText; BOOL32 Redraw; INT32 SelStart; /* offset of selection start, == SelEnd if no selection */ INT32 SelEnd; /* offset of selection end == current caret position */ INT32 NumTabStops; LPINT16 TabStops; /* * FIXME: The following should probably be a (VOID *) that is * typecast to either 16- or 32-bit callback when used, * depending on the type of edit control (16 or 32 bit). * * EDITWORDBREAKPROC WordBreakProc; * * For now: no more application specific wordbreaking. * (Internal wordbreak function still works) */ CHAR PasswordChar; INT32 LeftMargin; INT32 RightMargin; RECT32 FormatRect; } EDITSTATE; #define SWAP_INT32(x,y) do { INT32 temp = (INT32)(x); (x) = (INT32)(y); (y) = temp; } while(0) #define ORDER_INT32(x,y) do { if ((INT32)(y) < (INT32)(x)) SWAP_INT32((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)) #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \ (SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \ (WPARAM32)(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_MSG16(str) \ dprintf_edit(stddeb, \ "edit: 16 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \ (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam) #define DPRINTF_EDIT_MSG32(str) \ dprintf_edit(stddeb, \ "edit: 32 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \ (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam) /********************************************************************* * * Declarations * * Files like these should really be kept in alphabetical order. * */ LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam); static void EDIT_BuildLineDefs(WND *wndPtr); static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action); static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x); static void EDIT_DelEnd(WND *wndPtr); static void EDIT_DelLeft(WND *wndPtr); static void EDIT_DelRight(WND *wndPtr); static INT32 EDIT_GetAveCharWidth(WND *wndPtr); static INT32 EDIT_GetLineHeight(WND *wndPtr); static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc); static LPSTR EDIT_GetPointer(WND *wndPtr); static LPSTR EDIT_GetPasswordPointer(WND *wndPtr); static BOOL32 EDIT_GetRedraw(WND *wndPtr); static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e); static INT32 EDIT_GetTextWidth(WND *wndPtr); static LPSTR EDIT_GetUndoPointer(WND *wndPtr); static INT32 EDIT_GetVisibleLineCount(WND *wndPtr); static INT32 EDIT_GetWndWidth(WND *wndPtr); static INT32 EDIT_GetXOffset(WND *wndPtr); static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end); static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y); static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size); static BOOL32 EDIT_MakeUndoFit(WND *wndPtr, INT32 size); static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend); static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend); static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend); static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend); static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend); static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend); static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend); static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend); static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend); static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend); static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev); static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev); static void EDIT_ReleasePointer(WND *wndPtr); static void EDIT_ReleaseUndoPointer(WND *wndPtr); static void EDIT_SetSel(WND *wndPtr, INT32 ns, INT32 ne); static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col); static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line); static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action); static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Command(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_ContextMenu(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_InitMenuPopup(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_Timer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam); /********************************************************************* * * General shortcuts for variable names: * * INT32 l; line * INT32 c; column * INT32 s; offset of selection start * INT32 e; offset of selection end * INT32 sl; line on which the selection starts * INT32 el; line on which the selection ends * INT32 sc; column on which the selection starts * INT32 ec; column on which the selection ends * INT32 li; line index (offset) * INT32 fv; first visible line * INT32 vlc; vissible line count * INT32 lc; line count * INT32 lh; line height (in pixels) * INT32 tw; text width (in pixels) * INT32 ww; window width (in pixels) * INT32 cw; character width (average, in pixels) * */ /********************************************************************* * * EditWndProc() * * The messages are in the order of the actual integer values * (which can be found in include/windows.h) * Whereever possible the 16 bit versions are converted to * the 32 bit ones, so that we can 'fall through' to the * helper functions. These are mostly 32 bit (with a few * exceptions, clearly indicated by a '16' extension to their * names). * */ LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam) { LRESULT lResult = 0; WND *wndPtr = WIN_FindWndPtr(hwnd); if ((!EDITSTATEPTR(wndPtr)) && (msg != WM_CREATE)) return DefWindowProc32A(hwnd, msg, wParam, lParam); switch (msg) { case EM_GETSEL16: DPRINTF_EDIT_MSG16("EM_GETSEL"); wParam = 0; lParam = 0; /* fall through */ case EM_GETSEL32: DPRINTF_EDIT_MSG32("EM_GETSEL"); lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam); break; case EM_SETSEL16: DPRINTF_EDIT_MSG16("EM_SETSEL"); lResult = EDIT_EM_SetSel16(wndPtr, wParam, lParam); break; case EM_SETSEL32: DPRINTF_EDIT_MSG32("EM_SETSEL"); lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam); break; case EM_GETRECT16: DPRINTF_EDIT_MSG16("EM_GETRECT"); lResult = EDIT_EM_GetRect16(wndPtr, wParam, lParam); break; case EM_GETRECT32: DPRINTF_EDIT_MSG32("EM_GETRECT"); lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam); break; case EM_SETRECT16: DPRINTF_EDIT_MSG16("EM_SETRECT"); /* fall through */ case EM_SETRECT32: DPRINTF_EDIT_MSG32("EM_SETRECT"); lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam); break; case EM_SETRECTNP16: DPRINTF_EDIT_MSG16("EM_SETRECTNP"); /* fall through */ case EM_SETRECTNP32: DPRINTF_EDIT_MSG32("EM_SETRECTNP"); lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam); break; case EM_SCROLL16: DPRINTF_EDIT_MSG16("EM_SCROLL"); /* fall through */ case EM_SCROLL32: DPRINTF_EDIT_MSG32("EM_SCROLL"); lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam); break; case EM_LINESCROLL16: DPRINTF_EDIT_MSG16("EM_LINESCROLL"); wParam = (WPARAM32)(INT32)(INT16)HIWORD(lParam); lParam = (LPARAM)(INT32)(INT16)LOWORD(lParam); /* fall through */ case EM_LINESCROLL32: DPRINTF_EDIT_MSG32("EM_LINESCROLL"); lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam); break; case EM_SCROLLCARET16: DPRINTF_EDIT_MSG16("EM_SCROLLCARET"); /* fall through */ case EM_SCROLLCARET32: DPRINTF_EDIT_MSG32("EM_SCROLLCARET"); lResult = EDIT_EM_ScrollCaret(wndPtr, wParam, lParam); break; case EM_GETMODIFY16: DPRINTF_EDIT_MSG16("EM_GETMODIFY"); /* fall through */ case EM_GETMODIFY32: DPRINTF_EDIT_MSG32("EM_GETMODIFY"); lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam); break; case EM_SETMODIFY16: DPRINTF_EDIT_MSG16("EM_SETMODIFY"); /* fall through */ case EM_SETMODIFY32: DPRINTF_EDIT_MSG32("EM_SETMODIFY"); lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam); break; case EM_GETLINECOUNT16: DPRINTF_EDIT_MSG16("EM_GETLINECOUNT"); /* fall through */ case EM_GETLINECOUNT32: DPRINTF_EDIT_MSG32("EM_GETLINECOUNT"); lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam); break; case EM_LINEINDEX16: DPRINTF_EDIT_MSG16("EM_LINEINDEX"); /* fall through */ case EM_LINEINDEX32: DPRINTF_EDIT_MSG32("EM_LINEINDEX"); lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam); break; case EM_SETHANDLE16: DPRINTF_EDIT_MSG16("EM_SETHANDLE"); lResult = EDIT_EM_SetHandle16(wndPtr, wParam, lParam); break; case EM_SETHANDLE32: DPRINTF_EDIT_MSG32("EM_SETHANDLE"); lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam); break; case EM_GETHANDLE16: DPRINTF_EDIT_MSG16("EM_GETHANDLE"); lResult = EDIT_EM_GetHandle16(wndPtr, wParam, lParam); break; case EM_GETHANDLE32: DPRINTF_EDIT_MSG32("EM_GETHANDLE"); lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam); break; case EM_GETTHUMB16: DPRINTF_EDIT_MSG16("EM_GETTHUMB"); /* fall through */ case EM_GETTHUMB32: DPRINTF_EDIT_MSG32("EM_GETTHUMB"); lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam); break; /* messages 0x00bf and 0x00c0 missing from specs */ case WM_USER+15: DPRINTF_EDIT_MSG16("undocumented WM_USER+15, please report"); /* fall through */ case 0x00bf: DPRINTF_EDIT_MSG32("undocumented 0x00bf, please report"); lResult = DefWindowProc32A(hwnd, msg, wParam, lParam); break; case WM_USER+16: DPRINTF_EDIT_MSG16("undocumented WM_USER+16, please report"); /* fall through */ case 0x00c0: DPRINTF_EDIT_MSG32("undocumented 0x00c0, please report"); lResult = DefWindowProc32A(hwnd, msg, wParam, lParam); break; case EM_LINELENGTH16: DPRINTF_EDIT_MSG16("EM_LINELENGTH"); /* fall through */ case EM_LINELENGTH32: DPRINTF_EDIT_MSG32("EM_LINELENGTH"); lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam); break; case EM_REPLACESEL16: DPRINTF_EDIT_MSG16("EM_REPLACESEL"); lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam); /* fall through */ case EM_REPLACESEL32: DPRINTF_EDIT_MSG32("EM_REPLACESEL"); lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam); break; /* message 0x00c3 missing from specs */ case WM_USER+19: DPRINTF_EDIT_MSG16("undocumented WM_USER+19, please report"); /* fall through */ case 0x00c3: DPRINTF_EDIT_MSG32("undocumented 0x00c3, please report"); lResult = DefWindowProc32A(hwnd, msg, wParam, lParam); break; case EM_GETLINE16: DPRINTF_EDIT_MSG16("EM_GETLINE"); lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam); /* fall through */ case EM_GETLINE32: DPRINTF_EDIT_MSG32("EM_GETLINE"); lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam); break; case EM_LIMITTEXT16: DPRINTF_EDIT_MSG16("EM_LIMITTEXT"); /* fall through */ case EM_SETLIMITTEXT32: DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT"); lResult = EDIT_EM_SetLimitText(wndPtr, wParam, lParam); break; case EM_CANUNDO16: DPRINTF_EDIT_MSG16("EM_CANUNDO"); /* fall through */ case EM_CANUNDO32: DPRINTF_EDIT_MSG32("EM_CANUNDO"); lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam); break; case EM_UNDO16: DPRINTF_EDIT_MSG16("EM_UNDO"); /* fall through */ case EM_UNDO32: /* fall through */ case WM_UNDO: DPRINTF_EDIT_MSG32("EM_UNDO / WM_UNDO"); lResult = EDIT_EM_Undo(wndPtr, wParam, lParam); break; case EM_FMTLINES16: DPRINTF_EDIT_MSG16("EM_FMTLINES"); /* fall through */ case EM_FMTLINES32: DPRINTF_EDIT_MSG32("EM_FMTLINES"); lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam); break; case EM_LINEFROMCHAR16: DPRINTF_EDIT_MSG16("EM_LINEFROMCHAR"); /* fall through */ case EM_LINEFROMCHAR32: DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR"); lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam); break; /* message 0x00ca missing from specs */ case WM_USER+26: DPRINTF_EDIT_MSG16("undocumented WM_USER+26, please report"); /* fall through */ case 0x00ca: DPRINTF_EDIT_MSG32("undocumented 0x00ca, please report"); lResult = DefWindowProc32A(hwnd, msg, wParam, lParam); break; case EM_SETTABSTOPS16: DPRINTF_EDIT_MSG16("EM_SETTABSTOPS"); lResult = EDIT_EM_SetTabStops16(wndPtr, wParam, lParam); break; case EM_SETTABSTOPS32: DPRINTF_EDIT_MSG32("EM_SETTABSTOPS"); lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam); break; case EM_SETPASSWORDCHAR16: DPRINTF_EDIT_MSG16("EM_SETPASSWORDCHAR"); /* fall through */ case EM_SETPASSWORDCHAR32: DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR"); lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam); break; case EM_EMPTYUNDOBUFFER16: DPRINTF_EDIT_MSG16("EM_EMPTYUNDOBUFFER"); /* fall through */ case EM_EMPTYUNDOBUFFER32: DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER"); lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam); break; case EM_GETFIRSTVISIBLELINE16: DPRINTF_EDIT_MSG16("EM_GETFIRSTVISIBLELINE"); /* fall through */ case EM_GETFIRSTVISIBLELINE32: DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE"); lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam); break; case EM_SETREADONLY16: DPRINTF_EDIT_MSG16("EM_SETREADONLY"); /* fall through */ case EM_SETREADONLY32: DPRINTF_EDIT_MSG32("EM_SETREADONLY"); lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam); break; case EM_SETWORDBREAKPROC16: DPRINTF_EDIT_MSG16("EM_SETWORDBREAKPROC"); /* fall through */ case EM_SETWORDBREAKPROC32: DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC"); lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam); break; case EM_GETWORDBREAKPROC16: DPRINTF_EDIT_MSG16("EM_GETWORDBREAKPROC"); /* fall through */ case EM_GETWORDBREAKPROC32: DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC"); lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam); break; case EM_GETPASSWORDCHAR16: DPRINTF_EDIT_MSG16("EM_GETPASSWORDCHAR"); /* fall through */ case EM_GETPASSWORDCHAR32: DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR"); lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam); break; /* The following EM_xxx are new to win95 and don't exist for 16 bit */ case EM_SETMARGINS32: DPRINTF_EDIT_MSG16("EM_SETMARGINS"); lResult = EDIT_EM_SetMargins(wndPtr, wParam, lParam); break; case EM_GETMARGINS32: DPRINTF_EDIT_MSG16("EM_GETMARGINS"); lResult = EDIT_EM_GetMargins(wndPtr, wParam, lParam); break; case EM_GETLIMITTEXT32: DPRINTF_EDIT_MSG16("EM_GETLIMITTEXT"); lResult = EDIT_EM_GetLimitText(wndPtr, wParam, lParam); break; case EM_POSFROMCHAR32: DPRINTF_EDIT_MSG16("EM_POSFROMCHAR"); lResult = EDIT_EM_PosFromChar(wndPtr, wParam, lParam); break; case EM_CHARFROMPOS32: DPRINTF_EDIT_MSG16("EM_CHARFROMPOS"); lResult = EDIT_EM_CharFromPos(wndPtr, wParam, lParam); break; case WM_GETDLGCODE: DPRINTF_EDIT_MSG32("WM_GETDLGCODE"); lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam); break; case WM_CHAR: DPRINTF_EDIT_MSG32("WM_CHAR"); lResult = EDIT_WM_Char(wndPtr, wParam, lParam); break; case WM_CLEAR: DPRINTF_EDIT_MSG32("WM_CLEAR"); lResult = EDIT_WM_Clear(wndPtr, wParam, lParam); break; case WM_COMMAND: DPRINTF_EDIT_MSG32("WM_COMMAND"); lResult = EDIT_WM_Command(wndPtr, wParam, lParam); break; /* * FIXME: when this one is added to WINE, change RBUTTONUP to CONTEXTMENU * Furthermore, coordinate conversion should no longer be required * * case WM_CONTEXTMENU: */ case WM_RBUTTONUP: DPRINTF_EDIT_MSG32("WM_RBUTTONUP"); ClientToScreen16(wndPtr->hwndSelf, (LPPOINT16)&lParam); lResult = EDIT_WM_ContextMenu(wndPtr, wParam, lParam); break; case WM_COPY: DPRINTF_EDIT_MSG32("WM_COPY"); lResult = EDIT_WM_Copy(wndPtr, wParam, lParam); break; case WM_CREATE: DPRINTF_EDIT_MSG32("WM_CREATE"); lResult = EDIT_WM_Create(wndPtr, wParam, lParam); break; case WM_CUT: DPRINTF_EDIT_MSG32("WM_CUT"); lResult = EDIT_WM_Cut(wndPtr, wParam, lParam); break; case WM_DESTROY: DPRINTF_EDIT_MSG32("WM_DESTROY"); lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam); break; case WM_ENABLE: DPRINTF_EDIT_MSG32("WM_ENABLE"); lResult = EDIT_WM_Enable(wndPtr, wParam, lParam); break; case WM_ERASEBKGND: DPRINTF_EDIT_MSG32("WM_ERASEBKGND"); lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam); break; case WM_GETFONT: DPRINTF_EDIT_MSG32("WM_GETFONT"); lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam); break; case WM_GETTEXT: DPRINTF_EDIT_MSG32("WM_GETTEXT"); lResult = EDIT_WM_GetText(wndPtr, wParam, lParam); break; case WM_GETTEXTLENGTH: DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH"); lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam); break; case WM_HSCROLL: DPRINTF_EDIT_MSG32("WM_HSCROLL"); lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam); break; case WM_INITMENUPOPUP: DPRINTF_EDIT_MSG32("WM_INITMENUPOPUP"); lResult = EDIT_WM_InitMenuPopup(wndPtr, wParam, lParam); break; case WM_KEYDOWN: DPRINTF_EDIT_MSG32("WM_KEYDOWN"); lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam); break; case WM_KILLFOCUS: DPRINTF_EDIT_MSG32("WM_KILLFOCUS"); lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam); break; case WM_LBUTTONDBLCLK: DPRINTF_EDIT_MSG32("WM_LBUTTONDBLCLK"); lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam); break; case WM_LBUTTONDOWN: DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN"); lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam); break; case WM_LBUTTONUP: DPRINTF_EDIT_MSG32("WM_LBUTTONUP"); lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam); break; case WM_MOUSEMOVE: /* * DPRINTF_EDIT_MSG32("WM_MOUSEMOVE"); */ lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam); break; case WM_PAINT: DPRINTF_EDIT_MSG32("WM_PAINT"); lResult = EDIT_WM_Paint(wndPtr, wParam, lParam); break; case WM_PASTE: DPRINTF_EDIT_MSG32("WM_PASTE"); lResult = EDIT_WM_Paste(wndPtr, wParam, lParam); break; case WM_SETCURSOR: /* * DPRINTF_EDIT_MSG32("WM_SETCURSOR"); */ lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam); break; case WM_SETFOCUS: DPRINTF_EDIT_MSG32("WM_SETFOCUS"); lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam); break; case WM_SETFONT: DPRINTF_EDIT_MSG32("WM_SETFONT"); lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam); break; case WM_SETREDRAW: DPRINTF_EDIT_MSG32("WM_SETREDRAW"); lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam); break; case WM_SETTEXT: DPRINTF_EDIT_MSG32("WM_SETTEXT"); lResult = EDIT_WM_SetText(wndPtr, wParam, lParam); break; case WM_SIZE: DPRINTF_EDIT_MSG32("WM_SIZE"); lResult = EDIT_WM_Size(wndPtr, wParam, lParam); break; case WM_SYSKEYDOWN: DPRINTF_EDIT_MSG32("WM_SYSKEYDOWN"); lResult = EDIT_WM_SysKeyDown(wndPtr, wParam, lParam); break; case WM_TIMER: DPRINTF_EDIT_MSG32("WM_TIMER"); lResult = EDIT_WM_Timer(wndPtr, wParam, lParam); break; case WM_VSCROLL: DPRINTF_EDIT_MSG32("WM_VSCROLL"); lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam); break; default: lResult = DefWindowProc32A(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); LPSTR text = EDIT_GetPasswordPointer(wndPtr); INT32 ww = EDIT_GetWndWidth(wndPtr); HDC32 hdc; HFONT32 hFont; HFONT32 oldFont = 0; LPSTR start, cp; INT32 prev, next; INT32 width; INT32 length; LINE_END ending; hdc = GetDC32(wndPtr->hwndSelf); hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0); if (hFont) oldFont = SelectObject32(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, 0); es->LineDefs[0].ending = END_0; es->TextWidth = (INT32)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 = lstrlen32A(start); } else if ((cp > start) && (*(cp - 1) == '\r')) { ending = END_SOFT; length = cp - start - 1; } else { ending = END_HARD; length = cp - start; } width = (INT32)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 = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, next, es->NumTabStops, es->TabStops)); } while (width <= ww); if (!prev) { next = 0; do { prev = next; next++; width = (INT32)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 = (INT32)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) SelectObject32(hdc, oldFont); ReleaseDC32(wndPtr->hwndSelf, hdc); free(text); } /********************************************************************* * * EDIT_CallWordBreakProc * * Call appropriate WordBreakProc (internal or external). * * FIXME: Heavily broken now that we have a LOCAL32 buffer. * External wordbreak functions have been disabled in * EM_SETWORDBREAKPROC. * */ static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action) { return EDIT_WordBreakProc(s, index, count, action); /* * EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0); * * if (!wbp) return EDIT_WordBreakProc(s, index, count, action); * else { * EDITSTATE *es = EDITSTATEPTR(wndPtr); * SEGPTR ptr = LOCAL_LockSegptr( wndPtr->hInstance, es->hBuf16 ) + * (INT16)(s - EDIT_GetPointer(wndPtr)); * INT ret = CallWordBreakProc( (FARPROC16)wbp, ptr, * index, count, action); * LOCAL_Unlock( wndPtr->hInstance, es->hBuf16 ); * return ret; * } */ } /********************************************************************* * * EDIT_ColFromWndX * * Calculates, for a given line and X-coordinate on the screen, the column. * */ static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x) { INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0); INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0); INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0); INT32 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, 0); EDIT_MoveEnd(wndPtr, TRUE); EDIT_WM_Clear(wndPtr, 0, 0); } /********************************************************************* * * EDIT_DelLeft * * Delete character to left of cursor. * */ static void EDIT_DelLeft(WND *wndPtr) { EDIT_EM_SetSel(wndPtr, -1, 0); EDIT_MoveBackward(wndPtr, TRUE); EDIT_WM_Clear(wndPtr, 0, 0); } /********************************************************************* * * EDIT_DelRight * * Delete character to right of cursor. * */ static void EDIT_DelRight(WND *wndPtr) { EDIT_EM_SetSel(wndPtr, -1, 0); EDIT_MoveForward(wndPtr, TRUE); EDIT_WM_Clear(wndPtr, 0, 0); } /********************************************************************* * * EDIT_GetAveCharWidth * */ static INT32 EDIT_GetAveCharWidth(WND *wndPtr) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return es->AveCharWidth; } /********************************************************************* * * EDIT_GetLineHeight * */ static INT32 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, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc) { rc->top = EDIT_WndYFromLine(wndPtr, line); rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr); rc->left = EDIT_WndXFromCol(wndPtr, line, scol); rc->right = (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 LPSTR EDIT_GetPointer(WND *wndPtr) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (!es->text && (es->hBuf32 || es->hBuf16)) { if (es->hBuf32) es->text = (LPSTR)LocalLock32(es->hBuf32); else es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf16); } return es->text; } /********************************************************************* * * EDIT_GetPasswordPointer * * */ static LPSTR EDIT_GetPasswordPointer(WND *wndPtr) { EDITSTATE *es = EDITSTATEPTR(wndPtr); LPSTR text = xstrdup(EDIT_GetPointer(wndPtr)); LPSTR p; if(es->PasswordChar) { p = text; while(*p != '\0') { if(*p != '\r' && *p != '\n') *p = es->PasswordChar; p++; } } return text; } /********************************************************************* * * EDIT_GetRedraw * */ static BOOL32 EDIT_GetRedraw(WND *wndPtr) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return es->Redraw; } /********************************************************************* * * EDIT_GetSel * * Beware: This is not the function called on EM_GETSEL. * This is the unordered version used internally * (s can be > e). No return value either. * */ static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (s) *s = es->SelStart; if (e) *e = es->SelEnd; } /********************************************************************* * * EDIT_GetTextWidth * */ static INT32 EDIT_GetTextWidth(WND *wndPtr) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return es->TextWidth; } /********************************************************************* * * EDIT_GetUndoPointer * * This acts as a LocalLock32(), but it locks only once. This way * you can call it whenever you like, without unlocking. * */ static LPSTR EDIT_GetUndoPointer(WND *wndPtr) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (!es->UndoText && es->hUndoBuf) es->UndoText = (LPSTR)LocalLock32(es->hUndoBuf); return es->UndoText; } /********************************************************************* * * EDIT_GetVisibleLineCount * */ static INT32 EDIT_GetVisibleLineCount(WND *wndPtr) { RECT32 rc; EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc); return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr)); } /********************************************************************* * * EDIT_GetWndWidth * */ static INT32 EDIT_GetWndWidth(WND *wndPtr) { RECT32 rc; EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc); return rc.right - rc.left; } /********************************************************************* * * EDIT_GetXOffset * */ static INT32 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, INT32 start, INT32 end) { INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); INT32 vlc = EDIT_GetVisibleLineCount(wndPtr); INT32 sl; INT32 el; INT32 sc; INT32 ec; RECT32 rcWnd; RECT32 rcLine; RECT32 rcUpdate; INT32 l; if (end == start) return; if (end == -1) end = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0); ORDER_INT32(start, end); sl = (INT32)EDIT_EM_LineFromChar(wndPtr, start, 0); el = (INT32)EDIT_EM_LineFromChar(wndPtr, end, 0); if ((el < fv) || (sl > fv + vlc)) return; sc = start - (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0); ec = end - (INT32)EDIT_EM_LineIndex(wndPtr, el, 0); if (sl < fv) { sl = fv; sc = 0; } if (el > fv + vlc) { el = fv + vlc; ec = (INT32)EDIT_EM_LineLength(wndPtr, (INT32)EDIT_EM_LineIndex(wndPtr, el, 0), 0); } EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rcWnd); if (sl == el) { EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine); if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine)) InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE ); } else { EDIT_GetLineRect(wndPtr, sl, sc, (INT32)EDIT_EM_LineLength(wndPtr, (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0), 0), &rcLine); if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine)) InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE ); for (l = sl + 1 ; l < el ; l++) { EDIT_GetLineRect(wndPtr, l, 0, (INT32)EDIT_EM_LineLength(wndPtr, (INT32)EDIT_EM_LineIndex(wndPtr, l, 0), 0), &rcLine); if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine)) InvalidateRect32(wndPtr->hwndSelf, &rcUpdate, FALSE); } EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine); if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine)) InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE ); } } /********************************************************************* * * EDIT_LineFromWndY * * Calculates, for a given Y-coordinate on the screen, the line. * */ static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y) { INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); INT32 lh = EDIT_GetLineHeight(wndPtr); INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0); return MAX(0, MIN(lc - 1, y / lh + fv)); } /********************************************************************* * * EDIT_MakeFit * * Try to fit size + 1 bytes in the buffer. Constrain to limits. * */ static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size) { EDITSTATE *es = EDITSTATEPTR(wndPtr); HLOCAL32 hNew32; HLOCAL16 hNew16; if (size <= es->BufSize) return TRUE; if (size > es->BufLimit) { dprintf_edit(stddeb, "edit: notification EN_MAXTEXT sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT); 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); EDIT_ReleasePointer(wndPtr); if (es->hBuf32) { if ((hNew32 = LocalReAlloc32(es->hBuf32, size + 1, 0))) { dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 32 bit handle %08x, new handle %08x\n", es->hBuf32, hNew32); es->hBuf32 = hNew32; es->BufSize = MIN(LocalSize32(es->hBuf32) - 1, es->BufLimit); if (es->BufSize < size) { dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize); dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE); return FALSE; } dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize); return TRUE; } } else { if ((hNew16 = LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf16, size + 1, LMEM_MOVEABLE))) { dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 16 bit handle %08x, new handle %08x\n", es->hBuf16, hNew16); es->hBuf16 = hNew16; es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1, es->BufLimit); if (es->BufSize < size) { dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED ! We now have %d+1\n", es->BufSize); dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE); return FALSE; } dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize); return TRUE; } } dprintf_edit(stddeb, "edit: EDIT_MakeFit: Reallocation failed\n"); dprintf_edit(stddeb, "edit: notification EN_ERRSPACE sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_ERRSPACE); return FALSE; } /********************************************************************* * * EDIT_MakeUndoFit * * Try to fit size + 1 bytes in the undo buffer. * */ static BOOL32 EDIT_MakeUndoFit(WND *wndPtr, INT32 size) { EDITSTATE *es = EDITSTATEPTR(wndPtr); HLOCAL32 hNew; if (size <= es->UndoBufSize) return TRUE; size = ((size / GROWLENGTH) + 1) * GROWLENGTH; dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: trying to ReAlloc to %d+1\n", size); EDIT_ReleaseUndoPointer(wndPtr); if ((hNew = LocalReAlloc32(es->hUndoBuf, size + 1, 0))) { dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: Old handle %08x, new handle %08x\n", es->hUndoBuf, hNew); es->hUndoBuf = hNew; es->UndoBufSize = LocalSize32(es->hUndoBuf) - 1; if (es->UndoBufSize < size) { dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: FAILED ! We now have %d+1\n", es->UndoBufSize); return FALSE; } dprintf_edit(stddeb, "edit: EDIT_MakeUndoFit: We now have %d+1\n", es->UndoBufSize); return TRUE; } return FALSE; } /********************************************************************* * * EDIT_MoveBackward * */ static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 li; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); if (e - li == 0) { if (l) { li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0); e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0); } } else e--; if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_MoveDownward * */ static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 lc; INT32 li; INT32 x; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); if (l < lc - 1) { x = EDIT_WndXFromCol(wndPtr, l, e - li); l++; e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) + EDIT_ColFromWndX(wndPtr, l, x); } if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_MoveEnd * */ static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 ll; INT32 li; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); e = li + ll; if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_MoveForward * */ static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 lc; INT32 ll; INT32 li; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0); ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); if (e - li == ll) { if (l != lc - 1) e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0); } else e++; if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_MoveHome * * Home key: move to beginning of line. * */ static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 li; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); e = li; if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_MovePageDown * */ static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 lc; INT32 li; INT32 x; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); if (l < lc - 1) { x = EDIT_WndXFromCol(wndPtr, l, e - li); l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr)); e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) + EDIT_ColFromWndX(wndPtr, l, x); } if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_MovePageUp * */ static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 li; INT32 x; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); if (l) { x = EDIT_WndXFromCol(wndPtr, l, e - li); l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr)); e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) + EDIT_ColFromWndX(wndPtr, l, x); } if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_MoveUpward * */ static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 li; INT32 x; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); if (l) { x = EDIT_WndXFromCol(wndPtr, l, e - li); l--; e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) + EDIT_ColFromWndX(wndPtr, l, x); } if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_MoveWordBackward * */ static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 ll; INT32 li; LPSTR text; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); if (e - li == 0) { if (l) { li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0); e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0); } } else { text = EDIT_GetPointer(wndPtr); e = li + (INT32)EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_LEFT); } if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_MoveWordForward * */ static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend) { INT32 s; INT32 e; INT32 l; INT32 lc; INT32 ll; INT32 li; LPSTR text; EDIT_GetSel(wndPtr, &s, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0); ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); if (e - li == ll) { if (l != lc - 1) e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0); } else { text = EDIT_GetPointer(wndPtr); e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li + 1, ll, WB_RIGHT); } if (!extend) s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } /********************************************************************* * * EDIT_PaintLine * */ static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev) { INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); INT32 vlc = EDIT_GetVisibleLineCount(wndPtr); INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0); INT32 li; INT32 ll; INT32 s; INT32 e; INT32 x; INT32 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 = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0); ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0); EDIT_GetSel(wndPtr, &s, &e); ORDER_INT32(s, e); s = MIN(li + ll, MAX(li, s)); e = MIN(li + ll, MAX(li, e)); if (rev && (s != e) && ((GetFocus32() == 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 INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev) { EDITSTATE *es = EDITSTATEPTR(wndPtr); COLORREF BkColor; COLORREF TextColor; INT32 ret; LPSTR text; INT32 li; INT32 xoff; if (!count) return 0; BkColor = GetBkColor32(hdc); TextColor = GetTextColor32(hdc); if (rev) { SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); } text = EDIT_GetPasswordPointer(wndPtr); li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0); xoff = EDIT_GetXOffset(wndPtr); ret = (INT32)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->hBuf32 || es->hBuf16)) { if (es->hBuf32) LocalUnlock32(es->hBuf32); else LOCAL_Unlock(wndPtr->hInstance, es->hBuf16); } es->text = NULL; } /********************************************************************* * * EDIT_ReleaseUndoPointer * * 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_ReleaseUndoPointer(WND *wndPtr) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (!es) return; if (es->UndoText && es->hUndoBuf) LocalUnlock32(es->hUndoBuf); es->UndoText = NULL; } /********************************************************************* * * EDIT_SetSel * * Beware: This is not the function called on EM_SETSEL. * This is the unordered version used internally * (s can be > e). Doesn't accept -1 parameters either. * No range checking. * */ static void EDIT_SetSel(WND *wndPtr, INT32 ns, INT32 ne) { EDITSTATE *es = EDITSTATEPTR(wndPtr); LRESULT pos; INT32 s; INT32 e; EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e); es->SelStart = ns; es->SelEnd = ne; if (EDIT_GetRedraw(wndPtr)) { if (wndPtr->hwndSelf == GetFocus32()) { pos = EDIT_EM_PosFromChar(wndPtr, ne, 0); SetCaretPos((INT16)LOWORD(pos), (INT16)HIWORD(pos)); } ORDER_INT32(s, ns); ORDER_INT32(s, ne); ORDER_INT32(e, ns); ORDER_INT32(e, ne); ORDER_INT32(ns, ne); if (e != ns) { EDIT_InvalidateText(wndPtr, s, e); EDIT_InvalidateText(wndPtr, ns, ne); } else EDIT_InvalidateText(wndPtr, s, ne); } } /********************************************************************* * * EDIT_WndXFromCol * * Calculates, for a given line and column, the X-coordinate on the screen. * */ static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col) { EDITSTATE *es = EDITSTATEPTR(wndPtr); LPSTR text = EDIT_GetPasswordPointer(wndPtr); INT32 ret; HDC32 hdc; HFONT32 hFont; HFONT32 oldFont = 0; INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0); INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0); INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0); INT32 xoff = EDIT_GetXOffset(wndPtr); hdc = GetDC32(wndPtr->hwndSelf); hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0); if (hFont) oldFont = SelectObject32(hdc, hFont); line = MAX(0, MIN(line, lc - 1)); col = MIN(col, ll); ret = (INT32)LOWORD(GetTabbedTextExtent(hdc, text + li, col, es->NumTabStops, es->TabStops)) - xoff; if (hFont) SelectObject32(hdc, oldFont); ReleaseDC32(wndPtr->hwndSelf, hdc); free(text); return ret; } /********************************************************************* * * EDIT_WndYFromLine * * Calculates, for a given line, the Y-coordinate on the screen. * */ static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line) { INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); INT32 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 INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action) { INT32 ret = 0; dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%u" ", count=%u, 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, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return (LRESULT)(es->UndoInsertLen || lstrlen32A(EDIT_GetUndoPointer(wndPtr))); } /********************************************************************* * * EM_CHARFROMPOS * * FIXME: do the specs mean LineIndex or LineNumber (li v.s. l) ??? */ static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { POINT32 pt; RECT32 rc; INT32 l; INT32 li; INT32 c; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); GetClientRect32(wndPtr->hwndSelf, &rc); if (!PtInRect32(&rc, pt)) return -1; l = EDIT_LineFromWndY(wndPtr, pt.y); li = EDIT_EM_LineIndex(wndPtr, l, 0); c = EDIT_ColFromWndX(wndPtr, l, pt.x); return (LRESULT)MAKELONG(li + c, li); } /********************************************************************* * * EM_EMPTYUNDOBUFFER * */ static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); es->UndoInsertLen = 0; *EDIT_GetUndoPointer(wndPtr) = '\0'; return 0; } /********************************************************************* * * EM_FMTLINES * */ static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented\n"); return wParam ? TRUE : FALSE; } /********************************************************************* * * EM_GETFIRSTVISIBLELINE * */ static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (IsMultiLine(wndPtr)) return (LRESULT)es->FirstVisibleLine; else return (LRESULT)EDIT_ColFromWndX(wndPtr, 0, 0); } /********************************************************************* * * EM_GETHANDLE * */ static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (!IsMultiLine(wndPtr)) return 0; if (es->hBuf32) return (LRESULT)es->hBuf32; else return (LRESULT)es->hBuf16; } /********************************************************************* * * EM_GETHANDLE16 * * Hopefully this won't fire back at us. * We always start with a buffer in 32 bit linear memory. * However, with this message a 16 bit application requests * a handle of 16 bit local heap memory, where it expects to find * the text. * It's a pitty that from this moment on we have to use this * local heap, because applications may rely on the handle * in the future. * * In this function we'll try to switch to local heap. */ static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); LPSTR text; HLOCAL16 newBuf; LPSTR newText; INT16 newSize; if (!IsMultiLine(wndPtr)) return 0; if (es->hBuf16) return (LRESULT)es->hBuf16; if (!LOCAL_HeapSize(wndPtr->hInstance)) { if (!LocalInit(wndPtr->hInstance, 0, GlobalSize16(wndPtr->hInstance))) { fprintf(stderr, "edit: EM_GETHANDLE: could not initialize local heap\n"); return 0; } dprintf_edit(stddeb, "edit: EM_GETHANDLE: local heap initialized\n"); } if (!(newBuf = LOCAL_Alloc(wndPtr->hInstance, EDIT_WM_GetTextLength(wndPtr, 0, 0) + 1, LMEM_MOVEABLE))) { fprintf(stderr, "edit: EM_GETHANDLE: could not allocate new 16 bit buffer\n"); return 0; } newSize = MIN(LOCAL_Size(wndPtr->hInstance, newBuf) - 1, es->BufLimit); if (!(newText = LOCAL_Lock(wndPtr->hInstance, newBuf))) { fprintf(stderr, "edit: EM_GETHANDLE: could not lock new 16 bit buffer\n"); LOCAL_Free(wndPtr->hInstance, newBuf); return 0; } text = EDIT_GetPointer(wndPtr); lstrcpy32A(newText, text); EDIT_ReleasePointer(wndPtr); GlobalFree32(es->hBuf32); es->hBuf32 = (HLOCAL32)NULL; es->hBuf16 = newBuf; es->BufSize = newSize; es->text = newText; dprintf_edit(stddeb, "edit: EM_GETHANDLE: switched to 16 bit buffer\n"); return (LRESULT)es->hBuf16; } /********************************************************************* * * EM_GETLIMITTEXT * */ static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return es->BufLimit; } /********************************************************************* * * EM_GETLINE * */ static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { LPSTR text; LPSTR src; LPSTR dst; INT32 len; INT32 i; INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0); if (!IsMultiLine(wndPtr)) wParam = 0; if ((INT32)wParam >= lc) return 0; text = EDIT_GetPointer(wndPtr); src = text + (INT32)EDIT_EM_LineIndex(wndPtr, wParam, 0); dst = (LPSTR)lParam; len = MIN(*(WORD *)dst, (INT32)EDIT_EM_LineLength(wndPtr, wParam, 0)); for (i = 0 ; i < len ; i++) { *dst = *src; src++; dst++; } return (LRESULT)len; } /********************************************************************* * * EM_GETLINECOUNT * */ static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return (LRESULT)es->LineCount; } /********************************************************************* * * EM_GETMARGINS * */ static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return (LRESULT)MAKELONG(es->LeftMargin, es->RightMargin); } /********************************************************************* * * EM_GETMODIFY * */ static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return (LRESULT)es->TextChanged; } /********************************************************************* * * EM_GETPASSWORDCHAR * */ static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return (LRESULT)es->PasswordChar; } /********************************************************************* * * EM_GETRECT * */ static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); CopyRect32((LPRECT32)lParam, &es->FormatRect); return 0; } /********************************************************************* * * EM_GETRECT16 * */ static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); CONV_RECT32TO16(&es->FormatRect, (LPRECT16)PTR_SEG_TO_LIN((SEGPTR)lParam)); return 0; } /********************************************************************* * * EM_GETSEL * * Returns the ordered selection range so that * LOWORD(result) < HIWORD(result) * */ static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 s; INT32 e; EDIT_GetSel(wndPtr, &s, &e); ORDER_INT32(s, e); if (wParam) *(LPINT32)wParam = s; if (lParam) *(LPINT32)lParam = e; return MAKELONG((INT16)s, (INT16)e); } /********************************************************************* * * EM_GETTHUMB * * FIXME: is this right ? (or should it be only HSCROLL) * (and maybe only for edit controls that really have their * own scrollbars) (and maybe only for multiline controls ?) * All in all: very poorly documented * */ static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0), EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0)); } /********************************************************************* * * EM_GETWORDBREAKPROC * * FIXME: Application defined WordBreakProc should be returned * */ static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { /* EDITSTATE *es = EDITSTATEPTR(wndPtr); return (LRESULT)es->WordBreakProc; */ return 0; } /********************************************************************* * * EM_LINEFROMCHAR * */ static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 l; if (!IsMultiLine(wndPtr)) return 0; if ((INT32)wParam == -1) EDIT_EM_GetSel(wndPtr, (WPARAM32)&wParam, 0); /* intentional (looks weird, doesn't it ?) */ l = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0) - 1; while ((INT32)EDIT_EM_LineIndex(wndPtr, l, 0) > (INT32)wParam) l--; return (LRESULT)l; } /********************************************************************* * * EM_LINEINDEX * */ static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); INT32 e; INT32 l; INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0); if ((INT32)wParam == -1) { EDIT_GetSel(wndPtr, NULL, &e); l = lc - 1; while (es->LineDefs[l].offset > e) l--; return (LRESULT)es->LineDefs[l].offset; } if ((INT32)wParam >= lc) return -1; return (LRESULT)es->LineDefs[(INT32)wParam].offset; } /********************************************************************* * * EM_LINELENGTH * */ static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); INT32 s; INT32 e; INT32 sl; INT32 el; if (!IsMultiLine(wndPtr)) return (LRESULT)es->LineDefs[0].length; if ((INT32)wParam == -1) { EDIT_GetSel(wndPtr, &s, &e); sl = (INT32)EDIT_EM_LineFromChar(wndPtr, s, 0); el = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); return (LRESULT)(s - es->LineDefs[sl].offset + es->LineDefs[el].offset + es->LineDefs[el].length - e); } return (LRESULT)es->LineDefs[(INT32)EDIT_EM_LineFromChar(wndPtr, wParam, 0)].length; } /********************************************************************* * * EM_LINESCROLL * * FIXME: is wParam in pixels or in average character widths ??? * FIXME: we use this internally to scroll single line controls as well * (specs are vague about whether this message is valid or not for * single line controls) * */ static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0); INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); INT32 nfv = MAX(0, fv + (INT32)lParam); INT32 xoff = EDIT_GetXOffset(wndPtr); INT32 nxoff = MAX(0, xoff + (INT32)wParam); INT32 tw = EDIT_GetTextWidth(wndPtr); INT32 dx; INT32 dy; 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 (EDIT_GetRedraw(wndPtr)) ScrollWindow32(wndPtr->hwndSelf, dx, dy, NULL, NULL); es->FirstVisibleLine = nfv; es->XOffset = nxoff; if (IsVScrollBar(wndPtr)) SetScrollPos32(wndPtr->hwndSelf, SB_VERT, EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0), TRUE); if (IsHScrollBar(wndPtr)) SetScrollPos32(wndPtr->hwndSelf, SB_HORZ, EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0), TRUE); } if (IsMultiLine(wndPtr)) return TRUE; else return FALSE; } /********************************************************************* * * EM_POSFROMCHAR * */ static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 len = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0); INT32 l; INT32 li; wParam = MIN(wParam, len); l = EDIT_EM_LineFromChar(wndPtr, wParam, 0); li = EDIT_EM_LineIndex(wndPtr, l, 0); return (LRESULT)MAKELONG(EDIT_WndXFromCol(wndPtr, l, wParam - li), EDIT_WndYFromLine(wndPtr, l)); } /********************************************************************* * * EM_REPLACESEL * */ static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); LPCSTR str = (LPCSTR)lParam; INT32 strl = lstrlen32A(str); INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0); INT32 utl; INT32 s; INT32 e; INT32 i; LPSTR p; LPSTR text; LPSTR utext; BOOL32 redraw; EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e); if ((s == e) && !strl) return 0; if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) return 0; text = EDIT_GetPointer(wndPtr); utext = EDIT_GetUndoPointer(wndPtr); if (e != s) { /* there is something to be deleted */ if ((BOOL32)wParam) { /* we have to be able to undo */ utl = lstrlen32A(utext); if (!es->UndoInsertLen && (*utext && (s == es->UndoPos))) { /* undo-buffer is extended to the right */ EDIT_MakeUndoFit(wndPtr, utl + e - s); lstrcpyn32A(utext + utl, text + s, e - s + 1); } else if (!es->UndoInsertLen && (*utext && (e == es->UndoPos))) { /* undo-buffer is extended to the left */ EDIT_MakeUndoFit(wndPtr, utl + e - s); for (p = utext + utl ; p >= utext ; p--) p[e - s] = p[0]; for (i = 0 , p = utext ; i < e - s ; i++) p[i] = (text + s)[i]; es->UndoPos = s; } else { /* new undo-buffer */ EDIT_MakeUndoFit(wndPtr, e - s); lstrcpyn32A(utext, text + s, e - s + 1); es->UndoPos = s; } /* any deletion makes the old insertion-undo invalid */ es->UndoInsertLen = 0; } else EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0); /* now delete */ lstrcpy32A(text + s, text + e); } if (strl) { /* there is an insertion */ if ((BOOL32)wParam) { /* we have to be able to undo */ if ((s == es->UndoPos) || ((es->UndoInsertLen) && (s == es->UndoPos + es->UndoInsertLen))) /* * insertion is new and at delete position or * an extension to either left or right */ es->UndoInsertLen += strl; else { /* new insertion undo */ es->UndoPos = s; es->UndoInsertLen = strl; /* new insertion makes old delete-buffer invalid */ *utext = '\0'; } } else EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0); /* now insert */ tl = lstrlen32A(text); for (p = text + tl ; p >= text + s ; p--) p[strl] = p[0]; for (i = 0 , p = text + s ; i < strl ; i++) p[i] = str[i]; if(IsUpper(wndPtr)) CharUpperBuff32A(p, strl); else if(IsLower(wndPtr)) CharLowerBuff32A(p, strl); s += strl; } redraw = EDIT_GetRedraw(wndPtr); EDIT_WM_SetRedraw(wndPtr, FALSE, 0); EDIT_BuildLineDefs(wndPtr); EDIT_EM_SetSel(wndPtr, s, s); EDIT_EM_ScrollCaret(wndPtr, 0, 0); EDIT_EM_SetModify(wndPtr, TRUE, 0); dprintf_edit(stddeb, "edit: notification EN_UPDATE sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE); EDIT_WM_SetRedraw(wndPtr, redraw, 0); if (redraw) { InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); dprintf_edit(stddeb, "edit: notification EN_CHANGE sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE); } return 0; } /********************************************************************* * * EM_SCROLL * * FIXME: Scroll what ??? And where ??? * */ static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { fprintf(stdnimp, "edit: EM_SCROLL: message not implemented\n"); return 0; } /********************************************************************* * * EM_SCROLLCARET * * Makes sure the caret is visible. * FIXME: We use EM_LINESCROLL, but may we do that for single line * controls ??? * */ static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 e; INT32 l; INT32 li; INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); INT32 vlc = EDIT_GetVisibleLineCount(wndPtr); INT32 ww = EDIT_GetWndWidth(wndPtr); INT32 cw = EDIT_GetAveCharWidth(wndPtr); INT32 x; INT32 dy = 0; INT32 dx = 0; EDIT_GetSel(wndPtr, NULL, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); x = EDIT_WndXFromCol(wndPtr, l, e - li); 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, dx, dy); if (dy) { dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL); } if (dx) { dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL); } } return TRUE; } /********************************************************************* * * EM_SETHANDLE * */ static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (IsMultiLine(wndPtr)) { EDIT_ReleasePointer(wndPtr); /* * old buffer is freed by caller */ es->hBuf16 = (HLOCAL16)NULL; es->hBuf32 = (HLOCAL32)wParam; es->BufSize = LocalSize32(es->hBuf32) - 1; es->LineCount = 0; es->FirstVisibleLine = 0; es->SelStart = es->SelEnd = 0; EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0); EDIT_EM_SetModify(wndPtr, FALSE, 0); EDIT_BuildLineDefs(wndPtr); if (EDIT_GetRedraw(wndPtr)) InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } return 0; } /********************************************************************* * * EM_SETHANDLE16 * */ static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (IsMultiLine(wndPtr)) { EDIT_ReleasePointer(wndPtr); /* * old buffer is freed by caller */ es->hBuf16 = (HLOCAL16)wParam; es->hBuf32 = (HLOCAL32)NULL; es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1; es->LineCount = 0; es->FirstVisibleLine = 0; es->SelStart = es->SelEnd = 0; EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0); EDIT_EM_SetModify(wndPtr, FALSE, 0); EDIT_BuildLineDefs(wndPtr); if (EDIT_GetRedraw(wndPtr)) InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); EDIT_EM_ScrollCaret(wndPtr, 0, 0); } return 0; } /********************************************************************* * * EM_SETLIMITTEXT * * FIXME: in WinNT maxsize is 0x7FFFFFFF / 0xFFFFFFFF * However, the windows version is not complied to yet in all of edit.c * */ static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (IsMultiLine(wndPtr)) { if (wParam) es->BufLimit = MIN((INT32)wParam, BUFLIMIT_MULTI); else es->BufLimit = BUFLIMIT_MULTI; } else { if (wParam) es->BufLimit = MIN((INT32)wParam, BUFLIMIT_SINGLE); else es->BufLimit = BUFLIMIT_SINGLE; } return 0; } /********************************************************************* * * EM_SETMARGINS * * FIXME: We let the margins be set, but we don't use them yet !?! * */ static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (wParam & EC_USEFONTINFO) { if (IsMultiLine(wndPtr)) { /* * FIXME: do some GetABCCharWidth, or so * This is just preliminary */ es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr); } else es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr); return 0; } if (wParam & EC_LEFTMARGIN) es->LeftMargin = LOWORD(lParam); if (wParam & EC_RIGHTMARGIN) es->RightMargin = HIWORD(lParam); return 0; } /********************************************************************* * * EM_SETMODIFY * */ static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); es->TextChanged = (BOOL32)wParam; return 0; } /********************************************************************* * * EM_SETPASSWORDCHAR * * FIXME: This imlementation is way too simple * */ static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); es->PasswordChar = (CHAR)wParam; return 0; } /********************************************************************* * * EM_SETREADONLY * */ static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { if ((BOOL32)wParam) wndPtr->dwStyle |= ES_READONLY; else wndPtr->dwStyle &= ~(DWORD)ES_READONLY; return TRUE; } /********************************************************************* * * EM_SETRECT * */ static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { fprintf(stdnimp,"edit: EM_SETRECT: message not implemented\n"); return 0; } /********************************************************************* * * EM_SETRECTNP * */ static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented\n"); return 0; } /********************************************************************* * * EM_SETSEL * */ static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 ns = (INT32)wParam; INT32 ne = (INT32)lParam; INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0); if (ns == -1) { EDIT_GetSel(wndPtr, NULL, &ne); ns = ne; } else if ((!ns) && (ne == -1)) ne = tl; else { ns = MAX(0, MIN(ns, tl)); ne = MAX(0, MIN(ne, tl)); ORDER_INT32(ns, ne); } EDIT_SetSel(wndPtr, ns, ne); return -1; } /********************************************************************* * * EM_SETSEL16 * */ static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 ns = (INT32)LOWORD(lParam); INT32 ne = (INT32)HIWORD(lParam); if ((INT16)LOWORD(lParam) == -1) ns = -1; if ((!ns) && ((INT16)HIWORD(lParam) == -1)) ne = -1; EDIT_EM_SetSel(wndPtr, ns, ne); if (!wParam) EDIT_EM_ScrollCaret(wndPtr, 0, 0); return -1; } /********************************************************************* * * EM_SETTABSTOPS * */ static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); INT32 i; if (!IsMultiLine(wndPtr)) return FALSE; if (es->TabStops) free(es->TabStops); es->NumTabStops = (INT32)wParam; if (!wParam) es->TabStops = NULL; else { es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16)); for ( i = 0 ; i < (INT32)wParam ; i++ ) es->TabStops[i] = (INT16)((LPINT32)lParam)[i]; } return TRUE; } /********************************************************************* * * EM_SETTABSTOPS16 * */ static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); if (!IsMultiLine(wndPtr)) return FALSE; if (es->TabStops) free(es->TabStops); es->NumTabStops = (INT32)wParam; if (!wParam) es->TabStops = NULL; else { es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16)); memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam), (INT32)wParam * sizeof(INT16)); } return TRUE; } /********************************************************************* * * EM_SETWORDBREAKPROC * */ static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { /* EDITSTATE *es = EDITSTATEPTR(wndPtr); es->WordBreakProc = (EDITWORDBREAKPROC)lParam; */ return 0; } /********************************************************************* * * EM_UNDO / WM_UNDO * */ static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); LPSTR utext = xstrdup(EDIT_GetUndoPointer(wndPtr)); dprintf_edit(stddeb, "edit: before UNDO:insertion length = %d, deletion buffer = %s\n", es->UndoInsertLen, utext); EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen); EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0); EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)utext); EDIT_EM_SetSel(wndPtr, es->UndoPos, es->UndoPos + es->UndoInsertLen); free(utext); dprintf_edit(stddeb, "edit: after UNDO: insertion length = %d, deletion buffer = %s\n", es->UndoInsertLen, EDIT_GetUndoPointer(wndPtr)); return TRUE; } /********************************************************************* * * WM_CHAR * */ static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { char str[2]; unsigned char c = (unsigned char)wParam; switch (c) { case '\r': case '\n': if (IsMultiLine(wndPtr)) { if (IsReadOnly(wndPtr)) { EDIT_MoveHome(wndPtr, FALSE); EDIT_MoveDownward(wndPtr, FALSE); } else EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)"\r\n"); } break; case '\t': if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr)) EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)"\t"); break; default: if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) { str[0] = c; str[1] = '\0'; EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)str); } break; } return 0; } /********************************************************************* * * WM_CLEAR * */ static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDIT_EM_ReplaceSel(wndPtr, TRUE, (LPARAM)""); return -1; } /********************************************************************* * * WM_COMMAND * */ static LRESULT EDIT_WM_Command(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { if (HIWORD(wParam)) return 0; switch (LOWORD(wParam)) { case EM_UNDO32: EDIT_EM_Undo(wndPtr, 0, 0); break; case WM_CUT: EDIT_WM_Cut(wndPtr, 0, 0); break; case WM_COPY: EDIT_WM_Copy(wndPtr, 0, 0); break; case WM_PASTE: EDIT_WM_Paste(wndPtr, 0, 0); break; case WM_CLEAR: EDIT_WM_Clear(wndPtr, 0, 0); break; case EM_SETSEL32: EDIT_EM_SetSel(wndPtr, 0, -1); EDIT_EM_ScrollCaret(wndPtr, 0, 0); break; default: dprintf_edit(stddeb, "edit: unknown menu item, please report\n"); break; } return -1; } /********************************************************************* * * WM_CONTEXTMENU * * Note: the resource files resource/sysres_??.rc cannot define a * single popup menu. Hence we use a (dummy) menubar * containing the single popup menu as its first item. * */ static LRESULT EDIT_WM_ContextMenu(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { HMENU32 hMenu = LoadMenuIndirect32A(SYSRES_GetResPtr(SYSRES_MENU_EDITMENU)); HMENU32 hPopup = GetSubMenu32(hMenu, 0); TrackPopupMenu32(hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, LOWORD(lParam), HIWORD(lParam), 0, wndPtr->hwndSelf, NULL); DestroyMenu32(hMenu); return 0; } /********************************************************************* * * WM_COPY * */ static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 s; INT32 e; HGLOBAL16 hdst; LPSTR text; LPSTR dst; EDIT_GetSel(wndPtr, &s, &e); if (e == s) return -1; ORDER_INT32(s, e); hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1)); dst = GlobalLock16(hdst); text = EDIT_GetPointer(wndPtr); lstrcpyn32A(dst, text + s, e - s + 1); GlobalUnlock16(hdst); OpenClipboard(wndPtr->hwndSelf); EmptyClipboard(); SetClipboardData(CF_TEXT, hdst); CloseClipboard(); return -1; } /********************************************************************* * * WM_CREATE * */ static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam; EDITSTATE *es; LPSTR 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 (!(es->hBuf32 = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) { fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n"); return -1; } if (!(es->hUndoBuf = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) { fprintf(stderr, "edit: WM_CREATE: unable to allocate undo buffer\n"); LocalFree32(es->hBuf32); es->hBuf32 = (HLOCAL32)NULL; return -1; } es->BufSize = LocalSize32(es->hBuf32) - 1; es->UndoBufSize = LocalSize32(es->hUndoBuf) - 1; EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0); text = EDIT_GetPointer(wndPtr); *text = '\0'; EDIT_BuildLineDefs(wndPtr); EDIT_WM_SetFont(wndPtr, 0, 0); if (cs->lpszName && *(cs->lpszName) != '\0') EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, (LPARAM)cs->lpszName); EDIT_WM_SetRedraw(wndPtr, TRUE, 0); return 0; } /********************************************************************* * * WM_CUT * */ static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDIT_WM_Copy(wndPtr, 0, 0); EDIT_WM_Clear(wndPtr, 0, 0); return -1; } /********************************************************************* * * WM_DESTROY * */ static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); free(es->LineDefs); if (es->TabStops) free(es->TabStops); EDIT_ReleaseUndoPointer(wndPtr); LocalFree32(es->hUndoBuf); EDIT_ReleasePointer(wndPtr); if (es->hBuf32) LocalFree32(es->hBuf32); else LOCAL_Free(wndPtr->hInstance, es->hBuf16); free(es); *(EDITSTATE **)&wndPtr->wExtra = NULL; return 0; } /********************************************************************* * * WM_ENABLE * */ static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDIT_InvalidateText(wndPtr, 0, -1); return 0; } /********************************************************************* * * WM_ERASEBKGND * */ static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { HBRUSH32 hBrush; RECT32 rc; hBrush = (HBRUSH32)EDIT_SEND_CTLCOLOR(wndPtr, wParam); if (!hBrush) hBrush = (HBRUSH32)GetStockObject32(WHITE_BRUSH); GetClientRect32(wndPtr->hwndSelf, &rc); IntersectClipRect32((HDC32)wParam, rc.left, rc.top, rc.right, rc.bottom); GetClipBox32((HDC32)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. */ FillRect32((HDC32)wParam, &rc, hBrush); return -1; } /********************************************************************* * * WM_GETDLGCODE * */ static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS; } /********************************************************************* * * WM_GETFONT * */ static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); return (LRESULT)es->hFont; } /********************************************************************* * * WM_GETTEXT * */ static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { LPSTR text = EDIT_GetPointer(wndPtr); INT32 len; LRESULT lResult = 0; len = lstrlen32A(text); if ((INT32)wParam > len) { lstrcpy32A((LPSTR)lParam, text); lResult = (LRESULT)len + 1; } return lResult; } /********************************************************************* * * WM_GETTEXTLENGTH * */ static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { LPSTR text = EDIT_GetPointer(wndPtr); return (LRESULT)lstrlen32A(text); } /********************************************************************* * * WM_HSCROLL * * FIXME: scrollbar code itself is broken, so this one is a hack. * */ static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 ww = EDIT_GetWndWidth(wndPtr); INT32 tw = EDIT_GetTextWidth(wndPtr); INT32 cw = EDIT_GetAveCharWidth(wndPtr); INT32 xoff = EDIT_GetXOffset(wndPtr); INT32 dx = 0; BOOL32 not = TRUE; LRESULT ret = 0; 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 = HIWORD(wParam) * tw / 100 - xoff; break; /* The next two are undocumented ! */ case EM_GETTHUMB16: ret = tw ? xoff * 100 / tw : 0; break; case EM_LINESCROLL16: dx = (INT16)HIWORD(wParam); break; case SB_ENDSCROLL: default: break; } if (dx) { EDIT_EM_LineScroll(wndPtr, dx, 0); if (not) { dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL); } } return ret; } /********************************************************************* * * WM_INITMENUPOPUP * * FIXME: the message identifiers have been chosen arbitrarily, * hence we use MF_BYPOSITION. * We might as well use the "real" values (anybody knows ?) * The menu definition is in resources/sysres_??.rc. * Once these are OK, we better use MF_BYCOMMAND here * (as we do in EDIT_WM_Command()). * */ static LRESULT EDIT_WM_InitMenuPopup(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { HMENU32 hPopup = (HMENU32)wParam; INT32 s; INT32 e; EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e); /* undo */ EnableMenuItem32(hPopup, 0, MF_BYPOSITION | (EDIT_EM_CanUndo(wndPtr, 0, 0) ? MF_ENABLED : MF_GRAYED)); /* cut */ EnableMenuItem32(hPopup, 2, MF_BYPOSITION | ((e - s) && !IsPassword(wndPtr) ? MF_ENABLED : MF_GRAYED)); /* copy */ EnableMenuItem32(hPopup, 3, MF_BYPOSITION | ((e - s) && !IsPassword(wndPtr) ? MF_ENABLED : MF_GRAYED)); /* paste */ EnableMenuItem32(hPopup, 4, MF_BYPOSITION | (IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED)); /* delete */ EnableMenuItem32(hPopup, 5, MF_BYPOSITION | ((e - s) ? MF_ENABLED : MF_GRAYED)); /* select all */ EnableMenuItem32(hPopup, 7, MF_BYPOSITION | (s || (e != EDIT_WM_GetTextLength(wndPtr, 0, 0)) ? MF_ENABLED : MF_GRAYED)); return 0; } /********************************************************************* * * 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, WPARAM32 wParam, LPARAM lParam) { INT32 s; INT32 e; BOOL32 shift; BOOL32 control; if (GetKeyState(VK_MENU) & 0x8000) return 0; shift = GetKeyState(VK_SHIFT) & 0x8000; control = GetKeyState(VK_CONTROL) & 0x8000; EDIT_GetSel(wndPtr, &s, &e); 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, 0); else EDIT_DelLeft(wndPtr); break; case VK_DELETE: if (!IsReadOnly(wndPtr) && !(shift && control)) if (e != s) { if (shift) EDIT_WM_Cut(wndPtr, 0, 0); else EDIT_WM_Clear(wndPtr, 0, 0); } 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, 0); } else if (control) EDIT_WM_Copy(wndPtr, 0, 0); break; } return 0; } /********************************************************************* * * WM_KILLFOCUS * */ static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 s; INT32 e; DestroyCaret(); if(!(wndPtr->dwStyle & ES_NOHIDESEL)) { EDIT_EM_GetSel(wndPtr, (WPARAM32)&s, (LPARAM)&e); EDIT_InvalidateText(wndPtr, s, e); } dprintf_edit(stddeb, "edit: notification EN_KILLFOCUS sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS); return 0; } /********************************************************************* * * WM_LBUTTONDBLCLK * * The caret position has been set on the WM_LBUTTONDOWN message * */ static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 s; INT32 e; INT32 l; INT32 li; INT32 ll; LPSTR text = EDIT_GetPointer(wndPtr); EDIT_GetSel(wndPtr, NULL, &e); l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0); 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, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); return 0; } /********************************************************************* * * WM_LBUTTONDOWN * */ static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 x = (INT32)(INT16)LOWORD(lParam); INT32 y = (INT32)(INT16)HIWORD(lParam); INT32 l = EDIT_LineFromWndY(wndPtr, y); INT32 c; INT32 s; INT32 e; INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); INT32 vlc = EDIT_GetVisibleLineCount(wndPtr); INT32 li; SetFocus32(wndPtr->hwndSelf); SetCapture32(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 = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); e = li + c; if (GetKeyState(VK_SHIFT) & 0x8000) EDIT_GetSel(wndPtr, &s, NULL); else s = e; EDIT_SetSel(wndPtr, s, e); EDIT_EM_ScrollCaret(wndPtr, 0, 0); SetTimer32(wndPtr->hwndSelf, 0, 100, NULL); return 0; } /********************************************************************* * * WM_LBUTTONUP * */ static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { if (GetCapture32() == wndPtr->hwndSelf) { KillTimer32(wndPtr->hwndSelf, 0); ReleaseCapture(); } return 0; } /********************************************************************* * * WM_MOUSEMOVE * */ static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 x; INT32 y; INT32 l; INT32 c; INT32 s; INT32 fv; INT32 vlc; INT32 li; if (GetCapture32() == wndPtr->hwndSelf) { x = (INT32)(INT16)LOWORD(lParam); y = (INT32)(INT16)HIWORD(lParam); fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); 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); EDIT_GetSel(wndPtr, &s, NULL); li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0); EDIT_SetSel(wndPtr, s, li + c); } /* * FIXME: gotta do some scrolling if outside client (format ?) * area. Maybe reset the timer ? */ return 0; } /********************************************************************* * * WM_PAINT * */ static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { PAINTSTRUCT32 ps; INT32 i; INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); INT32 vlc = EDIT_GetVisibleLineCount(wndPtr); INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0); HDC32 hdc; HFONT32 hFont; HFONT32 oldFont = 0; RECT32 rc; RECT32 rcLine; RECT32 rcRgn; LRESULT pos; INT32 e; BOOL32 rev = IsWindowEnabled32(wndPtr->hwndSelf) && ((GetFocus32() == wndPtr->hwndSelf) || (wndPtr->dwStyle & ES_NOHIDESEL)); hdc = BeginPaint32(wndPtr->hwndSelf, &ps); GetClientRect32(wndPtr->hwndSelf, &rc); IntersectClipRect32( hdc, rc.left, rc.top, rc.right, rc.bottom ); hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0); if (hFont) oldFont = (HFONT32)SelectObject32(hdc, hFont); EDIT_SEND_CTLCOLOR(wndPtr, hdc); if (!IsWindowEnabled32(wndPtr->hwndSelf)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); GetClipBox32(hdc, &rcRgn); for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) { EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine); if (IntersectRect32(&rc, &rcRgn, &rcLine)) EDIT_PaintLine(wndPtr, hdc, i, rev); } if (hFont) SelectObject32(hdc, oldFont); if (wndPtr->hwndSelf == GetFocus32()) { EDIT_GetSel(wndPtr, NULL, &e); pos = EDIT_EM_PosFromChar(wndPtr, e, 0); SetCaretPos((INT16)LOWORD(pos), (INT16)HIWORD(pos)); } EndPaint32(wndPtr->hwndSelf, &ps); return 0; } /********************************************************************* * * WM_PASTE * */ static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { HGLOBAL16 hsrc; LPSTR src; OpenClipboard(wndPtr->hwndSelf); if ((hsrc = GetClipboardData(CF_TEXT))) { src = (LPSTR)GlobalLock16(hsrc); EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)TRUE, (LPARAM)src); GlobalUnlock16(hsrc); } CloseClipboard(); return -1; } /********************************************************************* * * WM_SETCURSOR * */ static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { if (LOWORD(lParam) == HTCLIENT) { SetCursor(LoadCursor16(0, IDC_IBEAM)); return -1; } else return 0; } /********************************************************************* * * WM_SETFOCUS * */ static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 s; INT32 e; EDIT_GetSel(wndPtr, &s, &e); CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr)); EDIT_SetSel(wndPtr, s, e); if(!(wndPtr->dwStyle & ES_NOHIDESEL)) EDIT_InvalidateText(wndPtr, s, e); ShowCaret(wndPtr->hwndSelf); dprintf_edit(stddeb, "edit: notification EN_SETFOCUS sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS); return 0; } /********************************************************************* * * WM_SETFONT * */ static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { TEXTMETRIC32A tm; EDITSTATE *es = EDITSTATEPTR(wndPtr); INT32 s; INT32 e; HDC32 hdc; HFONT32 oldFont = 0; EDIT_GetSel(wndPtr, &s, &e); es->hFont = (HFONT32)wParam; hdc = GetDC32(wndPtr->hwndSelf); if (es->hFont) oldFont = SelectObject32(hdc, es->hFont); GetTextMetrics32A(hdc, &tm); es->LineHeight = tm.tmHeight; es->AveCharWidth = tm.tmAveCharWidth; if (es->hFont) SelectObject32(hdc, oldFont); ReleaseDC32(wndPtr->hwndSelf, hdc); EDIT_BuildLineDefs(wndPtr); if ((BOOL32)lParam && EDIT_GetRedraw(wndPtr)) InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); if (wndPtr->hwndSelf == GetFocus32()) { DestroyCaret(); CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr)); EDIT_SetSel(wndPtr, s, e); ShowCaret(wndPtr->hwndSelf); } return 0; } /********************************************************************* * * WM_SETREDRAW * */ static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); es->Redraw = (BOOL32)wParam; return 0; } /********************************************************************* * * WM_SETTEXT * */ static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDIT_EM_SetSel(wndPtr, 0, -1); if (lParam) EDIT_EM_ReplaceSel(wndPtr, (WPARAM32)FALSE, lParam); EDIT_EM_SetModify(wndPtr, TRUE, 0); EDIT_EM_ScrollCaret(wndPtr, 0, 0); return 1; } /********************************************************************* * * WM_SIZE * * FIXME: What about that FormatRect ??? * */ static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { EDITSTATE *es = EDITSTATEPTR(wndPtr); INT32 e; EDIT_GetSel(wndPtr, 0, &e); GetClientRect32(wndPtr->hwndSelf, &es->FormatRect); if (EDIT_GetRedraw(wndPtr) && ((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED))) { if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr)) EDIT_BuildLineDefs(wndPtr); InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE ); } return 0; } /********************************************************************* * * WM_SYSKEYDOWN * */ static LRESULT EDIT_WM_SysKeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { if ((wParam == VK_BACK) && (lParam & 0x2000) && (BOOL32)EDIT_EM_CanUndo(wndPtr, 0, 0)) EDIT_EM_Undo(wndPtr, 0, 0); return 0; } /********************************************************************* * * WM_TIMER * */ static LRESULT EDIT_WM_Timer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { /* * FIXME: gotta do some scrolling here, like * EDIT_EM_LineScroll(wndPtr, 0, 1); */ return 0; } /********************************************************************* * * WM_VSCROLL * * FIXME: scrollbar code itself is broken, so this one is a hack. * */ static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam) { INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0); INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0); INT32 vlc = EDIT_GetVisibleLineCount(wndPtr); INT32 dy = 0; BOOL32 not = TRUE; LRESULT ret = 0; 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; /* fall through */ case SB_THUMBPOSITION: dy = HIWORD(wParam) * (lc - 1) / 100 - fv; break; /* The next two are undocumented ! */ case EM_GETTHUMB16: ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0; break; case EM_LINESCROLL16: dy = (INT16)LOWORD(lParam); break; case SB_ENDSCROLL: default: break; } if (dy) { EDIT_EM_LineScroll(wndPtr, 0, dy); if (not) { dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n"); EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL); } } return ret; }