📄 multiedit.c
字号:
}
/*********************************************************************
*
* _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
*
* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -