mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-28 16:17:09 +08:00
2472 lines
71 KiB
C
2472 lines
71 KiB
C
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IMPORTANT NOTICE
|
|
//
|
|
// The following open source license statement does not apply to any
|
|
// entity in the Exception List published by FMSoft.
|
|
//
|
|
// For more information, please visit:
|
|
//
|
|
// https://www.fmsoft.cn/exception-list
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
* This file is part of MiniGUI, a mature cross-platform windowing
|
|
* and Graphics User Interface (GUI) support system for embedded systems
|
|
* and smart IoT devices.
|
|
*
|
|
* Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd.
|
|
* Copyright (C) 1998~2002, WEI Yongming
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Or,
|
|
*
|
|
* As this program is a library, any link to this program must follow
|
|
* GNU General Public License version 3 (GPLv3). If you cannot accept
|
|
* GPLv3, you need to be licensed from FMSoft.
|
|
*
|
|
* If you have got a commercial license of this program, please use it
|
|
* under the terms and conditions of the commercial license.
|
|
*
|
|
* For more information about the commercial license, please refer to
|
|
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
|
|
*/
|
|
/*
|
|
** edit.c: the Single Line Edit Control module.
|
|
**
|
|
** Create date: 1999/8/26
|
|
**
|
|
** TODO:
|
|
** * Replace
|
|
** * Undo.
|
|
**/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "common.h"
|
|
|
|
#ifdef _MGCTRL_SLEDIT
|
|
|
|
#include "minigui.h"
|
|
#include "gdi.h"
|
|
#include "window.h"
|
|
#include "ctrl/ctrlhelper.h"
|
|
#include "ctrl/edit.h"
|
|
#include "cliprect.h"
|
|
#include "internals.h"
|
|
#include "ctrlclass.h"
|
|
#include "clipboard.h"
|
|
|
|
#include "text.h"
|
|
#include "edit_impl.h"
|
|
|
|
static void set_line_width (HWND hWnd, PSLEDITDATA sled);
|
|
static void mySetCaretPos (HWND hWnd, PSLEDITDATA sled, int x);
|
|
static LRESULT SLEditCtrlProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
|
static void sledit_refresh_caret (HWND hWnd, PSLEDITDATA sled, BOOL bInited);
|
|
static BOOL make_charpos_visible (HWND hWnd, PSLEDITDATA sled, int charPos, int *cx);
|
|
|
|
/*
|
|
* for bug 4894, when select text don't hide caret, because this will close
|
|
* the ime window. by humingming 2010.8.17
|
|
*/
|
|
/*#define check_caret() \
|
|
if(sled->selStart != sled->selEnd) \
|
|
HideCaret(hWnd); \
|
|
else \
|
|
ShowCaret(hWnd);
|
|
*/
|
|
#define check_caret() ShowCaret(hWnd);
|
|
|
|
|
|
#define shift_one_char_r(pos) \
|
|
{ \
|
|
int len = CHLENNEXT((sled->content.string + sled->pos), (sled->content.txtlen - sled->pos)); \
|
|
sled->pos += len; \
|
|
}
|
|
|
|
#define shift_one_char_l(pos) \
|
|
{ \
|
|
int len = CHLENPREV((const char* )(sled->content.string),(const char* )(sled->content.string + sled->pos) ); \
|
|
sled->pos -= len; \
|
|
}
|
|
|
|
#define PASSWORD_REPLACEMENT '*'
|
|
BOOL RegisterSLEditControl (void)
|
|
{
|
|
WNDCLASS WndClass;
|
|
|
|
WndClass.spClassName = CTRL_SLEDIT;
|
|
WndClass.dwStyle = WS_NONE;
|
|
WndClass.dwExStyle = WS_EX_NONE;
|
|
WndClass.hCursor = GetSystemCursor (IDC_IBEAM);
|
|
#ifdef _MGSCHEMA_COMPOSITING
|
|
WndClass.dwBkColor = GetWindowElementAttr (HWND_NULL, WE_BGC_WINDOW);
|
|
#else
|
|
WndClass.iBkColor =
|
|
GetWindowElementPixelEx (HWND_NULL, HDC_SCREEN, WE_BGC_WINDOW);
|
|
#endif
|
|
WndClass.WinProc = SLEditCtrlProc;
|
|
|
|
if (gui_AddNewControlClass (&WndClass) != ERR_OK)
|
|
return FALSE;
|
|
|
|
WndClass.spClassName = CTRL_EDIT;
|
|
|
|
return gui_AddNewControlClass (&WndClass) == ERR_OK;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
static void setup_dc (HWND hWnd, SLEDITDATA *sled, HDC hdc, BOOL bSel)
|
|
{
|
|
DWORD dwStyle = GetWindowStyle (hWnd);
|
|
if (!bSel) {
|
|
SetBkMode (hdc, BM_TRANSPARENT);
|
|
if (dwStyle & WS_DISABLED)
|
|
SetTextColor (hdc,
|
|
GetWindowElementPixelEx (hWnd, hdc, WE_FGC_DISABLED_ITEM));
|
|
else
|
|
SetTextColor (hdc,
|
|
GetWindowElementPixelEx (hWnd, hdc, WE_FGC_WINDOW));
|
|
SetBkColor (hdc, GetWindowBkColor (hWnd));
|
|
}
|
|
else {
|
|
SetBkMode (hdc, BM_OPAQUE);
|
|
|
|
if (dwStyle & WS_DISABLED)
|
|
SetTextColor (hdc,
|
|
GetWindowElementPixelEx (hWnd, hdc, WE_FGC_DISABLED_ITEM));
|
|
else
|
|
SetTextColor (hdc,
|
|
GetWindowElementPixelEx (hWnd, hdc, WE_FGC_SELECTED_ITEM));
|
|
|
|
if (sled->status & EST_FOCUSED)
|
|
SetBkColor (hdc,
|
|
GetWindowElementPixelEx (hWnd, hdc, WE_BGC_SELECTED_ITEM));
|
|
else
|
|
SetBkColor (hdc,
|
|
GetWindowElementPixelEx (hWnd, hdc, WE_BGC_SELECTED_LOSTFOCUS));
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
static int sledit_settext (PSLEDITDATA sled, const char *newtext)
|
|
{
|
|
int len, txtlen;
|
|
|
|
txtlen = strlen (newtext);
|
|
len = (txtlen <= 0) ? sled->nBlockSize : txtlen;
|
|
|
|
if (sled->hardLimit >= 0 && txtlen > sled->hardLimit) {
|
|
return -1;
|
|
}
|
|
|
|
/* free the old text */
|
|
if (sled->content.string)
|
|
testr_free (&sled->content);
|
|
|
|
if (!testr_alloc (&sled->content, len, sled->nBlockSize))
|
|
return -1;
|
|
|
|
if (newtext && txtlen > 0)
|
|
testr_setstr (&sled->content, newtext, txtlen);
|
|
else
|
|
sled->content.txtlen = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void get_content_width (HWND hWnd, PSLEDITDATA sled)
|
|
{
|
|
GetClientRect (hWnd, &sled->rcVis);
|
|
|
|
sled->rcVis.left += sled->leftMargin;
|
|
sled->rcVis.top += sled->topMargin;
|
|
sled->rcVis.right -= sled->rightMargin;
|
|
sled->rcVis.bottom -= sled->bottomMargin;
|
|
|
|
sled->nVisW = sled->rcVis.right - sled->rcVis.left;
|
|
}
|
|
|
|
static void recalcSize (HWND hWnd, PSLEDITDATA sled, BOOL bInited)
|
|
{
|
|
get_content_width (hWnd, sled);
|
|
|
|
sled->nContX = 0;
|
|
sled->nContW = sled->rcVis.right - sled->rcVis.left;
|
|
|
|
set_line_width (hWnd, sled);
|
|
|
|
sled->starty = sled->topMargin + ( sled->rcVis.bottom -
|
|
sled->rcVis.top - GetWindowFont (hWnd)->size - 1 ) / 2;
|
|
|
|
sledit_refresh_caret (hWnd, sled, bInited);
|
|
}
|
|
|
|
static int sledit_init (HWND hWnd, PSLEDITDATA sled)
|
|
{
|
|
PCONTROL pCtrl;
|
|
|
|
if (!sled)
|
|
return -1;
|
|
|
|
pCtrl = gui_Control(hWnd);
|
|
|
|
pCtrl->dwAddData2 = (DWORD)sled;
|
|
|
|
sled->status = 0;
|
|
sled->editPos = 0;
|
|
sled->selStart = 0;
|
|
sled->selEnd = 0;
|
|
|
|
sled->leftMargin = MARGIN_EDIT_LEFT;
|
|
sled->topMargin = MARGIN_EDIT_TOP;
|
|
sled->rightMargin = MARGIN_EDIT_RIGHT;
|
|
sled->bottomMargin = MARGIN_EDIT_BOTTOM;
|
|
|
|
sled->passwdChar = PASSWORD_REPLACEMENT;
|
|
|
|
sled->changed = FALSE;
|
|
sled->bShowCaret = FALSE;
|
|
|
|
sled->nBlockSize = DEF_LINE_BLOCK_SIZE;
|
|
sled->hardLimit = -1;
|
|
|
|
if (pCtrl->dwStyle & ES_TIP) {
|
|
sled->tiptext = FixStrAlloc (DEF_TIP_LEN + 1);
|
|
sled->tiptext[0] = 0;
|
|
}
|
|
else
|
|
sled->tiptext = NULL;
|
|
|
|
sled->content.string = NULL;
|
|
sled->content.buffsize = 0;
|
|
sled->content.txtlen = 0;
|
|
|
|
sledit_settext (sled, pCtrl->spCaption);
|
|
|
|
if (pCtrl->dwStyle & ES_PASSWORD) {
|
|
pCtrl->pLogFont = GetSystemFont (SYSLOGFONT_DEFAULT);
|
|
}
|
|
|
|
CreateCaret (hWnd, NULL, 1, pCtrl->pLogFont->size);
|
|
recalcSize (hWnd, sled, TRUE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void sledit_destroy (HWND hWnd, PSLEDITDATA sled)
|
|
{
|
|
DestroyCaret (hWnd);
|
|
if ( (GetWindowStyle(hWnd) & ES_TIP) && sled->tiptext)
|
|
FreeFixStr (sled->tiptext);
|
|
testr_free (&sled->content);
|
|
}
|
|
|
|
static inline BOOL sleContentToVisible (PSLEDITDATA sled, int *x)
|
|
{
|
|
if (x)
|
|
*x -= sled->nContX;
|
|
else
|
|
return -1;
|
|
|
|
if (*x < 0 || *x > sled->nVisW)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
static inline BOOL sleVisibleToWindow (PSLEDITDATA sled, int *x)
|
|
{
|
|
if (x)
|
|
*x += sled->leftMargin;
|
|
return TRUE;
|
|
}
|
|
|
|
static inline void sleContentToWindow (PSLEDITDATA sled, int *x)
|
|
{
|
|
sleContentToVisible (sled, x);
|
|
sleVisibleToWindow (sled, x);
|
|
}
|
|
|
|
static inline void sleWindowToContent (PSLEDITDATA sled, int *x)
|
|
{
|
|
*x -= sled->leftMargin;
|
|
*x += sled->nContX;
|
|
}
|
|
|
|
/* sets the current caret position in the virtual content window */
|
|
static void mySetCaretPos (HWND hWnd, PSLEDITDATA sled, int x)
|
|
{
|
|
if (sleContentToVisible(sled, &x) < 0) {
|
|
HideCaret (hWnd);
|
|
} else {
|
|
sleVisibleToWindow (sled, &x);
|
|
SetCaretPos (hWnd, x, sled->starty);
|
|
ActiveCaret (hWnd);
|
|
/* fix bug 4349: CENTER style does not work when startup*/
|
|
if (sled->status & EST_FOCUSED) {
|
|
ShowCaret (hWnd);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int get_caretpos_x(HWND hWnd)
|
|
{
|
|
PCONTROL pWin = (PCONTROL)hWnd;
|
|
|
|
if (!pWin->pCaretInfo)
|
|
return FALSE;
|
|
|
|
return pWin->pCaretInfo->x;
|
|
}
|
|
|
|
static void slePaint (HWND hWnd, HDC hdc, PSLEDITDATA sled)
|
|
{
|
|
char* dispBuffer, *passwdBuffer = NULL;
|
|
DWORD dwStyle = GetWindowStyle(hWnd);
|
|
StrBuffer *content = &sled->content;
|
|
int starty = sled->starty;
|
|
int outw = 0;
|
|
int startx;
|
|
|
|
//FIXME, normal case of ES_TIP?
|
|
if (dwStyle & ES_TIP && content->txtlen <= 0 &&
|
|
GetFocus(GetParent(hWnd)) != hWnd) {
|
|
setup_dc (hWnd, sled, hdc, FALSE);
|
|
TextOut (hdc, sled->leftMargin, starty,
|
|
sled->tiptext);
|
|
return;
|
|
}
|
|
|
|
if (dwStyle & ES_PASSWORD) {
|
|
dispBuffer = FixStrAlloc (content->txtlen);
|
|
memset (dispBuffer, sled->passwdChar, content->txtlen);
|
|
passwdBuffer = dispBuffer;
|
|
}
|
|
else {
|
|
dispBuffer = (char*)content->string;
|
|
}
|
|
|
|
if (dwStyle & ES_BASELINE) {
|
|
SetPenColor (hdc,
|
|
GetWindowElementPixelEx (hWnd, hdc, WE_FGC_WINDOW));
|
|
#ifdef _PHONE_WINDOW_STYLE
|
|
MoveTo (hdc, sled->leftMargin, sled->rcVis.bottom);
|
|
LineTo (hdc, sled->rcVis.right, sled->rcVis.bottom);
|
|
#else
|
|
DrawHDotLine (hdc,
|
|
sled->leftMargin,
|
|
sled->rcVis.bottom,
|
|
sled->rcVis.right - sled->rcVis.left);
|
|
#endif
|
|
}
|
|
|
|
ClipRectIntersect (hdc, &sled->rcVis);
|
|
|
|
if (sled->selStart != sled->selEnd) {//select chars
|
|
startx = sled->startx;
|
|
sleContentToWindow (sled, &startx);
|
|
/* draw first normal chars */
|
|
if (sled->selStart > 0) {
|
|
setup_dc (hWnd, sled, hdc, FALSE);
|
|
outw += TextOutLen (hdc, startx, starty,
|
|
dispBuffer, sled->selStart);
|
|
dispBuffer += sled->selStart;
|
|
}
|
|
|
|
/* draw selected chars */
|
|
setup_dc (hWnd, sled, hdc, TRUE);
|
|
outw += TextOutLen (hdc, startx + outw, starty, dispBuffer,
|
|
sled->selEnd - sled->selStart);
|
|
dispBuffer += sled->selEnd - sled->selStart;
|
|
|
|
/* draw others */
|
|
if (sled->selEnd < content->txtlen) {
|
|
setup_dc (hWnd, sled, hdc, FALSE);
|
|
outw += TextOutLen (hdc, startx + outw, starty, dispBuffer,
|
|
content->txtlen - sled->selEnd);
|
|
}
|
|
}
|
|
else {
|
|
setup_dc (hWnd, sled, hdc, FALSE);
|
|
startx = sled->startx;
|
|
sleContentToWindow (sled, &startx);
|
|
outw += TextOutLen (hdc, startx, starty, dispBuffer, content->txtlen);
|
|
}
|
|
|
|
if (dwStyle & ES_PASSWORD)
|
|
FreeFixStr (passwdBuffer);
|
|
}
|
|
|
|
static int sleSetSel (HWND hWnd, PSLEDITDATA sled, int sel_start, int sel_end)
|
|
{
|
|
if (sled->content.txtlen <= 0)
|
|
return -1;
|
|
|
|
if (sel_start < 0)
|
|
sel_start = 0;
|
|
if (sel_end < 0)
|
|
sel_end = sled->content.txtlen;
|
|
if (sel_start == sel_end)
|
|
return -1;
|
|
|
|
sled->selStart = sel_start;
|
|
sled->selEnd = sel_end;
|
|
|
|
/* houhh 20101129, set cart position to sled->selEnd. */
|
|
if (sled->selEnd >= sled->selStart) {
|
|
int cx = 0;
|
|
make_charpos_visible (hWnd, sled, sled->selEnd, &cx);
|
|
mySetCaretPos (hWnd, sled, cx);
|
|
}
|
|
|
|
/*
|
|
* for bug 4894, when select text don't hide caret, because this will close
|
|
* the ime window. by humingming 2010.8.17
|
|
*/
|
|
//HideCaret(hWnd);
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
|
|
return sled->selEnd - sled->selStart;
|
|
}
|
|
|
|
/*
|
|
* set caret position according to the new desired x coordinate.
|
|
*/
|
|
static void set_caret_pos (HWND hWnd, PSLEDITDATA sled, int x, BOOL bSel)
|
|
{
|
|
int out_chars;
|
|
HDC hdc;
|
|
SIZE txtsize;
|
|
hdc = GetClientDC (hWnd);
|
|
|
|
sleWindowToContent (sled, &x);
|
|
if (x - sled->startx <= 0) {
|
|
out_chars = 0;
|
|
txtsize.cx = 0;
|
|
}
|
|
else {
|
|
/* DK [10/05/07] for fix bug4542: Replace content of edit to a same length
|
|
* string which is made up of '*' character when the edit control include
|
|
* ES_PASSWORD style, for take the right content width. */
|
|
if ((GetWindowStyle(hWnd) & ES_PASSWORD)) {
|
|
int sled_width = x - sled->startx;
|
|
int max_char_len = 0;
|
|
GetTextExtent(hdc, "*", 1, &txtsize);
|
|
max_char_len = sled_width / txtsize.cx;
|
|
out_chars = sled->content.txtlen > max_char_len ?
|
|
max_char_len : sled->content.txtlen;
|
|
txtsize.cx *= out_chars;
|
|
}
|
|
else {
|
|
const char* sled_string = (const char*)sled->content.string;
|
|
out_chars = GetTextExtentPoint (hdc, sled_string,
|
|
sled->content.txtlen,
|
|
x - sled->startx,
|
|
NULL, NULL, NULL, &txtsize);
|
|
}
|
|
}
|
|
if (!bSel) {
|
|
sled->editPos = out_chars;
|
|
sled->selStart = sled->selEnd = sled->editPos;
|
|
//mySetCaretPos (hWnd, sled, txtsize.cx + sled->startx);
|
|
}
|
|
else {
|
|
if (out_chars > sled->editPos) {
|
|
sled->selStart = sled->editPos;
|
|
sled->selEnd = out_chars;
|
|
}
|
|
else {
|
|
sled->selEnd = sled->editPos;
|
|
sled->selStart = out_chars;
|
|
}
|
|
}
|
|
|
|
/* move caret with select end. */
|
|
if (sled->editPos == sled->selStart)
|
|
make_charpos_visible (hWnd, sled, sled->selEnd, NULL);
|
|
else
|
|
make_charpos_visible (hWnd, sled, sled->selStart, NULL);
|
|
mySetCaretPos (hWnd, sled, txtsize.cx + sled->startx);
|
|
|
|
ReleaseDC (hdc);
|
|
}
|
|
|
|
static BOOL make_pos_visible (HWND hWnd, PSLEDITDATA sled, int x)
|
|
{
|
|
if (x - sled->nContX > sled->nVisW) {
|
|
sled->nContX = x - sled->nVisW;
|
|
return TRUE;
|
|
}
|
|
else if (x < sled->nContX) {
|
|
sled->nContX = x;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL
|
|
make_charpos_visible (HWND hWnd, PSLEDITDATA sled, int charPos, int *cx)
|
|
{
|
|
SIZE txtsize;
|
|
HDC hdc;
|
|
|
|
if (charPos <= 0)
|
|
txtsize.cx = 0;
|
|
else {
|
|
char* string = (char*)sled->content.string;
|
|
int dwStyle = GetWindowStyle(hWnd);
|
|
hdc = GetClientDC (hWnd);
|
|
if (dwStyle & ES_PASSWORD) {
|
|
string = FixStrAlloc (sled->content.txtlen);
|
|
memset (string, sled->passwdChar, sled->content.txtlen);
|
|
}
|
|
GetTextExtent (hdc, (const char*)string,
|
|
charPos, &txtsize);
|
|
if (dwStyle & ES_PASSWORD)
|
|
FreeFixStr (string);
|
|
ReleaseDC (hdc);
|
|
}
|
|
if (cx)
|
|
*cx = sled->startx + txtsize.cx;
|
|
return make_pos_visible (hWnd, sled, sled->startx + txtsize.cx);
|
|
}
|
|
|
|
static void
|
|
calc_content_width(HWND hWnd, PSLEDITDATA sled, int charPos, int *cx)
|
|
{
|
|
SIZE txtsize;
|
|
HDC hdc;
|
|
|
|
if (charPos <= 0)
|
|
txtsize.cx = 0;
|
|
else {
|
|
hdc = GetClientDC (hWnd);
|
|
GetTextExtent (hdc, (const char*)sled->content.string,
|
|
charPos, &txtsize);
|
|
ReleaseDC (hdc);
|
|
}
|
|
if (cx)
|
|
*cx = txtsize.cx;
|
|
|
|
}
|
|
|
|
static void
|
|
calc_charpos_cx (HWND hWnd, PSLEDITDATA sled, int charPos, int *cx)
|
|
{
|
|
SIZE txtsize;
|
|
HDC hdc;
|
|
|
|
if (charPos <= 0)
|
|
txtsize.cx = 0;
|
|
else {
|
|
hdc = GetClientDC (hWnd);
|
|
GetTextExtent (hdc, (const char*)sled->content.string,
|
|
charPos, &txtsize);
|
|
ReleaseDC (hdc);
|
|
}
|
|
if (cx)
|
|
*cx = sled->startx + txtsize.cx;
|
|
|
|
}
|
|
|
|
/*
|
|
* set caret position according to the current edit position.
|
|
*/
|
|
static BOOL edtSetCaretPos (HWND hWnd, PSLEDITDATA sled)
|
|
{
|
|
BOOL bRefresh;
|
|
int cx;
|
|
|
|
bRefresh = make_charpos_visible (hWnd, sled, sled->editPos, &cx);
|
|
|
|
mySetCaretPos (hWnd, sled, cx);
|
|
if (bRefresh) {
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
return bRefresh;
|
|
}
|
|
static void set_edit_caret_pos(HWND hWnd, PSLEDITDATA sled)
|
|
{
|
|
int cx;
|
|
|
|
make_charpos_visible (hWnd, sled, sled->editPos, &cx);
|
|
mySetCaretPos (hWnd, sled, cx);
|
|
}
|
|
|
|
static int sleMouseMove (HWND hWnd, PSLEDITDATA sled, LPARAM lParam)
|
|
{
|
|
int selStart, selEnd;
|
|
int mouseX, mouseY;
|
|
RECT rcClient;
|
|
|
|
mouseX = LOSWORD(lParam);
|
|
mouseY = HISWORD(lParam);
|
|
|
|
ScreenToClient(hWnd, &mouseX, &mouseY);
|
|
GetClientRect(hWnd, &rcClient);
|
|
|
|
selStart = sled->selStart;
|
|
selEnd = sled->selEnd;
|
|
if (mouseX < 0) {
|
|
mouseX = 0;
|
|
if (sled->selStart > 0) {
|
|
shift_one_char_l (selStart);
|
|
make_charpos_visible (hWnd, sled, sled->selStart, NULL);
|
|
}
|
|
else {
|
|
return -1;
|
|
}
|
|
}
|
|
if (mouseX > RECTW(rcClient)) {
|
|
mouseX = RECTW(rcClient) - 1;
|
|
if (sled->selEnd < sled->content.txtlen) {
|
|
shift_one_char_r (selEnd);
|
|
make_charpos_visible (hWnd, sled, sled->selEnd, NULL);
|
|
}
|
|
else {
|
|
return -1;
|
|
}
|
|
}
|
|
set_caret_pos (hWnd, sled, mouseX, TRUE);
|
|
|
|
check_caret();
|
|
if (selStart != sled->selStart || selEnd != sled->selEnd)
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void set_line_width (HWND hWnd, PSLEDITDATA sled)
|
|
{
|
|
SIZE txtsize;
|
|
HDC hdc;
|
|
DWORD dwStyle = GetWindowStyle(hWnd);
|
|
int old_w = sled->nContW;
|
|
|
|
hdc = GetClientDC (hWnd);
|
|
SelectFont (hdc, GetWindowFont(hWnd));
|
|
GetTextExtent(hdc, (const char*)(sled->content.string),
|
|
sled->content.txtlen, &txtsize);
|
|
ReleaseDC (hdc);
|
|
|
|
if (txtsize.cx > sled->nVisW)
|
|
sled->nContW = txtsize.cx;
|
|
else
|
|
sled->nContW = sled->nVisW;
|
|
|
|
if (dwStyle & ES_RIGHT) {
|
|
sled->nContX += (sled->nContW - old_w);
|
|
}
|
|
else if (dwStyle & ES_CENTER) {
|
|
sled->nContX += (sled->nContW - old_w) >> 1;
|
|
}
|
|
|
|
if (sled->nContX + sled->nVisW > sled->nContW) {
|
|
sled->nContX = sled->nContW - sled->nVisW;
|
|
}
|
|
else if (sled->nContX < 0)
|
|
sled->nContX = 0;
|
|
|
|
if (sled->nContW > sled->nVisW)
|
|
sled->startx = 0;
|
|
else if (dwStyle & ES_RIGHT) {
|
|
sled->startx = sled->nVisW - txtsize.cx;
|
|
}
|
|
else if (dwStyle & ES_CENTER) {
|
|
sled->startx = (sled->nVisW - txtsize.cx) >> 1;
|
|
}
|
|
else {
|
|
sled->startx = 0;
|
|
}
|
|
}
|
|
|
|
static inline void edtChangeCont (HWND hWnd, PSLEDITDATA sled)
|
|
{
|
|
set_line_width (hWnd, sled);
|
|
}
|
|
|
|
/* check input validity for password style */
|
|
static void check_valid_passwd (char *newtext)
|
|
{
|
|
char *ptmp = newtext;
|
|
|
|
while (*ptmp) {
|
|
if (!isprint(*ptmp))
|
|
*ptmp = PASSWORD_REPLACEMENT;
|
|
ptmp ++;
|
|
}
|
|
}
|
|
|
|
static int
|
|
sleInsertText (HWND hWnd, PSLEDITDATA sled, char *newtext, int inserting)
|
|
{
|
|
int deleted;
|
|
unsigned char *pIns, *content = sled->content.string;
|
|
|
|
if ( (GetWindowStyle(hWnd) & ES_PASSWORD) && newtext && inserting > 0 ) {
|
|
check_valid_passwd (newtext);
|
|
}
|
|
|
|
//delete the seleted
|
|
if(sled->selStart != sled->selEnd) {
|
|
deleted = sled->selEnd - sled->selStart;
|
|
memmove (content + sled->selStart, content + sled->selEnd,
|
|
sled->content.txtlen - sled->selEnd);
|
|
sled->content.txtlen -= deleted;
|
|
|
|
sled->editPos = sled->selStart;
|
|
sled->selEnd = sled->selStart;
|
|
ShowCaret(hWnd);
|
|
|
|
if (!newtext)
|
|
inserting = 0;
|
|
}
|
|
|
|
if ( !(sled->status & EST_REPLACE) && inserting > 0
|
|
&& sled->hardLimit >= 0
|
|
&& ((sled->content.txtlen + inserting) > sled->hardLimit)) {
|
|
Ping ();
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_MAXTEXT);
|
|
inserting = sled->hardLimit - sled->content.txtlen;
|
|
return 0;
|
|
}
|
|
else if ( (sled->status & EST_REPLACE) && inserting > 0
|
|
&& sled->hardLimit >= 0
|
|
&& (sled->editPos + inserting > sled->hardLimit) ) {
|
|
Ping ();
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_MAXTEXT);
|
|
inserting = sled->hardLimit - sled->editPos;
|
|
}
|
|
|
|
if (inserting > 0) {
|
|
content = testr_realloc (&sled->content, sled->content.txtlen +
|
|
inserting);
|
|
pIns = content + sled->editPos;
|
|
if ( !(sled->status & EST_REPLACE) )
|
|
memmove (pIns + inserting, pIns,
|
|
sled->content.txtlen+1 - sled->editPos);
|
|
memcpy (pIns, newtext, inserting);
|
|
}
|
|
else if (inserting < 0) {
|
|
pIns = content + sled->editPos;
|
|
memmove (pIns + inserting, pIns,
|
|
sled->content.txtlen+1 - sled->editPos);
|
|
content = testr_realloc (&sled->content, sled->content.txtlen +
|
|
inserting);
|
|
}
|
|
|
|
if (inserting <= 0 || !(sled->status & EST_REPLACE))
|
|
sled->content.txtlen += inserting;
|
|
else {
|
|
int add_len = inserting - sled->content.txtlen + sled->editPos;
|
|
if (add_len > 0) {
|
|
sled->content.txtlen += add_len;
|
|
sled->content.string[sled->content.txtlen] = '\0';
|
|
}
|
|
}
|
|
sled->editPos += inserting;
|
|
sled->selStart = sled->selEnd = sled->editPos;
|
|
|
|
//FIXME
|
|
edtChangeCont (hWnd, sled);
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
|
|
if (!edtSetCaretPos (hWnd, sled)) {
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
sled->changed = TRUE;
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CHANGE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
sleInsertText_refresh (HWND hWnd,
|
|
PSLEDITDATA sled, char *newtext, int inserting)
|
|
{
|
|
int deleted;
|
|
unsigned char *pIns, *content = sled->content.string;
|
|
|
|
if ( (GetWindowStyle(hWnd) & ES_PASSWORD) && newtext && inserting > 0 ) {
|
|
check_valid_passwd (newtext);
|
|
}
|
|
|
|
//delete the seleted
|
|
if(sled->selStart != sled->selEnd) {
|
|
deleted = sled->selEnd - sled->selStart;
|
|
memmove (content + sled->selStart, content + sled->selEnd,
|
|
sled->content.txtlen - sled->selEnd);
|
|
sled->content.txtlen -= deleted;
|
|
|
|
sled->editPos = sled->selStart;
|
|
sled->selEnd = sled->selStart;
|
|
ShowCaret(hWnd);
|
|
if (!newtext)
|
|
inserting = 0;
|
|
}
|
|
|
|
if ( !(sled->status & EST_REPLACE) && inserting > 0 && sled->hardLimit >= 0
|
|
&& ((sled->content.txtlen + inserting) > sled->hardLimit)) {
|
|
Ping ();
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_MAXTEXT);
|
|
inserting = sled->hardLimit - sled->content.txtlen;
|
|
//return 0;
|
|
}
|
|
else if ( (sled->status & EST_REPLACE) && inserting > 0
|
|
&& sled->hardLimit >= 0
|
|
&& (sled->editPos + inserting > sled->hardLimit) ) {
|
|
Ping ();
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_MAXTEXT);
|
|
inserting = sled->hardLimit - sled->editPos;
|
|
}
|
|
|
|
if (inserting > 0) {
|
|
content = testr_realloc (&sled->content, sled->content.txtlen +
|
|
inserting);
|
|
pIns = content + sled->editPos;
|
|
if ( !(sled->status & EST_REPLACE) )
|
|
memmove (pIns + inserting, pIns,
|
|
sled->content.txtlen+1 - sled->editPos);
|
|
memcpy (pIns, newtext, inserting);
|
|
}
|
|
else if (inserting < 0) {
|
|
pIns = content + sled->editPos;
|
|
memmove (pIns + inserting, pIns,
|
|
sled->content.txtlen+1 - sled->editPos);
|
|
content = testr_realloc (&sled->content, sled->content.txtlen +
|
|
inserting);
|
|
}
|
|
|
|
if (inserting <= 0 || !(sled->status & EST_REPLACE))
|
|
sled->content.txtlen += inserting;
|
|
else {
|
|
int add_len = inserting - sled->content.txtlen + sled->editPos;
|
|
if (add_len > 0) {
|
|
sled->content.txtlen += add_len;
|
|
sled->content.string[sled->content.txtlen] = '\0';
|
|
}
|
|
}
|
|
sled->editPos += inserting;
|
|
sled->selStart = sled->selEnd = sled->editPos;
|
|
|
|
//FIXME
|
|
edtChangeCont (hWnd, sled);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sleCaseText (char* txt, BOOL bupper)
|
|
{
|
|
char *str;
|
|
char (*tocase)(char);
|
|
|
|
if (NULL == txt)
|
|
return -1;
|
|
|
|
if (bupper)
|
|
tocase = (char(*)(char))toupper;
|
|
else
|
|
tocase = (char(*)(char))tolower;
|
|
|
|
str = txt;
|
|
while (*str != '\0') {
|
|
str[0] = tocase(str[0]);
|
|
str ++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef _MGHAVE_CLIPBOARD
|
|
static int sleInsertCbText (HWND hWnd, PSLEDITDATA sled)
|
|
{
|
|
int inserting;
|
|
unsigned char *txtBuffer;
|
|
|
|
if (GetWindowStyle(hWnd) & ES_READONLY) {
|
|
return 0;
|
|
}
|
|
|
|
inserting = GetClipBoardDataLen (CBNAME_TEXT);
|
|
txtBuffer = ALLOCATE_LOCAL (inserting);
|
|
GetClipBoardData (CBNAME_TEXT, txtBuffer, inserting);
|
|
txtBuffer[inserting]=0;
|
|
|
|
if (GetWindowStyle(hWnd) & ES_UPPERCASE)
|
|
sleCaseText((char *)txtBuffer, TRUE);
|
|
else if (GetWindowStyle(hWnd) & ES_LOWERCASE)
|
|
sleCaseText((char *)txtBuffer, FALSE);
|
|
|
|
sleInsertText (hWnd, sled, (char *)txtBuffer, inserting);
|
|
DEALLOCATE_LOCAL(txtBuffer);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static void esright_backspace_refresh(HWND hWnd, PSLEDITDATA sled, int del)
|
|
{
|
|
RECT scroll_rc, refresh_rc;
|
|
int sel_start_x, sel_end_x;
|
|
int old_caret_x, cur_caret_x;
|
|
int scroll_len;
|
|
int old_editpos_x, cur_editpos_x;
|
|
|
|
scroll_rc.top = sled->rcVis.top;
|
|
scroll_rc.bottom = sled->rcVis.bottom;
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
if (sled->selStart != sled->selEnd){
|
|
|
|
calc_charpos_cx(hWnd, sled, sled->selStart, &sel_start_x);
|
|
calc_charpos_cx(hWnd, sled, sled->selEnd, &sel_end_x);
|
|
if (sled->selStart < sled->selEnd){
|
|
scroll_rc.right = sel_end_x + 1;
|
|
}
|
|
else{
|
|
scroll_rc.right = sel_start_x + 1;
|
|
}
|
|
|
|
scroll_rc.left = sled->rcVis.left;
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
|
|
scroll_len = abs(sel_start_x - sel_end_x);
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
edtSetCaretPos (hWnd, sled);
|
|
}
|
|
else{
|
|
calc_charpos_cx(hWnd, sled, sled->editPos, &old_editpos_x);
|
|
scroll_rc.left = sled->rcVis.left;
|
|
calc_charpos_cx(hWnd, sled, sled->editPos + del, &cur_editpos_x);
|
|
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
|
|
edtSetCaretPos (hWnd, sled);
|
|
scroll_rc.right = old_editpos_x + 1;
|
|
|
|
scroll_len = abs(cur_editpos_x - old_editpos_x);
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
else{
|
|
|
|
if (sled->nContX <= 0){//left scroll window while the head of text is in the sled->rcVis
|
|
if (sled->selStart != sled->selEnd){
|
|
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
refresh_rc.right = sled->rcVis.right;
|
|
|
|
scroll_rc.right = sled->rcVis.right;
|
|
|
|
calc_charpos_cx(hWnd, sled, sled->selStart, &sel_start_x);
|
|
calc_charpos_cx(hWnd, sled, sled->selEnd, &sel_end_x);
|
|
if (sled->selStart < sled->selEnd){
|
|
scroll_rc.left = sel_start_x + 1;
|
|
}
|
|
else{
|
|
scroll_rc.left = sel_end_x + 1;
|
|
}
|
|
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
edtSetCaretPos (hWnd, sled);
|
|
|
|
scroll_len = abs(sel_start_x - sel_end_x);
|
|
refresh_rc.left = refresh_rc.right - scroll_len;
|
|
ScrollWindow(hWnd, -scroll_len, 0, &scroll_rc, NULL);
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
|
|
}
|
|
else{
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
refresh_rc.right = sled->rcVis.right;
|
|
|
|
scroll_rc.right = sled->rcVis.right;
|
|
old_caret_x = get_caretpos_x(hWnd);
|
|
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
edtSetCaretPos (hWnd, sled);
|
|
cur_caret_x = get_caretpos_x(hWnd);
|
|
scroll_rc.left = cur_caret_x;
|
|
|
|
scroll_len = abs(cur_caret_x - old_caret_x);
|
|
refresh_rc.left = refresh_rc.right - scroll_len;
|
|
ScrollWindow(hWnd, -scroll_len, 0, &scroll_rc, NULL);
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
|
|
}
|
|
else{//right scroll window while sled->nContX > 0
|
|
if (sled->selStart != sled->selEnd){
|
|
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
refresh_rc.left = sled->rcVis.left;
|
|
|
|
calc_charpos_cx(hWnd, sled, sled->selStart, &sel_start_x);
|
|
calc_charpos_cx(hWnd, sled, sled->selEnd, &sel_end_x);
|
|
if (sled->selStart < sled->selEnd){
|
|
scroll_rc.right = sel_end_x + 1 - sled->nContX;
|
|
}
|
|
else{
|
|
scroll_rc.right = sel_start_x + 1 - sled->nContX;
|
|
}
|
|
|
|
scroll_rc.left = sled->rcVis.left;
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
|
|
scroll_len = abs(sel_start_x - sel_end_x);
|
|
refresh_rc.right = refresh_rc.left + scroll_len;
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
edtSetCaretPos (hWnd, sled);
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
|
|
if (sled->nContX <= 0){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
else{
|
|
int old_ncontw;
|
|
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
refresh_rc.left = sled->rcVis.left;
|
|
|
|
scroll_rc.left = sled->rcVis.left;
|
|
old_ncontw = sled->nContW;
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
edtSetCaretPos (hWnd, sled);
|
|
cur_caret_x = get_caretpos_x(hWnd);
|
|
scroll_rc.right = cur_caret_x;
|
|
|
|
scroll_len = abs(sled->nContW - old_ncontw);
|
|
refresh_rc.right = refresh_rc.left + abs(scroll_len);
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
|
|
if (sled->nContX <= 0){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sled->changed = TRUE;
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CHANGE);
|
|
}
|
|
|
|
static void esright_del_refresh(HWND hWnd, PSLEDITDATA sled, int del)
|
|
{
|
|
RECT scroll_rc, refresh_rc;
|
|
int sel_start_x, sel_end_x;
|
|
int old_caret_x, cur_caret_x;
|
|
int scroll_len;
|
|
int old_editpos_x, cur_editpos_x;
|
|
|
|
scroll_rc.top = sled->rcVis.top;
|
|
scroll_rc.bottom = sled->rcVis.bottom;
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
if (sled->selStart != sled->selEnd){
|
|
|
|
calc_charpos_cx(hWnd, sled, sled->selStart, &sel_start_x);
|
|
calc_charpos_cx(hWnd, sled, sled->selEnd, &sel_end_x);
|
|
if (sled->selStart < sled->selEnd){
|
|
scroll_rc.right = sel_end_x + 1;
|
|
}
|
|
else{
|
|
scroll_rc.right = sel_start_x + 1;
|
|
}
|
|
|
|
scroll_rc.left = sled->rcVis.left;
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
|
|
scroll_len = abs(sel_start_x - sel_end_x);
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
edtSetCaretPos (hWnd, sled);
|
|
}
|
|
else{
|
|
old_caret_x = get_caretpos_x(hWnd);
|
|
scroll_rc.left = sled->rcVis.left;
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
edtSetCaretPos (hWnd, sled);
|
|
cur_caret_x = get_caretpos_x(hWnd);
|
|
scroll_rc.right = cur_caret_x;
|
|
|
|
scroll_len = cur_caret_x - old_caret_x;
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
else{
|
|
if (sled->nContX <=0){//left scroll window while the head of text is in the sled->rcVis
|
|
if (sled->selStart != sled->selEnd){
|
|
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
refresh_rc.right = sled->rcVis.right;
|
|
|
|
scroll_rc.right = sled->rcVis.right;
|
|
|
|
calc_charpos_cx(hWnd, sled, sled->selStart, &sel_start_x);
|
|
calc_charpos_cx(hWnd, sled, sled->selEnd, &sel_end_x);
|
|
if (sled->selStart < sled->selEnd){
|
|
scroll_rc.left = sel_start_x + 1;
|
|
}
|
|
else{
|
|
scroll_rc.left = sel_end_x + 1;
|
|
}
|
|
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
edtSetCaretPos (hWnd, sled);
|
|
|
|
scroll_len = abs(sel_start_x - sel_end_x);
|
|
refresh_rc.left = refresh_rc.right - scroll_len;
|
|
ScrollWindow(hWnd, -scroll_len, 0, &scroll_rc, NULL);
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
|
|
}
|
|
else{
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
refresh_rc.right = sled->rcVis.right;
|
|
|
|
scroll_rc.right = sled->rcVis.right;
|
|
|
|
scroll_rc.left = get_caretpos_x(hWnd);
|
|
calc_charpos_cx(hWnd, sled, sled->editPos, &old_editpos_x);
|
|
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
calc_charpos_cx(hWnd, sled, sled->editPos, &cur_editpos_x);
|
|
edtSetCaretPos (hWnd, sled);
|
|
|
|
scroll_len = old_editpos_x - cur_editpos_x;
|
|
refresh_rc.left = refresh_rc.right - scroll_len;
|
|
ScrollWindow(hWnd, -scroll_len, 0, &scroll_rc, NULL);
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
|
|
}
|
|
else{//right scroll window while sled->nContX > 0
|
|
if (sled->selStart != sled->selEnd){
|
|
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
refresh_rc.left = sled->rcVis.left;
|
|
|
|
calc_charpos_cx(hWnd, sled, sled->selStart, &sel_start_x);
|
|
calc_charpos_cx(hWnd, sled, sled->selEnd, &sel_end_x);
|
|
if (sled->selStart < sled->selEnd){
|
|
scroll_rc.right = sel_end_x + 1 - sled->nContX;
|
|
}
|
|
else{
|
|
scroll_rc.right = sel_start_x + 1 - sled->nContX;
|
|
}
|
|
|
|
scroll_rc.left = sled->rcVis.left;
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
|
|
scroll_len = abs(sel_start_x - sel_end_x);
|
|
refresh_rc.right = refresh_rc.left + scroll_len;
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
edtSetCaretPos (hWnd, sled);
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
|
|
if (scroll_len >= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
|
|
if (sled->nContX <= 0){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
else{
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
refresh_rc.left = sled->rcVis.left;
|
|
|
|
old_caret_x = get_caretpos_x(hWnd);
|
|
scroll_rc.left = sled->rcVis.left;
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
edtSetCaretPos (hWnd, sled);
|
|
cur_caret_x = get_caretpos_x(hWnd);
|
|
scroll_rc.right = cur_caret_x;
|
|
|
|
scroll_len = cur_caret_x - old_caret_x;
|
|
refresh_rc.right = refresh_rc.left + abs(scroll_len);
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
|
|
if (sled->nContW <= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
|
|
if (sled->nContX <= 0){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
sled->changed = TRUE;
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CHANGE);
|
|
}
|
|
|
|
static void esleft_del_refresh(HWND hWnd, PSLEDITDATA sled, int del)
|
|
{
|
|
int old_nContX = sled->nContX;
|
|
RECT scroll_rc, del_rc, refresh_rc;
|
|
int txtlen_x;
|
|
int sel_start_x, sel_end_x;
|
|
int old_caret_x, cur_caret_x;
|
|
int scroll_len;
|
|
|
|
|
|
|
|
scroll_rc.top = sled->rcVis.top;
|
|
scroll_rc.bottom = sled->rcVis.bottom;
|
|
del_rc.bottom = sled->rcVis.bottom;
|
|
del_rc.top = sled->rcVis.top;
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
|
|
if (sled->selStart != sled->selEnd){
|
|
|
|
if (sled->selStart < sled->selEnd){
|
|
calc_charpos_cx(hWnd, sled, sled->selEnd, &sel_end_x);
|
|
scroll_rc.left = sel_end_x;
|
|
}
|
|
else{
|
|
calc_charpos_cx(hWnd, sled, sled->selStart, &sel_start_x);
|
|
scroll_rc.left = sel_start_x;
|
|
}
|
|
|
|
scroll_rc.right = sled->rcVis.right;
|
|
}
|
|
else{
|
|
calc_charpos_cx(hWnd, sled, sled->editPos, &scroll_rc.left);
|
|
scroll_rc.left = scroll_rc.left - old_nContX;
|
|
scroll_rc.right = sled->rcVis.right;
|
|
}
|
|
|
|
old_caret_x = get_caretpos_x(hWnd);
|
|
calc_charpos_cx(hWnd, sled, sled->content.txtlen, &txtlen_x);
|
|
|
|
sleInsertText_refresh (hWnd, sled, NULL, del);
|
|
|
|
calc_charpos_cx(hWnd, sled, sled->editPos, &del_rc.left);
|
|
del_rc.left = del_rc.left - old_nContX;
|
|
del_rc.right = scroll_rc.left;
|
|
|
|
scroll_len = del_rc.left - scroll_rc.left;
|
|
|
|
if (abs(sel_start_x - sel_end_x) >= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
else{
|
|
if ((old_nContX > 0) && ((txtlen_x - old_nContX) <= sled->rcVis.right)){
|
|
cur_caret_x = get_caretpos_x(hWnd);
|
|
if (cur_caret_x != old_caret_x){
|
|
scroll_len = cur_caret_x - old_caret_x;
|
|
scroll_rc.left = sled->rcVis.left;
|
|
scroll_rc.right = old_caret_x;
|
|
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
|
|
refresh_rc.left = old_caret_x;
|
|
refresh_rc.right = cur_caret_x;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
}
|
|
else if (sled->selStart != sled->selEnd) {
|
|
scroll_len = sel_start_x - sel_end_x;
|
|
scroll_rc.left = sled->rcVis.left;
|
|
scroll_rc.right = old_caret_x;
|
|
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
|
|
refresh_rc.left = old_caret_x;
|
|
refresh_rc.right = cur_caret_x;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
}
|
|
else{
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
else{
|
|
int rl;
|
|
|
|
InvalidateRect(hWnd, &del_rc, TRUE);
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
calc_charpos_cx(hWnd, sled, sled->content.txtlen, &rl);
|
|
|
|
if (((sled->nContW - sled->nContX) == sled->nVisW) && (old_nContX > 0)){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
else if (rl < sled->nVisW){
|
|
refresh_rc.left = rl;
|
|
refresh_rc.right = sled->rcVis.right;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
|
|
}
|
|
else{
|
|
refresh_rc.left = sled->rcVis.right - abs(scroll_len);
|
|
refresh_rc.right = sled->rcVis.right;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static int sleKeyDown (HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL bChange = FALSE;
|
|
DWORD dwStyle = GetWindowStyle (hWnd);
|
|
PCONTROL pCtrl = gui_Control(hWnd);
|
|
PSLEDITDATA sled = (PSLEDITDATA) (pCtrl->dwAddData2);
|
|
|
|
switch (LOWORD (wParam)) {
|
|
|
|
case SCANCODE_KEYPADENTER:
|
|
case SCANCODE_ENTER:
|
|
NotifyParent (hWnd, pCtrl->id, EN_ENTER);
|
|
return 0;
|
|
|
|
case SCANCODE_HOME:
|
|
{
|
|
BOOL refresh = FALSE;
|
|
|
|
if(lParam & KS_SHIFT) {
|
|
make_pos_visible (hWnd, sled, sled->startx);
|
|
sled->selStart = 0;
|
|
sled->selEnd = sled->editPos;
|
|
check_caret();
|
|
//InvalidateRect (hWnd, NULL, TRUE);
|
|
InvalidateRect (hWnd, &sled->rcVis, TRUE);
|
|
|
|
NotifyParent (hWnd, pCtrl->id, EN_SELCHANGED);
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (sled->selStart != sled->selEnd) {
|
|
ShowCaret(hWnd);
|
|
refresh = TRUE;
|
|
}
|
|
|
|
sled->editPos = 0;
|
|
sled->selStart = sled->selEnd = 0;
|
|
|
|
if (!edtSetCaretPos (hWnd, sled) && refresh)
|
|
//InvalidateRect (hWnd, NULL, TRUE);
|
|
InvalidateRect (hWnd, &sled->rcVis, TRUE);
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
case SCANCODE_END:
|
|
{
|
|
BOOL refresh = FALSE;
|
|
|
|
if(lParam & KS_SHIFT) {
|
|
sled->selStart = sled->editPos;
|
|
sled->selEnd = sled->content.txtlen;
|
|
check_caret();
|
|
make_charpos_visible (hWnd, sled, sled->selEnd, NULL);
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
|
|
NotifyParent (hWnd, pCtrl->id, EN_SELCHANGED);
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (sled->selStart != sled->selEnd) {
|
|
ShowCaret(hWnd);
|
|
refresh = TRUE;
|
|
}
|
|
|
|
sled->editPos = sled->content.txtlen;
|
|
sled->selStart = sled->selEnd = sled->editPos;
|
|
|
|
if (!edtSetCaretPos (hWnd, sled) && refresh)
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
case SCANCODE_CURSORBLOCKLEFT:
|
|
{
|
|
BOOL refresh = FALSE;
|
|
|
|
if(lParam & KS_SHIFT) {
|
|
if (sled->selStart == sled->selEnd) {
|
|
sled->selStart = sled->selEnd = sled->editPos;
|
|
}
|
|
|
|
if (sled->selStart < sled->editPos ||
|
|
sled->selStart == sled->selEnd) {
|
|
if (sled->selStart > 0)
|
|
shift_one_char_l(selStart);
|
|
}
|
|
else {
|
|
shift_one_char_l(selEnd);
|
|
}
|
|
|
|
check_caret ();
|
|
make_charpos_visible (hWnd, sled, sled->selStart, NULL);
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
|
|
NotifyParent (hWnd, pCtrl->id, EN_SELCHANGED);
|
|
return 0;
|
|
}
|
|
|
|
if (sled->selStart != sled->selEnd) {
|
|
if (sled->editPos != sled->selEnd)
|
|
sled->editPos = sled->selEnd;
|
|
else
|
|
sled->editPos = sled->selStart;
|
|
}
|
|
|
|
if (sled->editPos > 0) {
|
|
shift_one_char_l (editPos);
|
|
}
|
|
|
|
if (sled->selStart != sled->selEnd) {
|
|
ShowCaret (hWnd);
|
|
ActiveCaret (hWnd);
|
|
refresh = TRUE;
|
|
}
|
|
|
|
sled->selStart = sled->selEnd = sled->editPos;
|
|
if (!edtSetCaretPos (hWnd, sled) && refresh) {
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
case SCANCODE_CURSORBLOCKRIGHT:
|
|
{
|
|
BOOL refresh = FALSE;
|
|
|
|
if(lParam & KS_SHIFT) {
|
|
if(sled->selStart == sled->selEnd)
|
|
sled->selStart = sled->selEnd = sled->editPos;
|
|
|
|
if (sled->selStart == sled->selEnd ||
|
|
sled->selEnd > sled->editPos) {
|
|
if (sled->selEnd < sled->content.txtlen)
|
|
shift_one_char_r (selEnd);
|
|
}
|
|
else {
|
|
shift_one_char_r (selStart);
|
|
}
|
|
|
|
check_caret ();
|
|
make_charpos_visible (hWnd, sled, sled->selEnd, NULL);
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
NotifyParent (hWnd, pCtrl->id, EN_SELCHANGED);
|
|
return 0;
|
|
}
|
|
|
|
if (sled->selStart != sled->selEnd) {
|
|
if (sled->editPos != sled->selEnd)
|
|
sled->editPos = sled->selEnd;
|
|
else
|
|
sled->editPos = sled->selStart;
|
|
}
|
|
|
|
if (sled->editPos < sled->content.txtlen) {
|
|
shift_one_char_r (editPos);
|
|
}
|
|
|
|
if (sled->selStart != sled->selEnd) {
|
|
ShowCaret (hWnd);
|
|
ActiveCaret (hWnd);
|
|
refresh = TRUE;
|
|
}
|
|
|
|
sled->selStart = sled->selEnd = sled->editPos;
|
|
if (!edtSetCaretPos (hWnd, sled) && refresh)
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
return 0;
|
|
|
|
case SCANCODE_REMOVE:
|
|
{
|
|
int del;
|
|
int oldpos = sled->editPos;
|
|
|
|
if ((dwStyle & ES_READONLY))
|
|
return 0;
|
|
if (sled->editPos == sled->content.txtlen
|
|
&& sled->selStart == sled->selEnd)
|
|
return 0;
|
|
|
|
if (sled->selStart == sled->selEnd &&
|
|
sled->editPos < sled->content.txtlen) {
|
|
shift_one_char_r(editPos);
|
|
}
|
|
|
|
del = oldpos - sled->editPos;
|
|
if (dwStyle & ES_LEFT) {
|
|
esleft_del_refresh(hWnd, sled, del);
|
|
|
|
if (!edtSetCaretPos (hWnd, sled)) {
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
|
|
sled->changed = TRUE;
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CHANGE);
|
|
}
|
|
else if (dwStyle & ES_RIGHT) {
|
|
esright_del_refresh(hWnd, sled, del);
|
|
//sleInsertText (hWnd, sled, NULL, del);
|
|
}
|
|
else if (dwStyle & ES_CENTER) {
|
|
sleInsertText (hWnd, sled, NULL, del);
|
|
}
|
|
else {
|
|
sleInsertText (hWnd, sled, NULL, del);
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case SCANCODE_BACKSPACE:
|
|
{
|
|
int del;
|
|
|
|
if (dwStyle & ES_READONLY)
|
|
return 0;
|
|
if (sled->editPos == 0 && sled->selStart == sled->selEnd)
|
|
return 0;
|
|
|
|
del = - CHLENPREV( sled->content.string,
|
|
(sled->content.string + sled->editPos) );
|
|
sleInsertText (hWnd, sled, NULL, del);
|
|
}
|
|
break;
|
|
|
|
case SCANCODE_A:
|
|
{
|
|
if (lParam & KS_CTRL) {
|
|
sleSetSel (hWnd, sled, 0, sled->content.txtlen);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef _MGHAVE_CLIPBOARD
|
|
case SCANCODE_C:
|
|
case SCANCODE_X:
|
|
{
|
|
if ((lParam & KS_CTRL) && (sled->selEnd - sled->selStart > 0)) {
|
|
SetClipBoardData (CBNAME_TEXT, sled->content.string + sled->selStart,
|
|
sled->selEnd - sled->selStart, CBOP_NORMAL);
|
|
if (wParam == SCANCODE_X && !(GetWindowStyle(hWnd) & ES_READONLY)) {
|
|
sleInsertText (hWnd, sled, NULL, 0);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
case SCANCODE_V:
|
|
{
|
|
if (!(lParam & KS_CTRL))
|
|
return 0;
|
|
return sleInsertCbText (hWnd, sled);
|
|
}
|
|
#endif /* _MGHAVE_CLIPBOARD */
|
|
|
|
case SCANCODE_INSERT:
|
|
sled->status ^= EST_REPLACE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
} //end switch
|
|
|
|
if (bChange){
|
|
sled->changed = TRUE;
|
|
NotifyParent (hWnd, pCtrl->id, EN_CHANGE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
static void
|
|
esright_input_char_refresh (HWND hWnd,
|
|
PSLEDITDATA sled, char *charBuffer, int chars)
|
|
{
|
|
RECT scroll_rc;
|
|
int scroll_len;
|
|
int old_ncontw, cur_ncontw;
|
|
int cur_caret_x;
|
|
|
|
if (sled->selStart != sled->selEnd) {
|
|
sleInsertText (hWnd, sled, (char* )charBuffer, chars);
|
|
}
|
|
else {//left scroll window
|
|
scroll_rc.top = sled->rcVis.top;
|
|
scroll_rc.bottom = sled->rcVis.bottom;
|
|
calc_content_width(hWnd, sled, sled->content.txtlen, &old_ncontw);
|
|
sleInsertText_refresh (hWnd, sled, (char* )charBuffer, chars);
|
|
|
|
calc_content_width(hWnd, sled, sled->content.txtlen, &cur_ncontw);
|
|
scroll_len = abs(old_ncontw- cur_ncontw);
|
|
cur_caret_x = get_caretpos_x(hWnd);
|
|
scroll_rc.left = sled->rcVis.left;
|
|
scroll_rc.right = cur_caret_x;
|
|
|
|
ScrollWindow(hWnd, -scroll_len, 0, &scroll_rc, NULL);
|
|
UpdateInvalidClient(hWnd, TRUE);
|
|
edtSetCaretPos (hWnd, sled);
|
|
|
|
sled->changed = TRUE;
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CHANGE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
esleft_input_char_refresh (HWND hWnd,
|
|
PSLEDITDATA sled, char *charBuffer, int chars)
|
|
{
|
|
int old_caretpos_x;
|
|
int old_sel_start, old_sel_end;
|
|
int old_sel_start_x, old_sel_end_x, cur_sel_start_x;
|
|
RECT scroll_rc, refresh_rc;
|
|
int scroll_len;
|
|
int old_edit_pos_x, cur_edit_pos_x;
|
|
int old_nContX;
|
|
//char_size is width of input chars; sel_size is width of the selected area
|
|
int char_size, sel_size;
|
|
int txtlen_x;
|
|
|
|
old_sel_start = sled->selStart;
|
|
old_sel_end = sled->selEnd;
|
|
|
|
old_caretpos_x = get_caretpos_x(hWnd);
|
|
calc_charpos_cx(hWnd, sled, sled->editPos, &old_edit_pos_x);
|
|
calc_charpos_cx(hWnd, sled, sled->content.txtlen, &txtlen_x);
|
|
old_nContX= sled->nContX;
|
|
calc_charpos_cx(hWnd, sled, old_sel_start, &old_sel_start_x);
|
|
calc_charpos_cx(hWnd, sled, old_sel_end, &old_sel_end_x);
|
|
old_sel_start_x = old_sel_start_x - sled->nContX;
|
|
old_sel_end_x = old_sel_end_x - sled->nContX;
|
|
|
|
sleInsertText_refresh (hWnd, sled, (char* )charBuffer, chars);
|
|
|
|
calc_charpos_cx(hWnd, sled, sled->editPos, &cur_edit_pos_x);
|
|
calc_charpos_cx(hWnd, sled, old_sel_start, &cur_sel_start_x);
|
|
|
|
/* Not used var
|
|
int cur_caretpos_x, cur_ncontx;
|
|
cur_ncontx = sled->nContX;
|
|
cur_caretpos_x = get_caretpos_x(hWnd);
|
|
*/
|
|
|
|
char_size = cur_edit_pos_x - cur_sel_start_x;
|
|
sel_size = abs(old_sel_start_x - old_sel_end_x);
|
|
|
|
scroll_rc.top = sled->rcVis.top;
|
|
scroll_rc.bottom = sled->rcVis.bottom;
|
|
refresh_rc.top = sled->rcVis.top;
|
|
refresh_rc.bottom = sled->rcVis.bottom;
|
|
|
|
if (char_size >= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
else{
|
|
if (old_sel_start != old_sel_end){
|
|
|
|
if (sel_size >= sled->nVisW){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
else{
|
|
if (char_size < sel_size){
|
|
//right scroll window
|
|
if ((old_nContX > 0)
|
|
&& ((txtlen_x - old_nContX) <= sled->rcVis.right)) {
|
|
scroll_len = sel_size - char_size;
|
|
scroll_rc.left = sled->rcVis.left;
|
|
scroll_rc.right = old_sel_start_x < old_sel_end_x
|
|
? old_sel_start_x : old_sel_end_x;
|
|
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
|
|
refresh_rc.left = scroll_rc.right;
|
|
refresh_rc.right = refresh_rc.left + sel_size + scroll_len;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
}
|
|
else{//left scroll window
|
|
scroll_len = -(sel_size - char_size);
|
|
scroll_rc.left = old_sel_start_x < old_sel_end_x
|
|
? old_sel_end_x : old_sel_start_x;
|
|
scroll_rc.right = sled->rcVis.right;
|
|
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
|
|
refresh_rc.left = scroll_rc.left - sel_size;
|
|
refresh_rc.right = scroll_rc.left;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
}
|
|
}
|
|
else{//when char_size > sel_size right scroll window
|
|
scroll_len = char_size - sel_size;
|
|
scroll_rc.left = old_sel_start_x < old_sel_end_x
|
|
? old_sel_end_x : old_sel_start_x;
|
|
scroll_rc.right = sled->rcVis.right;
|
|
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
|
|
refresh_rc.left = scroll_rc.left - sel_size;
|
|
refresh_rc.right = refresh_rc.left + char_size + 1;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
int right;
|
|
char_size = cur_edit_pos_x - old_edit_pos_x;
|
|
calc_charpos_cx(hWnd, sled, sled->content.txtlen, &right);
|
|
if (old_caretpos_x < sled->rcVis.right){//right scroll window
|
|
scroll_len = cur_edit_pos_x - old_edit_pos_x;
|
|
if ((sled->rcVis.right - old_caretpos_x) < scroll_len){//
|
|
scroll_len = -(scroll_len - (sled->rcVis.right- old_caretpos_x));
|
|
scroll_rc.left = sled->rcVis.left;
|
|
scroll_rc.right = old_caretpos_x;
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
|
|
refresh_rc.left = sled->rcVis.right - char_size;
|
|
refresh_rc.right = sled->rcVis.right;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
}
|
|
else{
|
|
scroll_rc.left = old_caretpos_x;
|
|
scroll_rc.right = (right < sled->rcVis.right)
|
|
? right+1 : sled->rcVis.right;
|
|
ScrollWindow(hWnd, scroll_len, 0, &scroll_rc, NULL);
|
|
|
|
refresh_rc.left = sled->rcVis.right - char_size;
|
|
refresh_rc.right = sled->rcVis.right;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
}
|
|
}
|
|
else{//left scroll window
|
|
scroll_len = old_edit_pos_x - cur_edit_pos_x;
|
|
ScrollWindow(hWnd, scroll_len, 0, &sled->rcVis, NULL);
|
|
|
|
refresh_rc.left = sled->rcVis.right - char_size;
|
|
refresh_rc.right = sled->rcVis.right;
|
|
|
|
InvalidateRect(hWnd, &refresh_rc, TRUE);
|
|
}
|
|
|
|
if (((sled->nContW - sled->nContX) == sled->nVisW)
|
|
&& (old_nContX > 0)){
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void sledit_refresh_caret (HWND hWnd, PSLEDITDATA sled, BOOL bInited)
|
|
{
|
|
DWORD dwStyle = GetWindowStyle(hWnd);
|
|
SIZE txtsize;
|
|
int outchar;
|
|
HDC hdc;
|
|
|
|
if (!sled)
|
|
return;
|
|
|
|
hdc= GetClientDC (hWnd);
|
|
outchar = GetTextExtentPoint (hdc, (const char*)sled->content.string,
|
|
sled->content.txtlen,
|
|
0,
|
|
NULL, NULL, NULL, &txtsize);
|
|
ReleaseDC (hdc);
|
|
|
|
if (bInited) {
|
|
if (dwStyle & ES_RIGHT)
|
|
sled->editPos = outchar;
|
|
else if (dwStyle & ES_CENTER)
|
|
sled->editPos = outchar/2;
|
|
else
|
|
sled->editPos = 0;
|
|
}
|
|
if (!edtSetCaretPos (hWnd, sled)) {
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
|
|
static int sledit_reset_text (HWND hWnd, PSLEDITDATA sled, char* str)
|
|
{
|
|
DWORD dwStyle = GetWindowStyle(hWnd);
|
|
char* buffer = str;
|
|
|
|
if (!sled || !buffer)
|
|
return -1;
|
|
|
|
if (dwStyle & ES_PASSWORD) {
|
|
buffer = strdup (buffer);
|
|
check_valid_passwd (buffer);
|
|
}
|
|
|
|
//we must retain the status of this control, it include is ETS_FOCUS state, that
|
|
//tell this control whether the caret is need
|
|
//sled->status = 0;
|
|
sled->selStart = 0;
|
|
sled->selEnd = 0;
|
|
|
|
if (sled->content.string) {
|
|
free (sled->content.string);
|
|
sled->content.string = NULL;
|
|
sled->content.buffsize = 0;
|
|
sled->content.txtlen = 0;
|
|
}
|
|
|
|
sledit_settext (sled, buffer);
|
|
recalcSize (hWnd, sled, TRUE);
|
|
|
|
if (dwStyle & ES_PASSWORD) { free (buffer);
|
|
}
|
|
|
|
//sledit_refresh_caret (hWnd, sled, TRUE);
|
|
|
|
sled->changed = TRUE;
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_UPDATE);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
sledit_insert_text (HWND hWnd, PSLEDITDATA sled, const char* newtext, int len)
|
|
{
|
|
int i, realen = strlen (newtext);
|
|
char* tempstr;
|
|
char* newbuffer;
|
|
DWORD dwStyle = GetWindowStyle(hWnd);
|
|
|
|
if (len > realen)
|
|
len = realen;
|
|
if (!newtext || len <= 0)
|
|
return -1;
|
|
|
|
if (dwStyle & ES_READONLY) {
|
|
return 0;
|
|
}
|
|
|
|
tempstr = (char*) malloc(realen+1);
|
|
|
|
for (i = 0; i < len && newtext[i] != '\0'; i ++)
|
|
{
|
|
if (dwStyle & ES_UPPERCASE) {
|
|
tempstr[i] = toupper (newtext[i]);
|
|
}
|
|
else if (dwStyle & ES_LOWERCASE) {
|
|
tempstr[i] = tolower (newtext[i]);
|
|
}
|
|
else
|
|
tempstr[i] = newtext[i];
|
|
}
|
|
newbuffer = tempstr;
|
|
|
|
sleInsertText (hWnd, sled, (char* )newbuffer, len);
|
|
|
|
free(tempstr);
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT
|
|
SLEditCtrlProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DWORD dwStyle;
|
|
HDC hdc;
|
|
PSLEDITDATA sled = NULL;
|
|
PMAINWIN pWin = (PMAINWIN)hWnd;
|
|
RECT rcCaret;
|
|
|
|
dwStyle = GetWindowStyle(hWnd);
|
|
|
|
if (message != MSG_CREATE)
|
|
sled = (PSLEDITDATA) GetWindowAdditionalData2 (hWnd);
|
|
|
|
switch (message) {
|
|
|
|
case MSG_CREATE:
|
|
if ( !(sled = calloc (1, sizeof (SLEDITDATA))) )
|
|
return -1;
|
|
if (sledit_init (hWnd, sled) < 0)
|
|
return -1;
|
|
break;
|
|
|
|
case MSG_DESTROY:
|
|
sledit_destroy (hWnd, sled);
|
|
free (sled);
|
|
break;
|
|
|
|
case MSG_PAINT:
|
|
{
|
|
hdc = BeginPaint (hWnd);
|
|
slePaint (hWnd, hdc, sled);
|
|
EndPaint (hWnd, hdc);
|
|
|
|
if (sled->bShowCaret)
|
|
ShowCaret (hWnd);
|
|
else
|
|
HideCaret (hWnd);
|
|
return 0;
|
|
}
|
|
|
|
case MSG_SIZECHANGED:
|
|
recalcSize (hWnd, sled, FALSE);
|
|
return 0;
|
|
|
|
case MSG_FONTCHANGING:
|
|
if (dwStyle & ES_PASSWORD)
|
|
return -1;
|
|
return 0;
|
|
|
|
case MSG_FONTCHANGED:
|
|
{
|
|
sled->starty = sled->topMargin + (sled->rcVis.bottom
|
|
- sled->rcVis.top - GetWindowFont(hWnd)->size - 1)/2;
|
|
|
|
DestroyCaret (hWnd);
|
|
CreateCaret (hWnd, NULL, 1, GetWindowFont (hWnd)->size);
|
|
|
|
recalcSize (hWnd, sled, FALSE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
case MSG_SETCURSOR:
|
|
if (dwStyle & WS_DISABLED) {
|
|
SetCursor (GetSystemCursor (IDC_ARROW));
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case MSG_KILLFOCUS:
|
|
if (sled->status & EST_FOCUSED) {
|
|
BOOL refresh = FALSE;
|
|
|
|
sled->status &= ~EST_FOCUSED;
|
|
|
|
//HideCaret (hWnd);
|
|
if (pWin->pCaretInfo) {
|
|
sled->bShowCaret = FALSE;
|
|
SetRect (&rcCaret, pWin->pCaretInfo->x, pWin->pCaretInfo->y,
|
|
pWin->pCaretInfo->x + pWin->pCaretInfo->nWidth,
|
|
pWin->pCaretInfo->y + pWin->pCaretInfo->nHeight);
|
|
InvalidateRect (hWnd, &rcCaret, FALSE);
|
|
}
|
|
|
|
if ( sled->selStart != sled->selEnd
|
|
|| (dwStyle & ES_TIP && sled->content.txtlen <= 0)) {
|
|
refresh = TRUE;
|
|
}
|
|
if (sled->selStart != sled->selEnd && !(dwStyle & ES_NOHIDESEL))
|
|
{
|
|
sled->selStart = sled->selEnd = sled->editPos;
|
|
}
|
|
|
|
if (refresh)
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_KILLFOCUS);
|
|
|
|
if (sled->changed){
|
|
sled->changed = FALSE;
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CONTCHANGED);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MSG_SETFOCUS:
|
|
if (sled->status & EST_FOCUSED)
|
|
break;
|
|
|
|
sled->status |= EST_FOCUSED;
|
|
|
|
/*[humingming/2010/10/19]:bug 5158:
|
|
* don't draw the caret here, should in MSG_PAINT. */
|
|
ActiveCaret (hWnd);
|
|
//ShowCaret(hWnd);
|
|
if (pWin->pCaretInfo) {
|
|
sled->bShowCaret = TRUE;
|
|
SetRect (&rcCaret, pWin->pCaretInfo->x, pWin->pCaretInfo->y,
|
|
pWin->pCaretInfo->x + pWin->pCaretInfo->nWidth,
|
|
pWin->pCaretInfo->y + pWin->pCaretInfo->nHeight);
|
|
InvalidateRect (hWnd, &rcCaret, FALSE);
|
|
}
|
|
|
|
if (dwStyle & ES_AUTOSELECT) {
|
|
if (sleSetSel (hWnd, sled, 0,
|
|
sled->content.txtlen) <= 0 && dwStyle & ES_TIP)
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
if (lParam == 1)
|
|
sled->status |= EST_TMP;
|
|
}
|
|
else if ( (dwStyle & ES_NOHIDESEL && sled->selStart != sled->selEnd)
|
|
|| (dwStyle & ES_TIP && sled->content.txtlen <= 0)) {
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_SETFOCUS);
|
|
break;
|
|
|
|
case MSG_ENABLE:
|
|
if ( (!(dwStyle & WS_DISABLED) && !wParam)
|
|
|| ((dwStyle & WS_DISABLED) && wParam) ) {
|
|
if (wParam)
|
|
ExcludeWindowStyle(hWnd,WS_DISABLED);
|
|
else
|
|
IncludeWindowStyle(hWnd,WS_DISABLED);
|
|
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
return 0;
|
|
|
|
case MSG_GETTEXTLENGTH:
|
|
return sled->content.txtlen;
|
|
|
|
case MSG_GETTEXT:
|
|
{
|
|
char* buffer = (char*)lParam;
|
|
int len;
|
|
|
|
len = MIN ((int)wParam, sled->content.txtlen);
|
|
memcpy (buffer, sled->content.string, len);
|
|
buffer [len] = '\0';
|
|
return len;
|
|
}
|
|
|
|
case MSG_SETTEXT:
|
|
return sledit_reset_text (hWnd, sled, (char*)lParam);
|
|
|
|
case MSG_KEYDOWN:
|
|
{
|
|
return sleKeyDown (hWnd, wParam, lParam);
|
|
}
|
|
|
|
case MSG_UTF8CHAR:
|
|
_ERR_PRINTF ("CONTROL>EDIT: MSG_UTF8CHAR is not implemented.\n");
|
|
break;
|
|
|
|
case MSG_CHAR:
|
|
{
|
|
unsigned char charBuffer [4];
|
|
int chars;
|
|
|
|
if (dwStyle & ES_READONLY)
|
|
return 0;
|
|
|
|
charBuffer [0] = FIRSTBYTE (wParam);
|
|
charBuffer [1] = SECONDBYTE (wParam);
|
|
charBuffer [2] = THIRDBYTE (wParam);
|
|
charBuffer [3] = FOURTHBYTE (wParam);
|
|
|
|
if (charBuffer [3]) {
|
|
chars = 4;
|
|
}
|
|
else if (charBuffer [2]) {
|
|
chars = 3;
|
|
}
|
|
else if (charBuffer [1]) {
|
|
chars = 2;
|
|
}
|
|
else {
|
|
chars = 1;
|
|
|
|
if (dwStyle & ES_UPPERCASE) {
|
|
charBuffer [0] = toupper (charBuffer[0]);
|
|
}
|
|
else if (dwStyle & ES_LOWERCASE) {
|
|
charBuffer [0] = tolower (charBuffer[0]);
|
|
}
|
|
}
|
|
|
|
if (chars == 1 && (charBuffer[0] == '\b' || charBuffer[0] == 0x7F)) {
|
|
// ASCII BS or DEL
|
|
int del;
|
|
|
|
if (sled->editPos == 0 && sled->selStart == sled->selEnd)
|
|
return 0;
|
|
del = -CHLENPREV((const char *)(sled->content.string),
|
|
(sled->content.string + sled->editPos) );
|
|
|
|
if (dwStyle & ES_LEFT) {
|
|
esleft_del_refresh(hWnd, sled, del);
|
|
set_edit_caret_pos(hWnd, sled);
|
|
|
|
sled->changed = TRUE;
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CHANGE);
|
|
}
|
|
else if (dwStyle & ES_RIGHT) {
|
|
esright_backspace_refresh(hWnd, sled, del);
|
|
}
|
|
else if (dwStyle & ES_CENTER) {
|
|
sleInsertText (hWnd, sled, NULL, del);
|
|
}
|
|
else {
|
|
sleInsertText (hWnd, sled, NULL, del);
|
|
}
|
|
}
|
|
else if (chars == 1 && charBuffer [0] < 0x20) {
|
|
// ignore all other ASCII control characters.
|
|
return 0;
|
|
}
|
|
else {
|
|
if (dwStyle & ES_LEFT) {
|
|
esleft_input_char_refresh(hWnd, sled, (char*)charBuffer, chars);
|
|
set_edit_caret_pos(hWnd, sled);
|
|
|
|
sled->changed = TRUE;
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CHANGE);
|
|
}
|
|
else if (dwStyle & ES_RIGHT) {
|
|
esright_input_char_refresh(hWnd, sled, (char*)charBuffer, chars);
|
|
}
|
|
else if (dwStyle & ES_CENTER) {
|
|
sleInsertText (hWnd, sled, (char* )charBuffer, chars);
|
|
|
|
}
|
|
else {
|
|
sleInsertText (hWnd, sled, (char* )charBuffer, chars);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
case MSG_LBUTTONDBLCLK:
|
|
sleSetSel (hWnd, sled, 0, sled->content.txtlen);
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_DBLCLK);
|
|
break;
|
|
|
|
case MSG_LBUTTONDOWN:
|
|
{
|
|
if ( sled->status & EST_TMP) {
|
|
sled->status &= ~EST_TMP;
|
|
break;
|
|
}
|
|
|
|
if (HISWORD(lParam) < sled->rcVis.top
|
|
|| HISWORD(lParam) > sled->rcVis.bottom)
|
|
break;
|
|
|
|
set_caret_pos (hWnd, sled, LOSWORD(lParam), FALSE);
|
|
|
|
ActiveCaret (hWnd);
|
|
ShowCaret(hWnd);
|
|
SetCapture(hWnd);
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
|
|
break;
|
|
}
|
|
|
|
case MSG_NCLBUTTONUP:
|
|
case MSG_LBUTTONUP:
|
|
if (GetCapture() == hWnd)
|
|
ReleaseCapture();
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_CLICKED);
|
|
|
|
if (sled->selStart != sled->selEnd)
|
|
NotifyParent (hWnd, GetDlgCtrlID(hWnd), EN_SELCHANGED);
|
|
|
|
break;
|
|
|
|
case MSG_MOUSEMOVE:
|
|
{
|
|
if (GetCapture () == hWnd)
|
|
sleMouseMove (hWnd, sled, lParam);
|
|
return 0;
|
|
}
|
|
|
|
case MSG_GETDLGCODE:
|
|
return DLGC_WANTCHARS| DLGC_HASSETSEL| DLGC_WANTARROWS| DLGC_WANTENTER;
|
|
|
|
case MSG_DOESNEEDIME:
|
|
if (dwStyle & ES_READONLY)
|
|
return IME_WINDOW_TYPE_READONLY;
|
|
else if (dwStyle & ES_PASSWORD)
|
|
return IME_WINDOW_TYPE_PASSWORD;
|
|
else
|
|
return IME_WINDOW_TYPE_EDITABLE;
|
|
|
|
case EM_GETCARETPOS:
|
|
case EM_GETSELPOS:
|
|
{
|
|
int nr_chars, pos;
|
|
int* line_pos = (int *)wParam;
|
|
int* char_pos = (int *)lParam;
|
|
|
|
if (message == EM_GETSELPOS)
|
|
pos = (sled->editPos == sled->selStart)
|
|
? sled->selEnd : sled->selStart;
|
|
else
|
|
pos = sled->editPos;
|
|
nr_chars = GetTextMCharInfo (GetWindowFont (hWnd),
|
|
(const char* )(sled->content.string), pos, NULL);
|
|
|
|
if (line_pos) *line_pos = 0;
|
|
if (char_pos) *char_pos = nr_chars;
|
|
|
|
return pos;
|
|
}
|
|
|
|
case EM_SETCARETPOS:
|
|
case EM_SETSEL:
|
|
{
|
|
int char_pos = (int)lParam;
|
|
int nr_chars, pos;
|
|
int *pos_chars;
|
|
|
|
if (char_pos < 0)
|
|
return -1;
|
|
|
|
pos_chars = ALLOCATE_LOCAL (sled->content.txtlen * sizeof(int));
|
|
nr_chars = GetTextMCharInfo (GetWindowFont (hWnd),
|
|
(const char* )sled->content.string, sled->content.txtlen, pos_chars);
|
|
if (char_pos > nr_chars) {
|
|
DEALLOCATE_LOCAL (pos_chars);
|
|
return -1;
|
|
}
|
|
|
|
if (char_pos == nr_chars)
|
|
pos = sled->content.txtlen;
|
|
else
|
|
pos = pos_chars[char_pos];
|
|
|
|
DEALLOCATE_LOCAL (pos_chars);
|
|
|
|
if (message == EM_SETCARETPOS) {
|
|
sled->editPos = pos;
|
|
sled->selStart = sled->selEnd = 0;
|
|
edtSetCaretPos (hWnd, sled);
|
|
return sled->editPos;
|
|
}
|
|
else {
|
|
int start, end;
|
|
if (sled->editPos < pos) {
|
|
start = sled->editPos;
|
|
end = pos;
|
|
}
|
|
else {
|
|
start = pos;
|
|
end = sled->editPos;
|
|
}
|
|
return sleSetSel (hWnd, sled, start, end);
|
|
}
|
|
}
|
|
|
|
case EM_INSERTTEXT:
|
|
{
|
|
return sledit_insert_text (hWnd, sled, (const char*)lParam, wParam);
|
|
}
|
|
|
|
case EM_SETREADONLY:
|
|
if (wParam)
|
|
IncludeWindowStyle (hWnd, ES_READONLY);
|
|
else
|
|
ExcludeWindowStyle (hWnd, ES_READONLY);
|
|
return 0;
|
|
|
|
case EM_SETPASSWORDCHAR:
|
|
if (sled->passwdChar != (int)wParam) {
|
|
sled->passwdChar = (int)wParam;
|
|
if (dwStyle & ES_PASSWORD) {
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case EM_GETPASSWORDCHAR:
|
|
{
|
|
if (lParam)
|
|
*((int*)lParam) = sled->passwdChar;
|
|
return 0;
|
|
}
|
|
|
|
case EM_GETMAXLIMIT:
|
|
return sled->hardLimit;
|
|
|
|
case EM_LIMITTEXT:
|
|
{
|
|
int newLimit = (int)wParam;
|
|
|
|
if (newLimit >= 0) {
|
|
if (sled->content.txtlen > newLimit) {
|
|
Ping ();
|
|
return -1;
|
|
}
|
|
else {
|
|
sled->hardLimit = newLimit;
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
case EM_GETTIPTEXT:
|
|
{
|
|
int len, tip_len;
|
|
char *buffer = (char *)lParam;
|
|
|
|
if (!(dwStyle & ES_TIP))
|
|
return -1;
|
|
|
|
tip_len = strlen (sled->tiptext);
|
|
|
|
if (!buffer)
|
|
return tip_len;
|
|
|
|
if (wParam >= 0)
|
|
len = (wParam > DEF_TIP_LEN) ? DEF_TIP_LEN : wParam;
|
|
else
|
|
len = DEF_TIP_LEN;
|
|
|
|
strncpy (buffer, sled->tiptext, len);
|
|
buffer[len] = '\0';
|
|
|
|
return tip_len;
|
|
}
|
|
|
|
case EM_SETTIPTEXT:
|
|
{
|
|
int len;
|
|
|
|
if (!(dwStyle & ES_TIP) || !lParam)
|
|
return -1;
|
|
|
|
if (wParam >= 0)
|
|
len = (wParam > DEF_TIP_LEN) ? DEF_TIP_LEN : wParam;
|
|
else
|
|
len = DEF_TIP_LEN;
|
|
strncpy (sled->tiptext, (char *)lParam, len);
|
|
sled->tiptext[len] = '\0';
|
|
|
|
if (sled->content.txtlen <= 0)
|
|
InvalidateRect (hWnd, NULL, TRUE);
|
|
|
|
return strlen(sled->tiptext);
|
|
}
|
|
|
|
case EM_GETSEL:
|
|
{
|
|
char *buffer = (char *)lParam;
|
|
int len;
|
|
|
|
if (!buffer || sled->selEnd - sled->selStart <= 0)
|
|
return 0;
|
|
|
|
if (wParam < 0)
|
|
len = sled->selEnd - sled->selStart;
|
|
else
|
|
len = MIN(sled->selEnd - sled->selStart, (int)wParam);
|
|
|
|
strncpy (buffer,
|
|
(const char*)(sled->content.string + sled->selStart), len);
|
|
|
|
return len;
|
|
}
|
|
|
|
case EM_INSERTCBTEXT:
|
|
{
|
|
#ifdef _CLIPBOAR_SUPPORT
|
|
return sleInsertCbText (hWnd, sled);
|
|
#endif
|
|
}
|
|
|
|
case EM_COPYTOCB:
|
|
case EM_CUTTOCB:
|
|
{
|
|
#ifdef _MGHAVE_CLIPBOARD
|
|
if (sled->selEnd - sled->selStart > 0) {
|
|
SetClipBoardData (CBNAME_TEXT,
|
|
sled->content.string + sled->selStart,
|
|
sled->selEnd - sled->selStart, CBOP_NORMAL);
|
|
if (message == EM_CUTTOCB
|
|
&& !(GetWindowStyle(hWnd) & ES_READONLY)) {
|
|
sleInsertText (hWnd, sled, NULL, 0);
|
|
}
|
|
return sled->selEnd - sled->selStart;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
|
|
} // end switch
|
|
|
|
return DefaultControlProc (hWnd, message, wParam, lParam);
|
|
}
|
|
|
|
#endif /* _MGCTRL_SLEDIT */
|