📄 caret.c
字号:
p = &editor->pCursors[nCursor];
tp = ME_FindItemBack(p->pRun, diParagraph);
para = &tp->member.para;
assert(tp);
if (p->nOffset) {
ME_SplitRunSimple(editor, p->pRun, p->nOffset);
p = &editor->pCursors[nCursor];
}
tmp_style = ME_GetInsertStyle(editor, nCursor);
/* ME_SplitParagraph increases style refcount */
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style);
p->pRun = ME_FindItemFwd(tp, diRun);
end_run = ME_FindItemBack(tp, diRun);
ME_ReleaseStyle(end_run->member.run.style);
end_run->member.run.style = tmp_style;
p->nOffset = 0;
if(pos-str < len && *pos =='\r')
pos++;
if(pos-str < len && *pos =='\n')
pos++;
if(pos-str <= len) {
len -= pos - str;
str = pos;
continue;
}
}
ME_InternalInsertTextFromCursor(editor, nCursor, str, len, style, 0);
len = 0;
}
}
static BOOL ME_ArrowLeft(ME_TextEditor *editor, ME_Cursor *p)
{
if (p->nOffset) {
p->nOffset = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, -1);
return TRUE;
}
else
{
ME_DisplayItem *pRun = ME_FindItemBack(p->pRun, diRunOrParagraph);
assert(pRun);
if (pRun->type == diRun) {
p->pRun = pRun;
assert(p->pRun->type == diRun);
assert(pRun->member.run.strText->nLen);
p->nOffset = pRun->member.run.strText->nLen;
if (p->nOffset) {
p->nOffset = ME_StrRelPos2(pRun->member.run.strText, p->nOffset, -1);
return TRUE;
}
else
assert(0);
}
if (pRun->type == diParagraph)
{
if (pRun->member.para.prev_para->type == diTextStart)
return FALSE;
assert(pRun->member.para.prev_para->type == diParagraph);
pRun = ME_FindItemBack(pRun, diRunOrParagraph);
/* every paragraph ought to have at least one run */
assert(pRun && pRun->type == diRun);
assert(pRun->member.run.nFlags & MERF_ENDPARA);
p->pRun = pRun;
p->nOffset = 0;
return TRUE;
}
assert(0);
}
return FALSE;
}
static BOOL ME_ArrowRight(ME_TextEditor *editor, ME_Cursor *p)
{
ME_DisplayItem *pRun;
if (!(p->pRun->member.run.nFlags & MERF_ENDPARA))
{
int new_ofs = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, 1);
if (new_ofs<p->pRun->member.run.strText->nLen)
{
p->nOffset = new_ofs;
return TRUE;
}
}
pRun = ME_FindItemFwd(p->pRun, diRun);
if (pRun) {
p->pRun = pRun;
assert(p->pRun->type == diRun);
p->nOffset = 0;
}
return TRUE;
}
int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor)
{
ME_Cursor *pCursor = &editor->pCursors[nCursor];
return ME_GetParagraph(pCursor->pRun)->member.para.nCharOfs
+ pCursor->pRun->member.run.nCharOfs + pCursor->nOffset;
}
int ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *result, BOOL *is_eol)
{
ME_DisplayItem *p = editor->pBuffer->pFirst->member.para.next_para;
int rx = 0;
if (is_eol)
*is_eol = 0;
while(p != editor->pBuffer->pLast)
{
if (p->type == diParagraph)
{
int ry = y - p->member.para.nYPos;
if (ry < 0)
{
result->pRun = ME_FindItemFwd(p, diRun);
result->nOffset = 0;
return 0;
}
if (ry >= p->member.para.nHeight)
{
p = p->member.para.next_para;
continue;
}
p = ME_FindItemFwd(p, diStartRow);
y = ry;
continue;
}
if (p->type == diStartRow)
{
int ry = y - p->member.row.nYPos;
if (ry < 0)
return 0;
if (ry >= p->member.row.nHeight)
{
p = ME_FindItemFwd(p, diStartRowOrParagraphOrEnd);
if (p->type != diStartRow)
return 0;
continue;
}
p = ME_FindItemFwd(p, diRun);
continue;
}
if (p->type == diRun)
{
ME_DisplayItem *pp;
rx = x - p->member.run.pt.x;
if (rx < 0)
rx = 0;
if (rx >= p->member.run.nWidth) /* not this run yet... find next item */
{
pp = p;
do {
p = p->next;
if (p->type == diRun)
{
rx = x - p->member.run.pt.x;
goto continue_search;
}
if (p->type == diStartRow)
{
p = ME_FindItemFwd(p, diRun);
if (is_eol)
*is_eol = 1;
rx = 0; /* FIXME not sure */
goto found_here;
}
if (p->type == diParagraph || p->type == diTextEnd)
{
rx = 0; /* FIXME not sure */
p = pp;
goto found_here;
}
} while(1);
continue;
}
found_here:
if (p->member.run.nFlags & MERF_ENDPARA)
rx = 0;
result->pRun = p;
result->nOffset = ME_CharFromPointCursor(editor, rx, &p->member.run);
if (editor->pCursors[0].nOffset == p->member.run.strText->nLen && rx)
{
result->pRun = ME_FindItemFwd(editor->pCursors[0].pRun, diRun);
result->nOffset = 0;
}
return 1;
}
assert(0);
continue_search:
;
}
result->pRun = ME_FindItemBack(p, diRun);
result->nOffset = 0;
assert(result->pRun->member.run.nFlags & MERF_ENDPARA);
return 0;
}
int
ME_CharFromPos(ME_TextEditor *editor, int x, int y)
{
ME_Cursor cursor;
RECT rc;
GetClientRect(editor->hWnd, &rc);
if (x < 0 || y < 0 || x >= rc.right || y >= rc.bottom)
return -1;
ME_FindPixelPos(editor, x, y, &cursor, NULL);
return (ME_GetParagraph(cursor.pRun)->member.para.nCharOfs
+ cursor.pRun->member.run.nCharOfs + cursor.nOffset);
}
void ME_LButtonDown(ME_TextEditor *editor, int x, int y)
{
ME_Cursor tmp_cursor;
int is_selection = 0;
editor->nUDArrowX = -1;
y += ME_GetYScrollPos(editor);
tmp_cursor = editor->pCursors[0];
is_selection = ME_IsSelection(editor);
ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd);
if (GetKeyState(VK_SHIFT)>=0)
{
editor->pCursors[1] = editor->pCursors[0];
}
else
{
if (!is_selection) {
editor->pCursors[1] = tmp_cursor;
is_selection = 1;
}
}
HideCaret(editor->hWnd);
ME_MoveCaret(editor);
if (is_selection)
ME_Repaint(editor);
ShowCaret(editor->hWnd);
ME_ClearTempStyle(editor);
ME_SendSelChange(editor);
}
void ME_MouseMove(ME_TextEditor *editor, int x, int y)
{
ME_Cursor tmp_cursor;
y += ME_GetYScrollPos(editor);
tmp_cursor = editor->pCursors[0];
if (!ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd))
/* return */;
if (tmp_cursor.pRun == editor->pCursors[0].pRun &&
tmp_cursor.nOffset == editor->pCursors[0].nOffset)
return;
HideCaret(editor->hWnd);
ME_MoveCaret(editor);
ME_Repaint(editor);
ShowCaret(editor->hWnd);
ME_SendSelChange(editor);
}
static ME_DisplayItem *ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow,
int x, int *pOffset, int *pbCaretAtEnd)
{
ME_DisplayItem *pNext, *pLastRun;
pNext = ME_FindItemFwd(pRow, diRunOrStartRow);
assert(pNext->type == diRun);
pLastRun = pNext;
*pbCaretAtEnd = FALSE;
do {
int run_x = pNext->member.run.pt.x;
int width = pNext->member.run.nWidth;
if (x < run_x)
{
if (pOffset) *pOffset = 0;
return pNext;
}
if (x >= run_x && x < run_x+width)
{
int ch = ME_CharFromPointCursor(editor, x-run_x, &pNext->member.run);
ME_String *s = pNext->member.run.strText;
if (ch < s->nLen) {
if (pOffset)
*pOffset = ch;
return pNext;
}
}
pLastRun = pNext;
pNext = ME_FindItemFwd(pNext, diRunOrStartRow);
} while(pNext && pNext->type == diRun);
if ((pLastRun->member.run.nFlags & MERF_ENDPARA) == 0)
{
pNext = ME_FindItemFwd(pNext, diRun);
if (pbCaretAtEnd) *pbCaretAtEnd = 1;
if (pOffset) *pOffset = 0;
return pNext;
} else {
if (pbCaretAtEnd) *pbCaretAtEnd = 0;
if (pOffset) *pOffset = 0;
return pLastRun;
}
}
static int ME_GetXForArrow(ME_TextEditor *editor, ME_Cursor *pCursor)
{
ME_DisplayItem *pRun = pCursor->pRun;
int x;
if (editor->nUDArrowX != -1)
x = editor->nUDArrowX;
else {
if (editor->bCaretAtEnd)
{
pRun = ME_FindItemBack(pRun, diRun);
assert(pRun);
x = pRun->member.run.pt.x + pRun->member.run.nWidth;
}
else {
x = pRun->member.run.pt.x;
x += ME_PointFromChar(editor, &pRun->member.run, pCursor->nOffset);
}
editor->nUDArrowX = x;
}
return x;
}
static void ME_ArrowUp(ME_TextEditor *editor, ME_Cursor *pCursor)
{
ME_DisplayItem *pRun = pCursor->pRun;
ME_DisplayItem *pItem, *pItem2;
int x = ME_GetXForArrow(editor, pCursor);
if (editor->bCaretAtEnd && !pCursor->nOffset)
{
pRun = ME_FindItemBack(pRun, diRun);
if (!pRun)
return;
}
/* start of this row */
pItem = ME_FindItemBack(pRun, diStartRow);
assert(pItem);
/* start of the previous row */
pItem2 = ME_FindItemBack(pItem, diStartRow);
/* no previous row = the first line of the first paragraph */
if (!pItem2) /* can't go up - don't go BOL (as in MS richedit) */
return;
/* FIXME
ME_WrapTextParagraph(editor, ME_FindItemBack(pItem2, diParagraph));
*/
pCursor->pRun = ME_FindRunInRow(editor, pItem2, x, &pCursor->nOffset, &editor->bCaretAtEnd);
}
static void ME_ArrowDown(ME_TextEditor *editor, ME_Cursor *pCursor)
{
ME_DisplayItem *pRun = pCursor->pRun;
ME_DisplayItem *pItem;
int x = ME_GetXForArrow(editor, pCursor);
if (!pCursor->nOffset && editor->bCaretAtEnd)
{
pRun = ME_FindItemBack(pRun, diRun);
/* x = pRun->member.run.pt.x + pRun->member.run.nWidth; */
}
/* start of the next row */
pItem = ME_FindItemFwd(pRun, diStartRow);
/* FIXME If diParagraph is before diStartRow, wrap the next paragraph?
*/
if (!pItem)
{
/* next row not found - ignore */
return;
}
pCursor->pRun = ME_FindRunInRow(editor, pItem, x, &pCursor->nOffset, &editor->bCaretAtEnd);
assert(pCursor->pRun);
assert(pCursor->pRun->type == diRun);
}
static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
{
ME_DisplayItem *pRun = pCursor->pRun;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -