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