📄 wrap.c
字号:
/* wc->pt.x += run->nWidth; */
/* skip runs consisting of only whitespaces */
return p->next;
}
if (run->nFlags & MERF_STARTWHITE) {
/* try to split the run at the first non-white char */
int black;
black = ME_FindNonWhitespaceV(run->strText, 0);
if (black) {
wc->bOverflown = FALSE;
pp = ME_SplitRun(wc->context, p, black);
p->member.run.nFlags |= MERF_SKIPPED;
ME_InsertRowStart(wc, pp);
return pp;
}
}
/* black run: the row goes from pRowStart to the previous run */
ME_InsertRowStart(wc, p);
return p;
}
/* we're not at the end of the row */
/* will current run fit? */
if (wc->pt.x + run->nWidth > wc->nAvailWidth)
{
int loc = wc->nAvailWidth - wc->pt.x;
/* total white run ? */
if (run->nFlags & MERF_WHITESPACE) {
/* let the overflow logic handle it */
wc->bOverflown = TRUE;
return p;
}
/* graphics or TAB - we can split before */
if (run->nFlags & (MERF_GRAPHICS|MERF_TAB)) {
wc->bOverflown = TRUE;
return p;
}
/* can we separate out the last spaces ? (to use overflow logic later) */
if (run->nFlags & MERF_ENDWHITE)
{
/* we aren't sure if it's *really* necessary, it's a good start however */
int black = ME_ReverseFindNonWhitespaceV(run->strText, len);
ME_SplitRun(wc->context, p, black);
/* handle both parts again */
return p;
}
/* determine the split point by backtracking */
pp = ME_SplitByBacktracking(wc, p, loc);
if (pp == wc->pRowStart)
{
/* we had only spaces so far, entire content can be omitted */
wc->pt.x = 0;
return p->next;
}
if (p != pp) /* found a suitable split point */
{
wc->bOverflown = TRUE;
return pp;
}
/* we detected that it's best to split on start of this run */
if (wc->bOverflown)
return pp;
ERR("failure!\n");
/* not found anything - writing over margins is the only option left */
}
if ((run->nFlags & (MERF_SPLITTABLE | MERF_STARTWHITE))
|| ((run->nFlags & (MERF_GRAPHICS|MERF_TAB)) && (p != wc->pRowStart)))
{
wc->pLastSplittableRun = p;
wc->ptLastSplittableRun = wc->pt;
}
wc->pt.x += run->nWidth;
return p->next;
}
void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
ME_DisplayItem *p;
ME_WrapContext wc;
int dpi = GetDeviceCaps(c->hDC, LOGPIXELSX);
assert(tp->type == diParagraph);
if (!(tp->member.para.nFlags & MEPF_REWRAP)) {
return;
}
ME_PrepareParagraphForWrapping(c, tp);
wc.context = c;
/* wc.para_style = tp->member.para.style; */
wc.style = NULL;
tp->member.para.nRightMargin = tp->member.para.pFmt->dxRightIndent*dpi/1440;
tp->member.para.nFirstMargin = tp->member.para.pFmt->dxStartIndent*dpi/1440;
tp->member.para.nLeftMargin = (tp->member.para.pFmt->dxStartIndent+tp->member.para.pFmt->dxOffset)*dpi/1440;
wc.nFirstMargin = tp->member.para.nFirstMargin;
wc.nLeftMargin = tp->member.para.nLeftMargin;
wc.nRightMargin = tp->member.para.nRightMargin;
wc.nRow = 0;
wc.pt.x = 0;
wc.pt.y = 0;
wc.nTotalWidth = c->rcView.right - c->rcView.left;
wc.nAvailWidth = wc.nTotalWidth - wc.nFirstMargin - wc.nRightMargin;
wc.pRowStart = NULL;
ME_BeginRow(&wc);
for (p = tp->next; p!=tp->member.para.next_para; ) {
assert(p->type != diStartRow);
if (p->type == diRun) {
p = ME_WrapHandleRun(&wc, p);
continue;
}
p = p->next;
}
ME_WrapEndParagraph(&wc, p);
tp->member.para.nFlags &= ~MEPF_REWRAP;
tp->member.para.nHeight = wc.pt.y;
tp->member.para.nRows = wc.nRow;
}
void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) {
ME_DisplayItem *p, *pRow;
/* remove all items that will be reinserted by paragraph wrapper anyway */
tp->member.para.nRows = 0;
for (p = tp->next; p!=tp->member.para.next_para; p = p->next) {
switch(p->type) {
case diStartRow:
pRow = p;
p = p->prev;
ME_Remove(pRow);
ME_DestroyDisplayItem(pRow);
break;
default:
break;
}
}
/* join runs that can be joined, set up flags */
for (p = tp->next; p!=tp->member.para.next_para; p = p->next) {
int changed = 0;
switch(p->type) {
case diStartRow: assert(0); break; /* should have deleted it */
case diRun:
while (p->next->type == diRun) { /* FIXME */
if (ME_CanJoinRuns(&p->member.run, &p->next->member.run)) {
ME_JoinRuns(c->editor, p);
changed = 1;
}
else
break;
}
p->member.run.nFlags &= ~MERF_CALCBYWRAP;
break;
default:
break;
}
}
}
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
HWND hWnd = editor->hWnd;
HDC hDC = GetDC(hWnd);
ME_DisplayItem *item;
ME_Context c;
BOOL bModified = FALSE;
int yStart = -1, yEnd = -1;
ME_InitContext(&c, editor, hDC);
c.pt.x = 0;
c.pt.y = 0;
item = editor->pBuffer->pFirst->next;
while(item != editor->pBuffer->pLast) {
BOOL bRedraw = FALSE;
assert(item->type == diParagraph);
if ((item->member.para.nFlags & MEPF_REWRAP)
|| (item->member.para.nYPos != c.pt.y))
bRedraw = TRUE;
item->member.para.nYPos = c.pt.y;
ME_WrapTextParagraph(&c, item);
if (bRedraw)
{
item->member.para.nFlags |= MEPF_REPAINT;
if (yStart == -1)
yStart = c.pt.y;
}
bModified = bModified | bRedraw;
c.pt.y += item->member.para.nHeight;
if (bRedraw)
yEnd = c.pt.y;
item = item->member.para.next_para;
}
editor->sizeWindow.cx = c.rcView.right-c.rcView.left;
editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top;
editor->nTotalLength = c.pt.y;
ME_DestroyContext(&c);
ReleaseDC(hWnd, hDC);
if (bModified || editor->nTotalLength < editor->nLastTotalLength)
ME_InvalidateMarkedParagraphs(editor);
return bModified;
}
void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor) {
ME_Context c;
HDC hDC = GetDC(editor->hWnd);
ME_InitContext(&c, editor, hDC);
if (editor->bRedraw)
{
RECT rc = c.rcView;
int ofs = ME_GetYScrollPos(editor);
ME_DisplayItem *item = editor->pBuffer->pFirst;
while(item != editor->pBuffer->pLast) {
if (item->member.para.nFlags & MEPF_REPAINT) {
rc.top = item->member.para.nYPos - ofs;
rc.bottom = item->member.para.nYPos + item->member.para.nHeight - ofs;
InvalidateRect(editor->hWnd, &rc, TRUE);
}
item = item->member.para.next_para;
}
if (editor->nTotalLength < editor->nLastTotalLength)
{
rc.top = editor->nTotalLength - ofs;
rc.bottom = editor->nLastTotalLength - ofs;
InvalidateRect(editor->hWnd, &rc, TRUE);
}
}
ME_DestroyContext(&c);
ReleaseDC(editor->hWnd, hDC);
}
void
ME_SendRequestResize(ME_TextEditor *editor, BOOL force)
{
if (editor->nEventMask & ENM_REQUESTRESIZE)
{
RECT rc;
GetClientRect(editor->hWnd, &rc);
if (force || rc.bottom != editor->nTotalLength)
{
REQRESIZE info;
info.nmhdr.hwndFrom = editor->hWnd;
info.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID);
info.nmhdr.code = EN_REQUESTRESIZE;
info.rc = rc;
info.rc.bottom = editor->nTotalLength;
SendMessageW(GetParent(editor->hWnd), WM_NOTIFY,
info.nmhdr.idFrom, (LPARAM)&info);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -