📄 multiedit.c
字号:
*
* Returns the width of the cursor to be draw according to the
* insert mode flag and the cursor position.
*/
static int _GetCursorSizeX(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
if (_IsOverwriteAtThisChar(hObj, pObj)) {
const char *pText;
pText = (const char *)GUI_ALLOC_h2p(pObj->hText);
pText += pObj->CursorPosByte;
return _GetCharDistX(pObj, pText);
} else {
return 2;
}
}
/*********************************************************************
*
* static code, buffer management
*
**********************************************************************
*/
/*********************************************************************
*
* _IncrementBuffer
*
* Increments the buffer size by AddBytes.
*/
static int _IncrementBuffer(MULTIEDIT_OBJ* pObj, unsigned AddBytes) {
WM_HMEM hNew;
int NewSize;
NewSize = pObj->BufferSize + AddBytes;
hNew = GUI_ALLOC_Realloc(pObj->hText, NewSize);
if (hNew) {
if (!(pObj->hText)) {
char* pText;
pText = (char*) GUI_ALLOC_h2p(hNew);
*pText = 0;
}
pObj->BufferSize = NewSize;
pObj->hText = hNew;
return 1;
}
return 0;
}
/*********************************************************************
*
* _IsSpaceInBuffer
*
* Checks the available space in the buffer. If there is not enough
* space left this function attempts to get more.
*
* Returns:
* 1 = requested space is available
* 0 = failed to get enough space
*/
static int _IsSpaceInBuffer(MULTIEDIT_OBJ* pObj, int BytesNeeded) {
int NumBytes = 0;
if (pObj->hText) {
NumBytes = strlen((char*)GUI_ALLOC_h2p(pObj->hText));
}
BytesNeeded = (BytesNeeded + NumBytes + 1) - pObj->BufferSize;
if (BytesNeeded > 0) {
if (!_IncrementBuffer(pObj, BytesNeeded + MULTIEDIT_REALLOC_SIZE)) {
return 0;
}
}
return 1;
}
/*********************************************************************
*
* _IsCharsAvailable
*
* Checks weither the maximum number of characters is reached or not.
*
* Returns:
* 1 = requested number of chars is available
* 0 = maximum number of chars have reached
*/
static int _IsCharsAvailable(MULTIEDIT_OBJ* pObj, int CharsNeeded) {
if ((CharsNeeded > 0) && (pObj->MaxNumChars > 0)) {
int NumChars = 0;
if (pObj->hText) {
NumChars = _GetNumChars(pObj);
}
if ((CharsNeeded + NumChars) > pObj->MaxNumChars) {
return 0;
}
}
return 1;
}
/*********************************************************************
*
* static code, string manipulation routines
*
**********************************************************************
*/
/*********************************************************************
*
* _DeleteChar
*
* Deletes a character at the current cursor position and moves
* all bytes after the cursor position.
*/
static void _DeleteChar(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
if (pObj->hText) {
unsigned CursorOffset;
char* s;
s = (char*) GUI_ALLOC_h2p(pObj->hText);
CursorOffset = pObj->CursorPosByte;
if (CursorOffset < strlen(s)) {
char *pCursor, *pLine, *pEndLine;
int CursorLine, NumChars, NumBytes;
pCursor = s + CursorOffset;
CursorLine = pObj->CursorLine;
pLine = _GetpLine(hObj, pObj, CursorLine);
NumChars = _WrapGetNumCharsDisp(hObj, pObj, pLine);
pEndLine = pLine + GUI_UC__NumChars2NumBytes(pLine, NumChars);
pLine = pLine + _WrapGetNumBytesToNextLine(hObj, pObj, pLine);
if (pCursor == pEndLine) {
NumBytes = pLine - pEndLine;
} else {
NumBytes = GUI_UC_GetCharSize(pCursor);
}
NumChars = GUI_UC__NumBytes2NumChars(pCursor, NumBytes);
strcpy(pCursor, pCursor + NumBytes);
WM_NotifyParent(hObj, WM_NOTIFICATION_VALUE_CHANGED);
pObj->NumChars -= NumChars;
_InvalidateNumLines(pObj);
_InvalidateTextSizeX(pObj);
_InvalidateCursorXY(pObj); /* Invalidate X/Y position */
_ClearCache(pObj);
pObj->CursorLine = _GetCursorLine(hObj, pObj, s, pObj->CursorPosChar);
}
}
}
/*********************************************************************
*
* _InsertChar
*
* Create space at the current cursor position and inserts a character.
*/
static int _InsertChar(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj, U16 Char) {
if (_IsCharsAvailable(pObj, 1)) {
int BytesNeeded;
BytesNeeded = GUI_UC__CalcSizeOfChar(Char);
if (_IsSpaceInBuffer(pObj, BytesNeeded)) {
int CursorOffset;
char* pText;
pText = (char*) GUI_ALLOC_h2p(pObj->hText);
CursorOffset = pObj->CursorPosByte;
pText += CursorOffset;
memmove(pText + BytesNeeded, pText, strlen(pText) + 1);
GUI_UC_Encode(pText, Char);
WM_NotifyParent(hObj, WM_NOTIFICATION_VALUE_CHANGED);
pObj->NumChars += 1;
_InvalidateNumLines(pObj);
_InvalidateTextSizeX(pObj);
_ClearCache(pObj);
return 1;
}
}
return 0;
}
/*********************************************************************
*
* static code
*
**********************************************************************
*/
/*********************************************************************
*
* _MULTIEDIT_Paint
*/
static void _MULTIEDIT_Paint(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ * pObj) {
int ScrollPosX, ScrollPosY, EffectSize, HBorder;
int x, y, xOff, yOff, ColorIndex, FontSizeY;
GUI_RECT r, rClip;
const GUI_RECT *prOldClip;
/* Init some values */
GUI_SetFont(pObj->pFont);
FontSizeY = GUI_GetFontDistY();
ScrollPosX = pObj->ScrollStateH.v;
ScrollPosY = pObj->ScrollStateV.v;
EffectSize = pObj->Widget.pEffect->EffectSize;
HBorder = pObj->HBorder;
xOff = EffectSize + HBorder - ScrollPosX ;
yOff = EffectSize - ScrollPosY * FontSizeY;
ColorIndex = ((pObj->Flags & MULTIEDIT_SF_READONLY) ? 1 : 0);
/* Set colors and draw the background */
LCD_SetBkColor(pObj->aBkColor[ColorIndex]);
LCD_SetColor(pObj->aColor[ColorIndex]);
GUI_Clear();
/* Draw the text if necessary */
rClip.x0 = EffectSize + HBorder;
rClip.y0 = EffectSize;
rClip.x1 = WM_GetWindowSizeX(hObj) - EffectSize - HBorder - 1;
rClip.y1 = WM_GetWindowSizeY(hObj) - EffectSize - 1;
prOldClip = WM_SetUserClipRect(&rClip);
if (pObj->hText) {
const char* pText;
int Line = 0;
int xSize = _GetXSize(hObj, pObj);
int NumVisLines = _GetNumVisLines(hObj, pObj);
/* Get the text */
pText = (const char *)GUI_ALLOC_h2p(pObj->hText);
/* Set the rectangle for drawing */
r.x0 = xOff;
r.y0 = EffectSize;
r.x1 = xSize + EffectSize + HBorder - 1;
r.y1 = pObj->Widget.Win.Rect.y1 - pObj->Widget.Win.Rect.y0 + 1;
/* Use cached position of first visible byte if possible */
if (ScrollPosY >= pObj->CacheFirstVisibleLine) {
if (pObj->CacheFirstVisibleByte) {
pText += pObj->CacheFirstVisibleByte;
Line = pObj->CacheFirstVisibleLine;
}
}
/* Do the drawing of the text */
do {
/* Cache the position of the first visible byte and the depending line number */
if (pObj->CacheFirstVisibleLine != ScrollPosY) {
if (Line == ScrollPosY) {
pObj->CacheFirstVisibleByte = pText - (const char *)GUI_ALLOC_h2p(pObj->hText);
pObj->CacheFirstVisibleLine = ScrollPosY;
}
}
/* Draw it */
if ((Line >= ScrollPosY) && ((Line - ScrollPosY) <= NumVisLines)) {
_DispString(hObj, pObj, pText, &r);
r.y0 += FontSizeY; /* Next line */
}
pText += _WrapGetNumBytesToNextLine(hObj, pObj, pText);
Line++;
} while (GUI_UC_GetCharCode(pText) && ((Line - ScrollPosY) <= NumVisLines));
}
/* Draw cursor if necessary */
if (WM_HasFocus(hObj)) {
_GetCursorXY(hObj, pObj, &x, &y);
r.x0 = x + xOff;
r.y0 = y + yOff;
r.x1 = r.x0 + _GetCursorSizeX(hObj, pObj) - 1;
r.y1 = r.y0 + FontSizeY - 1;
GUI_InvertRect(r.x0, r.y0, r.x1, r.y1);
}
WM_SetUserClipRect(prOldClip);
/* Draw the 3D effect (if configured) */
WIDGET__EFFECT_DrawDown(&pObj->Widget);
}
/*********************************************************************
*
* _OnTouch
*/
static void _OnTouch(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj, WM_MESSAGE*pMsg) {
int Notification;
const GUI_PID_STATE* pState = (const GUI_PID_STATE*)pMsg->Data.p;
if (pMsg->Data.p) { /* Something happened in our area (pressed or released) */
if (pState->Pressed) {
int Effect, xPos, yPos;
Effect = pObj->Widget.pEffect->EffectSize;
xPos = pState->x + pObj->ScrollStateH.v - Effect - pObj->HBorder;
yPos = pState->y + pObj->ScrollStateV.v * GUI_GetYDistOfFont(pObj->pFont) - Effect;
_SetCursorXY(hObj, pObj, xPos, yPos);
_Invalidate(hObj);
Notification = WM_NOTIFICATION_CLICKED;
} else {
Notification = WM_NOTIFICATION_RELEASED;
}
} else {
Notification = WM_NOTIFICATION_MOVED_OUT;
}
WM_NotifyParent(hObj, Notification);
}
/*********************************************************************
*
* _AddKey
*
* Returns: 1 if Key has been consumed
* 0 else
*/
static int _AddKey(MULTIEDIT_HANDLE hObj, U16 Key) {
int r = 0; /* Key has not been consumed */
MULTIEDIT_OBJ* pObj;
pObj = MULTIEDIT_H2P(hObj);
switch (Key) {
case GUI_KEY_UP:
_MoveCursorUp(hObj, pObj);
r = 1; /* Key has been consumed */
break;
case GUI_KEY_DOWN:
_MoveCursorDown(hObj, pObj);
r = 1; /* Key has been consumed */
break;
case GUI_KEY_RIGHT:
_SetCursorPos(hObj, pObj, pObj->CursorPosChar + 1);
r = 1; /* Key has been consumed */
break;
case GUI_KEY_LEFT:
_SetCursorPos(hObj, pObj, pObj->CursorPosChar - 1);
r = 1; /* Key has been consumed */
break;
case GUI_KEY_END:
_MoveCursor2LineEnd(hObj, pObj);
r = 1; /* Key has been consumed */
break;
case GUI_KEY_HOME:
_MoveCursor2LinePos1(hObj, pObj);
r = 1; /* Key has been consumed */
break;
case GUI_KEY_BACKSPACE:
if (!(pObj->Flags & MULTIEDIT_SF_READONLY)) {
if (pObj->CursorPosChar > pObj->NumCharsPrompt) {
_SetCursorPos(hObj, pObj, pObj->CursorPosChar - 1);
_DeleteChar(hObj, pObj);
}
r = 1; /* Key has been consumed */
}
break;
case GUI_KEY_DELETE:
if (!(pObj->Flags & MULTIEDIT_SF_READONLY)) {
_DeleteChar(hObj, pObj);
r = 1; /* Key has been consumed */
}
break;
case GUI_KEY_INSERT:
if (!(pObj->Flags & MULTIEDIT_CF_INSERT)) {
pObj->Flags |= MULTIEDIT_CF_INSERT;
} else {
pObj->Flags &= ~MULTIEDIT_CF_INSERT;
}
r = 1; /* Key has been consumed */
break;
case GUI_KEY_ENTER:
if (pObj->Flags & MULTIEDIT_SF_READONLY) {
_MoveCursor2NextLine(hObj, pObj);
} else {
if (_InsertChar(hObj, pObj, (U8)('\n'))) {
if (pObj->Flags & MULTIEDIT_SF_PASSWORD) {
_SetCursorPos(hObj, pObj, pObj->CursorPosChar + 1);
} else {
_MoveCursor2NextLine(hObj, pObj);
}
}
}
r = 1; /* Key has been consumed */
break;
case GUI_KEY_ESCAPE:
break;
default:
if (!(pObj->Flags & MULTIEDIT_SF_READONLY) && (Key >= 0x20)) {
if (_IsOverwriteAtThisChar(hObj, pObj)) {
_DeleteChar(hObj, pObj);
}
if (_InsertChar(hObj, pObj, Key)) {
_SetCursorPos(hObj, pObj, pObj->CursorPosChar + 1);
}
r = 1; /* Key has been consumed */
}
}
_InvalidateTextArea(hObj);
return r;
}
/*********************************************************************
*
* _MULTIEDIT_Callback
*/
static void _MULTIEDIT_Callback (WM_MESSAGE *pMsg) {
MULTIEDIT_HANDLE hObj;
MULTIEDIT_OBJ* pObj;
WM_SCROLL_STATE ScrollState;
hObj = pMsg->hWin;
/* Let widget handle the standard messages */
if (WIDGET_HandleActive(hObj, pMsg) == 0) {
return;
}
pObj = MULTIEDIT_H2P(hObj);
switch (pMsg->MsgId) {
case WM_NOTIFY_CLIENTCHANGE:
_InvalidateCursorXY(pObj);
_InvalidateNumLines(pObj);
_InvalidateTextSizeX(pObj);
_ClearCache(pObj);
_CalcScrollParas(hObj);
break;
case WM_SIZE:
_InvalidateCursorXY(pObj);
_InvalidateNumLines(pObj);
_InvalidateTextSizeX(pObj);
_ClearCache(pObj);
_Invalidate(hObj);
break;
case WM_NOTIFY_PARENT:
switch (pMsg->Data.v) {
case WM_NOTIFICATION_VALUE_CHANGED:
if (pMsg->hWinSrc == WM_GetScrollbarV(hObj)) {
WM_GetScrollState(pMsg->hWinSrc, &ScrollState);
pObj->ScrollStateV.v = ScrollState.v;
WM_InvalidateWindow(hObj);
WM_NotifyParent(hObj, WM_NOTIFICATION_SCROLL_CHANGED);
} else if (pMsg->hWinSrc == WM_GetScrollbarH(hObj)) {
WM_GetScrollState(pMsg->hWinSrc, &ScrollState);
pObj->ScrollStateH.v = ScrollState.v;
WM_InvalidateWindow(hObj);
WM_NotifyParent(hObj, WM_NOTIFICATION_SCROLL_CHANGED);
}
break;
case WM_NOTIFICATION_SCROLLBAR_ADDED:
_SetScrollState(hObj);
break;
}
break;
case WM_PAINT:
_MULTIEDIT_Paint(hObj, pObj);
return;
case WM_TOUCH:
_OnTouch(hObj, pObj, pMsg);
break;
case WM_DELETE:
GUI_ALLOC_FreePtr(&pObj->hText);
break;
case WM_KEY:
if (((const WM_KEY_INFO*)(pMsg->Data.p))->PressedCnt >0) {
int Key = ((const WM_KEY_INFO*)(pMsg->Data.p))->Key;
/* Leave code for test purpose
switch (Key) {
case '1': Key = GUI_KEY_LEFT; break;
case '2': Key = GUI_KEY_UP; break;
case '3': Key = GUI_KEY_RIGHT; break;
case '4': Key = GUI_KEY_DOWN; break;
}
*/
if (_AddKey(hObj, Key)) {
return;
}
} else {
if (!(pObj->Flags & MULTIEDIT_SF_READONLY)) {
return; /* Key release is consumed (not sent to parent) */
}
}
}
WM_DefaultProc(pMsg);
}
/*********************************************************************
*
* Exported routines: Create
*
**********************************************************************
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -