📄 multiedit.c
字号:
* Find out if the current position of the cursor is still in the
* visible area. If it is not, the scroll position is updated.
* Needs to be called every time the cursor is move, wrap, font or
* window size are changed.
*/
static void _CalcScrollPos(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
int xCursor, yCursor;
_GetCursorXY(hObj, pObj, &xCursor, &yCursor);
yCursor /= GUI_GetYDistOfFont(pObj->pFont);
WM_CheckScrollPos(&pObj->ScrollStateV, yCursor, 0, 0); /* Vertical */
WM_CheckScrollPos(&pObj->ScrollStateH, xCursor, 30, 30); /* Horizontal */
_SetScrollState(hObj);
}
/*********************************************************************
*
* _GetTextSizeX
*
* Returns the width of the displayed text.
*/
static int _GetTextSizeX(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
if (pObj->InvalidFlags & INVALID_TEXTSIZE) {
pObj->TextSizeX = 0;
if (pObj->hText) {
int NumChars, xSizeLine;
char *pText, *pLine;
GUI_SetFont(pObj->pFont);
pText = (char*) GUI_ALLOC_h2p(pObj->hText);
do {
NumChars = _WrapGetNumCharsDisp(hObj, pObj, pText);
xSizeLine = 0;
pLine = pText;
while (NumChars--) {
xSizeLine += _GetCharDistX(pObj, pLine);
pLine += GUI_UC_GetCharSize(pLine);
}
if (xSizeLine > pObj->TextSizeX) {
pObj->TextSizeX = xSizeLine;
}
pText += _WrapGetNumBytesToNextLine(hObj, pObj, pText);
} while (*pText);
}
pObj->InvalidFlags &= ~INVALID_TEXTSIZE;
}
return pObj->TextSizeX;
}
/*********************************************************************
*
* _GetNumVisLines
*/
static int _GetNumVisLines(MULTIEDIT_HANDLE hObj, const MULTIEDIT_OBJ* pObj) {
GUI_RECT Rect;
WM_GetInsideRectExScrollbar(hObj, &Rect);
return (Rect.y1 - Rect.y0 + 1) / GUI_GetYDistOfFont(pObj->pFont);
}
/*********************************************************************
*
* _GetNumLines
*
* Calculates (if needed) and returns the number of lines
*/
static int _GetNumLines(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ * pObj) {
if (pObj->InvalidFlags & INVALID_NUMLINES) {
int NumLines = 0;
if (pObj->hText) {
int NumChars, NumBytes;
char *pText;
U16 Char;
pText = (char*) GUI_ALLOC_h2p(pObj->hText);
GUI_SetFont(pObj->pFont);
do {
NumChars = _WrapGetNumCharsDisp(hObj, pObj, pText);
NumBytes = GUI_UC__NumChars2NumBytes(pText, NumChars);
Char = GUI_UC_GetCharCode(pText + NumBytes);
if (Char) {
NumLines++;
}
pText += _WrapGetNumBytesToNextLine(hObj, pObj, pText);
} while (Char);
}
pObj->NumLines = NumLines + 1;
pObj->InvalidFlags &= ~INVALID_NUMLINES;
}
return pObj->NumLines;
}
/*********************************************************************
*
* _InvalidateNumLines
*
* Invalidates the number of lines
*/
static void _InvalidateNumLines(MULTIEDIT_OBJ * pObj) {
pObj->InvalidFlags |= INVALID_NUMLINES;
}
/*********************************************************************
*
* _InvalidateTextSizeX
*
* Calculates the TextSizeX
*/
static void _InvalidateTextSizeX(MULTIEDIT_OBJ * pObj) {
pObj->InvalidFlags |= INVALID_TEXTSIZE;
}
/*********************************************************************
*
* _CalcScrollParas
*
* Purpose:
* Calculate page size ,number of items & position
*/
static void _CalcScrollParas(MULTIEDIT_HANDLE hObj) {
MULTIEDIT_OBJ* pObj = MULTIEDIT_H2P(hObj);
/* Calc vertical scroll parameters */
pObj->ScrollStateV.NumItems = _GetNumLines(hObj, pObj);
pObj->ScrollStateV.PageSize = _GetNumVisLines(hObj, pObj);
/* Calc horizontal scroll parameters */
pObj->ScrollStateH.NumItems = _GetTextSizeX(hObj, pObj);
pObj->ScrollStateH.PageSize = _GetXSize(hObj, pObj);
_CalcScrollPos(hObj, pObj);
}
/*********************************************************************
*
* _ManageAutoScrollV
*/
static void _ManageAutoScrollV(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
if (pObj->Flags & MULTIEDIT_SF_AUTOSCROLLBAR_V) {
char IsRequired = _GetNumVisLines(hObj, pObj) < _GetNumLines(hObj, pObj);
if (WM_SetScrollbarV(hObj, IsRequired) != IsRequired) {
_InvalidateNumLines(pObj);
_InvalidateTextSizeX(pObj);
_InvalidateCursorXY(pObj);
_ClearCache(pObj);
}
}
}
/*********************************************************************
*
* _ManageScrollers
*
* Function:
* If autoscroll mode is enabled, add or remove the horizonatal and
* vertical scrollbars as required.
* Caution: This routine should not be called as reaction to a message
* From the child, as this could lead to a recursion problem
*/
static void _ManageScrollers(MULTIEDIT_HANDLE hObj) {
MULTIEDIT_OBJ* pObj;
pObj = MULTIEDIT_H2P(hObj);
/* 1. Step: Check if vertical scrollbar is required */
_ManageAutoScrollV(hObj, pObj);
/* 2. Step: Check if horizontal scrollbar is required */
if (pObj->Flags & MULTIEDIT_SF_AUTOSCROLLBAR_H) {
char IsRequired;
IsRequired = (_GetXSize(hObj, pObj) < _GetTextSizeX(hObj, pObj));
if (WM_SetScrollbarH(hObj, IsRequired) != IsRequired) {
/* 3. Step: Check vertical scrollbar again if horizontal has changed */
_ManageAutoScrollV(hObj, pObj);
}
}
_CalcScrollParas(hObj);
}
/*********************************************************************
*
* _Invalidate
*/
static void _Invalidate(MULTIEDIT_HANDLE hObj) {
_ManageScrollers(hObj);
WM_Invalidate(hObj);
}
/*********************************************************************
*
* _InvalidateTextArea
*
* Invalidates the text area only
*/
static void _InvalidateTextArea(MULTIEDIT_HANDLE hObj) {
GUI_RECT rInsideRect;
_ManageScrollers(hObj);
WM_GetInsideRectExScrollbar(hObj, &rInsideRect);
WM_InvalidateRect(hObj, &rInsideRect);
}
/*********************************************************************
*
* _InvalidateCursorPos
*
* Sets the position of the cursor to an invalid value
*/
static int _InvalidateCursorPos(MULTIEDIT_OBJ * pObj) {
int Value;
Value = pObj->CursorPosChar;
pObj->CursorPosChar = 0xffff;
return Value;
}
/*********************************************************************
*
* _SetFlag
*/
static void _SetFlag(MULTIEDIT_HANDLE hObj, int OnOff, U8 Flag) {
if (hObj) {
MULTIEDIT_OBJ * pObj;
WM_LOCK();
pObj = MULTIEDIT_H2P(hObj);
if (OnOff) {
pObj->Flags |= Flag;
} else {
pObj->Flags &= ~Flag;
}
_InvalidateTextArea(hObj);
WM_UNLOCK();
}
}
/*********************************************************************
*
* _CalcNextValidCursorPos
*
* Purpose:
* Calculates the next valid cursor position of the desired position.
*
* Parameters:
* hObj, pObj : Obvious
* CursorPosChar : New character position of the cursor
* pCursorPosByte: Pointer to save the cursorposition in bytes. Used to abolish further calculations. Could be 0.
* pCursorLine : Pointer to save the line number of the cursor. Used to abolish further calculations. Could be 0.
*/
static int _CalcNextValidCursorPos(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj, int CursorPosChar, int * pCursorPosByte, int * pCursorLine) {
if (pObj->hText) {
char *pNextLine, *pCursor, *pText;
int CursorLine, NumChars, CursorPosByte;
pText = (char*) GUI_ALLOC_h2p(pObj->hText);
NumChars = _GetNumChars(pObj);
/* Set offset in valid range */
if (CursorPosChar < pObj->NumCharsPrompt) {
CursorPosChar = pObj->NumCharsPrompt;
}
if (CursorPosChar > NumChars) {
CursorPosChar = NumChars;
}
CursorPosByte = GUI_UC__NumChars2NumBytes(pText, CursorPosChar);
CursorLine = _GetCursorLine(hObj, pObj, pText, CursorPosChar);
pCursor = pText + CursorPosByte;
pNextLine = _GetpLine(hObj, pObj, CursorLine);
if (pNextLine > pCursor) {
if (pObj->CursorPosChar < CursorPosChar) {
pCursor = pNextLine;
} else {
char *pPrevLine;
int NumChars;
pPrevLine = _GetpLine(hObj, pObj, CursorLine - 1);
NumChars = _WrapGetNumCharsDisp(hObj, pObj, pPrevLine);
pPrevLine += GUI_UC__NumChars2NumBytes(pPrevLine, NumChars);
pCursor = pPrevLine;
}
CursorPosChar = GUI_UC__NumBytes2NumChars(pText, pCursor - pText);
CursorPosByte = GUI_UC__NumChars2NumBytes(pText, CursorPosChar);
CursorLine = _GetCursorLine(hObj, pObj, pText, CursorPosChar);
}
if (pCursorPosByte) {
*pCursorPosByte = CursorPosByte;
}
if (pCursorLine) {
*pCursorLine = CursorLine;
}
return CursorPosChar;
}
return 0;
}
/*********************************************************************
*
* _SetCursorPos
*
* Sets a new cursor position.
*/
static void _SetCursorPos(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj, int CursorPosChar) {
int CursorPosByte, CursorLine;
CursorPosChar = _CalcNextValidCursorPos(hObj, pObj, CursorPosChar, &CursorPosByte, &CursorLine);
/* Assign value and recalc whatever necessary */
if (pObj->CursorPosChar != CursorPosChar) {
/* Save values */
pObj->CursorPosByte = CursorPosByte;
pObj->CursorPosChar = CursorPosChar;
pObj->CursorLine = CursorLine;
_InvalidateCursorXY(pObj); /* Invalidate X/Y position */
_CalcScrollPos(hObj, pObj);
}
}
/*********************************************************************
*
* _SetWrapMode
*/
static int _SetWrapMode(MULTIEDIT_HANDLE hObj, GUI_WRAPMODE WrapMode) {
int r;
r = 0;
if (hObj) {
MULTIEDIT_OBJ * pObj;
WM_LOCK();
pObj = MULTIEDIT_H2P(hObj);
r = pObj->WrapMode;
if (pObj->WrapMode != WrapMode) {
int Position;
pObj->WrapMode = WrapMode;
_ClearCache(pObj);
_InvalidateNumLines(pObj);
_InvalidateTextSizeX(pObj);
_InvalidateTextArea(hObj);
Position = _InvalidateCursorPos(pObj);
_SetCursorPos(hObj, pObj, Position);
}
WM_UNLOCK();
}
return r;
}
/*********************************************************************
*
* _SetCursorXY
*
* Sets the cursor position from window coordinates.
*/
static void _SetCursorXY(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj, int x, int y) {
int CursorPosChar = 0;
if ((x < 0) || (y < 0)) {
return;
}
if (pObj->hText) {
char *pLine, *pText;
int CursorLine, WrapChars;
int SizeX = 0;
U16 Char;
GUI_SetFont(pObj->pFont);
CursorLine = y / GUI_GetFontDistY();
pLine = _GetpLine(hObj, pObj, CursorLine);
pText = (char*) GUI_ALLOC_h2p(pObj->hText);
WrapChars = _WrapGetNumCharsDisp(hObj, pObj, pLine);
Char = GUI_UC__GetCharCode(pLine + GUI_UC__NumChars2NumBytes(pLine, WrapChars));
if (pObj->Flags & MULTIEDIT_SF_PASSWORD) {
if (!Char) {
WrapChars++;
}
} else {
if (!Char || (Char == '\n') || ((Char == ' ') && (pObj->WrapMode == GUI_WRAPMODE_WORD))) {
WrapChars++;
}
}
while (--WrapChars > 0) {
Char = GUI_UC_GetCharCode(pLine);
SizeX += _GetCharDistX(pObj, pLine);
if (!Char || (SizeX > x)) {
break;
}
pLine += GUI_UC_GetCharSize(pLine);
}
CursorPosChar = GUI_UC__NumBytes2NumChars(pText, pLine - pText);
}
_SetCursorPos(hObj, pObj, CursorPosChar);
}
/*********************************************************************
*
* _MoveCursorUp
*/
static void _MoveCursorUp(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
int xPos, yPos;
_GetCursorXY(hObj, pObj, &xPos, &yPos);
yPos -= GUI_GetYDistOfFont(pObj->pFont);
_SetCursorXY(hObj, pObj, xPos, yPos);
}
/*********************************************************************
*
* _MoveCursorDown
*/
static void _MoveCursorDown(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
int xPos, yPos;
_GetCursorXY(hObj, pObj, &xPos, &yPos);
yPos += GUI_GetYDistOfFont(pObj->pFont);
_SetCursorXY(hObj, pObj, xPos, yPos);
}
/*********************************************************************
*
* _MoveCursor2NextLine
*/
static void _MoveCursor2NextLine(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
int xPos, yPos;
_GetCursorXY(hObj, pObj, &xPos, &yPos);
yPos += GUI_GetYDistOfFont(pObj->pFont);
_SetCursorXY(hObj, pObj, 0, yPos);
}
/*********************************************************************
*
* _MoveCursor2LineEnd
*/
static void _MoveCursor2LineEnd(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
int xPos, yPos;
_GetCursorXY(hObj, pObj, &xPos, &yPos);
_SetCursorXY(hObj, pObj, 0x7FFF, yPos);
}
/*********************************************************************
*
* _MoveCursor2LinePos1
*/
static void _MoveCursor2LinePos1(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
int xPos, yPos;
_GetCursorXY(hObj, pObj, &xPos, &yPos);
_SetCursorXY(hObj, pObj, 0, yPos);
}
/*********************************************************************
*
* _IsOverwriteAtThisChar
*/
static int _IsOverwriteAtThisChar(MULTIEDIT_HANDLE hObj, MULTIEDIT_OBJ* pObj) {
int r = 0;
if (pObj->hText && !(pObj->Flags & MULTIEDIT_CF_INSERT)) {
const char *pText;
int CurPos, Line1, Line2;
U16 Char;
pText = (const char *)GUI_ALLOC_h2p(pObj->hText);
Line1 = pObj->CursorLine;
CurPos = _CalcNextValidCursorPos(hObj, pObj, pObj->CursorPosChar + 1, 0, 0);
Line2 = _GetCursorLine(hObj, pObj, pText, CurPos);
pText += pObj->CursorPosByte;
Char = GUI_UC_GetCharCode(pText);
if (Char) {
if ((Line1 == Line2) || (pObj->Flags & MULTIEDIT_SF_PASSWORD)) {
r = 1;
} else {
if (Char != '\n') {
if ((Char != ' ') || (pObj->WrapMode == GUI_WRAPMODE_CHAR)) {
r = 1;
}
}
}
}
}
return r;
}
/*********************************************************************
*
* _GetCursorSizeX
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -