📄 run.c
字号:
assert(!(item->member.run.nFlags & MERF_NONTEXT));
assert(item->member.run.nCharOfs != -1);
item2 = ME_MakeRun(run->style,
ME_VSplitString(run->strText, nVChar), run->nFlags&MERF_SPLITMASK);
item2->member.run.nCharOfs = item->member.run.nCharOfs+
ME_VPosToPos(item->member.run.strText, nVChar);
run2 = &item2->member.run;
ME_InsertBefore(item->next, item2);
ME_UpdateRunFlags(editor, run);
ME_UpdateRunFlags(editor, run2);
for (i=0; i<editor->nCursors; i++) {
if (editor->pCursors[i].pRun == item &&
editor->pCursors[i].nOffset >= nVChar) {
assert(item2->type == diRun);
editor->pCursors[i].pRun = item2;
editor->pCursors[i].nOffset -= nVChar;
}
}
ME_GetParagraph(item)->member.para.nFlags |= MEPF_REWRAP;
return item2;
}
/******************************************************************************
* ME_MakeRun
*
* A helper function to create run structures quickly.
*/
ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags)
{
ME_DisplayItem *item = ME_MakeDI(diRun);
item->member.run.style = s;
item->member.run.strText = strData;
item->member.run.nFlags = nFlags;
item->member.run.nCharOfs = -1;
ME_AddRefStyle(s);
return item;
}
/******************************************************************************
* ME_InsertRun
*
* Inserts a run at a given character position (offset).
*/
ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem *pItem)
{
ME_Cursor tmp;
ME_DisplayItem *pDI;
assert(pItem->type == diRun || pItem->type == diUndoInsertRun);
ME_CursorFromCharOfs(editor, nCharOfs, &tmp);
pDI = ME_InsertRunAtCursor(editor, &tmp, pItem->member.run.style,
pItem->member.run.strText->szData,
pItem->member.run.strText->nLen,
pItem->member.run.nFlags);
return pDI;
}
/******************************************************************************
* ME_InsertRunAtCursor
*
* Inserts a new run with given style, flags and content at a given position,
* which is passed as a cursor structure (which consists of a run and
* a run-relative character offset).
*/
ME_DisplayItem *
ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
const WCHAR *str, int len, int flags)
{
ME_DisplayItem *pDI;
ME_UndoItem *pUI;
if (cursor->nOffset) {
/* We're inserting at the middle of the existing run, which means that
* that run must be split. It isn't always necessary, but */
cursor->pRun = ME_SplitRunSimple(editor, cursor->pRun, cursor->nOffset);
cursor->nOffset = 0;
}
pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL);
if (pUI) {
pUI->nStart = (ME_GetParagraph(cursor->pRun)->member.para.nCharOfs
+ cursor->pRun->member.run.nCharOfs);
pUI->nLen = len;
}
pDI = ME_MakeRun(style, ME_MakeStringN(str, len), flags);
pDI->member.run.nCharOfs = cursor->pRun->member.run.nCharOfs;
ME_InsertBefore(cursor->pRun, pDI);
TRACE("Shift length:%d\n", len);
ME_PropagateCharOffset(cursor->pRun, len);
ME_GetParagraph(cursor->pRun)->member.para.nFlags |= MEPF_REWRAP;
return pDI;
}
/******************************************************************************
* ME_UpdateRunFlags
*
* Determine some of run attributes given its content (style, text content).
* Some flags cannot be determined by this function (MERF_GRAPHICS,
* MERF_ENDPARA)
*/
void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run)
{
assert(run->nCharOfs != -1);
if (RUN_IS_HIDDEN(run))
run->nFlags |= MERF_HIDDEN;
else
run->nFlags &= ~MERF_HIDDEN;
if (ME_IsSplitable(run->strText))
run->nFlags |= MERF_SPLITTABLE;
else
run->nFlags &= ~MERF_SPLITTABLE;
if (!(run->nFlags & MERF_NOTEXT)) {
if (ME_IsWhitespaces(run->strText))
run->nFlags |= MERF_WHITESPACE | MERF_STARTWHITE | MERF_ENDWHITE;
else
{
run->nFlags &= ~MERF_WHITESPACE;
if (ME_IsWSpace(ME_GetCharFwd(run->strText,0)))
run->nFlags |= MERF_STARTWHITE;
else
run->nFlags &= ~MERF_STARTWHITE;
if (ME_IsWSpace(ME_GetCharBack(run->strText,0)))
run->nFlags |= MERF_ENDWHITE;
else
run->nFlags &= ~MERF_ENDWHITE;
}
}
else
run->nFlags &= ~(MERF_WHITESPACE | MERF_STARTWHITE | MERF_ENDWHITE);
}
/******************************************************************************
* ME_GetGraphicsSize
*
* Sets run extent for graphics runs. This functionality is just a placeholder
* for future OLE object support, and will be removed.
*/
void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize)
{
assert(run->nFlags & MERF_GRAPHICS);
pSize->cx = 64;
pSize->cy = 64;
}
/******************************************************************************
* ME_CharFromPoint
*
* Returns a character position inside the run given a run-relative
* pixel horizontal position. This version rounds left (ie. if the second
* character is at pixel position 8, then for cx=0..7 it returns 0).
*/
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run)
{
int fit = 0;
HGDIOBJ hOldFont;
HDC hDC;
SIZE sz;
if (!run->strText->nLen)
return 0;
if (run->nFlags & (MERF_TAB | MERF_CELL))
{
if (cx < run->nWidth/2)
return 0;
return 1;
}
if (run->nFlags & MERF_GRAPHICS)
{
SIZE sz;
ME_GetGraphicsSize(editor, run, &sz);
if (cx < sz.cx)
return 0;
return 1;
}
hDC = GetDC(editor->hWnd);
hOldFont = ME_SelectStyleFont(editor, hDC, run->style);
if (editor->cPasswordMask)
{
ME_String *strMasked = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(run->strText));
GetTextExtentExPointW(hDC, strMasked->szData, run->strText->nLen,
cx, &fit, NULL, &sz);
ME_DestroyString(strMasked);
}
else
{
GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
cx, &fit, NULL, &sz);
}
ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
ReleaseDC(editor->hWnd, hDC);
return fit;
}
/******************************************************************************
* ME_CharFromPointCursor
*
* Returns a character position inside the run given a run-relative
* pixel horizontal position. This version rounds to the nearest character edge
* (ie. if the second character is at pixel position 8, then for cx=0..3
* it returns 0, and for cx=4..7 it returns 1).
*
* It is used for mouse click handling, for better usability (and compatibility
* with the native control).
*/
int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
{
ME_String *strRunText;
/* This could point to either the run's real text, or it's masked form in a password control */
int fit = 0, fit1 = 0;
HGDIOBJ hOldFont;
HDC hDC;
SIZE sz, sz2, sz3;
if (!run->strText->nLen)
return 0;
if (run->nFlags & (MERF_TAB | MERF_CELL))
{
if (cx < run->nWidth/2)
return 0;
return 1;
}
if (run->nFlags & MERF_GRAPHICS)
{
SIZE sz;
ME_GetGraphicsSize(editor, run, &sz);
if (cx < sz.cx/2)
return 0;
return 1;
}
if (editor->cPasswordMask)
strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(run->strText));
else
strRunText = run->strText;
hDC = GetDC(editor->hWnd);
hOldFont = ME_SelectStyleFont(editor, hDC, run->style);
GetTextExtentExPointW(hDC, strRunText->szData, strRunText->nLen,
cx, &fit, NULL, &sz);
if (fit != strRunText->nLen)
{
int chars = 1;
GetTextExtentPoint32W(hDC, strRunText->szData, fit, &sz2);
fit1 = ME_StrRelPos(strRunText, fit, &chars);
GetTextExtentPoint32W(hDC, strRunText->szData, fit1, &sz3);
if (cx >= (sz2.cx+sz3.cx)/2)
fit = fit1;
}
if (editor->cPasswordMask)
ME_DestroyString(strRunText);
ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
ReleaseDC(editor->hWnd, hDC);
return fit;
}
/******************************************************************************
* ME_PointFromChar
*
* Returns a run-relative pixel position given a run-relative character
* position (character offset)
*/
int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset)
{
SIZE size;
HDC hDC = GetDC(editor->hWnd);
HGDIOBJ hOldFont;
ME_String *strRunText;
/* This could point to either the run's real text, or it's masked form in a password control */
if (pRun->nFlags & MERF_GRAPHICS)
{
if (!nOffset) return 0;
ME_GetGraphicsSize(editor, pRun, &size);
return 1;
}
if (editor->cPasswordMask)
strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(pRun->strText));
else
strRunText = pRun->strText;
hOldFont = ME_SelectStyleFont(editor, hDC, pRun->style);
GetTextExtentPoint32W(hDC, strRunText->szData, nOffset, &size);
ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont);
ReleaseDC(editor->hWnd, hDC);
if (editor->cPasswordMask)
ME_DestroyString(strRunText);
return size.cx;
}
/******************************************************************************
* ME_GetTextExtent
*
* Finds a width and a height of the text using a specified style
*/
static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size)
{
HDC hDC = c->hDC;
HGDIOBJ hOldFont;
hOldFont = ME_SelectStyleFont(c->editor, hDC, s);
GetTextExtentPoint32W(hDC, szText, nChars, size);
ME_UnselectStyleFont(c->editor, hDC, s, hOldFont);
}
/******************************************************************************
* ME_GetRunSizeCommon
*
* Finds width, height, ascent and descent of a run, up to given character
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -