📄 editor.c
字号:
"EM_GETOLEINTERFACE",
"EM_GETPARAFORMAT",
"EM_GETSELTEXT",
"EM_HIDESELECTION",
"EM_PASTESPECIAL",
"EM_REQUESTRESIZE",
"EM_SELECTIONTYPE",
"EM_SETBKGNDCOLOR",
"EM_SETCHARFORMAT",
"EM_SETEVENTMASK",
"EM_SETOLECALLBACK",
"EM_SETPARAFORMAT",
"EM_SETTARGETDEVICE",
"EM_STREAMIN",
"EM_STREAMOUT",
"EM_GETTEXTRANGE",
"EM_FINDWORDBREAK",
"EM_SETOPTIONS",
"EM_GETOPTIONS",
"EM_FINDTEXTEX",
"EM_GETWORDBREAKPROCEX",
"EM_SETWORDBREAKPROCEX",
"EM_SETUNDOLIMIT",
"EM_UNKNOWN_USER_83",
"EM_REDO",
"EM_CANREDO",
"EM_GETUNDONAME",
"EM_GETREDONAME",
"EM_STOPGROUPTYPING",
"EM_SETTEXTMODE",
"EM_GETTEXTMODE",
"EM_AUTOURLDETECT",
"EM_GETAUTOURLDETECT",
"EM_SETPALETTE",
"EM_GETTEXTEX",
"EM_GETTEXTLENGTHEX",
"EM_SHOWSCROLLBAR",
"EM_SETTEXTEX",
"EM_UNKNOWN_USER_98",
"EM_UNKNOWN_USER_99",
"EM_SETPUNCTUATION",
"EM_GETPUNCTUATION",
"EM_SETWORDWRAPMODE",
"EM_GETWORDWRAPMODE",
"EM_SETIMECOLOR",
"EM_GETIMECOLOR",
"EM_SETIMEOPTIONS",
"EM_GETIMEOPTIONS",
"EM_CONVPOSITION",
"EM_UNKNOWN_USER_109",
"EM_UNKNOWN_USER_110",
"EM_UNKNOWN_USER_111",
"EM_UNKNOWN_USER_112",
"EM_UNKNOWN_USER_113",
"EM_UNKNOWN_USER_114",
"EM_UNKNOWN_USER_115",
"EM_UNKNOWN_USER_116",
"EM_UNKNOWN_USER_117",
"EM_UNKNOWN_USER_118",
"EM_UNKNOWN_USER_119",
"EM_SETLANGOPTIONS",
"EM_GETLANGOPTIONS",
"EM_GETIMECOMPMODE",
"EM_FINDTEXTW",
"EM_FINDTEXTEXW",
"EM_RECONVERSION",
"EM_SETIMEMODEBIAS",
"EM_GETIMEMODEBIAS"
};
static const char *
get_msg_name(UINT msg)
{
if (msg >= EM_GETSEL && msg <= EM_CHARFROMPOS)
return edit_messages[msg - EM_GETSEL];
if (msg >= EM_CANPASTE && msg <= EM_GETIMEMODEBIAS)
return richedit_messages[msg - EM_CANPASTE];
return "";
}
static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam, BOOL unicode)
{
ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongPtrW(hWnd, 0);
TRACE("hwnd %p msg %04x (%s) %lx %lx, unicode %d\n",
hWnd, msg, get_msg_name(msg), wParam, lParam, unicode);
if (!editor && msg != WM_NCCREATE && msg != WM_NCDESTROY) {
ERR("called with invalid hWnd %p - application bug?\n", hWnd);
return 0;
}
switch(msg) {
UNSUPPORTED_MSG(EM_DISPLAYBAND)
UNSUPPORTED_MSG(EM_FINDWORDBREAK)
UNSUPPORTED_MSG(EM_FMTLINES)
UNSUPPORTED_MSG(EM_FORMATRANGE)
UNSUPPORTED_MSG(EM_GETBIDIOPTIONS)
UNSUPPORTED_MSG(EM_GETEDITSTYLE)
UNSUPPORTED_MSG(EM_GETIMECOMPMODE)
/* UNSUPPORTED_MSG(EM_GETIMESTATUS) missing in Wine headers */
UNSUPPORTED_MSG(EM_GETLANGOPTIONS)
/* UNSUPPORTED_MSG(EM_GETOLEINTERFACE) separate stub */
UNSUPPORTED_MSG(EM_GETREDONAME)
UNSUPPORTED_MSG(EM_GETTEXTMODE)
UNSUPPORTED_MSG(EM_GETTYPOGRAPHYOPTIONS)
UNSUPPORTED_MSG(EM_GETUNDONAME)
UNSUPPORTED_MSG(EM_GETWORDBREAKPROCEX)
UNSUPPORTED_MSG(EM_PASTESPECIAL)
UNSUPPORTED_MSG(EM_SELECTIONTYPE)
UNSUPPORTED_MSG(EM_SETBIDIOPTIONS)
UNSUPPORTED_MSG(EM_SETEDITSTYLE)
UNSUPPORTED_MSG(EM_SETFONTSIZE)
UNSUPPORTED_MSG(EM_SETLANGOPTIONS)
UNSUPPORTED_MSG(EM_SETPALETTE)
UNSUPPORTED_MSG(EM_SETTABSTOPS)
UNSUPPORTED_MSG(EM_SETTARGETDEVICE)
UNSUPPORTED_MSG(EM_SETTYPOGRAPHYOPTIONS)
UNSUPPORTED_MSG(EM_SETWORDBREAKPROCEX)
UNSUPPORTED_MSG(WM_STYLECHANGING)
UNSUPPORTED_MSG(WM_STYLECHANGED)
/* UNSUPPORTED_MSG(WM_UNICHAR) FIXME missing in Wine headers */
/* Messages specific to Richedit controls */
case EM_STREAMIN:
return ME_StreamIn(editor, wParam, (EDITSTREAM*)lParam);
case EM_STREAMOUT:
return ME_StreamOut(editor, wParam, (EDITSTREAM *)lParam);
case WM_GETDLGCODE:
{
UINT code = DLGC_WANTCHARS|DLGC_WANTARROWS;
if(lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
{
int vk = (int)((LPMSG)lParam)->wParam;
/* if style says we want return key */
if((vk == VK_RETURN) && (GetWindowLongW(hWnd, GWL_STYLE) & ES_WANTRETURN))
{
code |= DLGC_WANTMESSAGE;
}
/* we always handle ctrl-tab */
if((vk == VK_TAB) && (GetKeyState(VK_CONTROL) & 0x8000))
{
code |= DLGC_WANTMESSAGE;
}
}
return code;
}
case WM_NCCREATE:
{
CREATESTRUCTW *pcs = (CREATESTRUCTW *)lParam;
TRACE("WM_NCCREATE: style 0x%08x\n", pcs->style);
editor = ME_MakeEditor(hWnd);
SetWindowLongPtrW(hWnd, 0, (LONG_PTR)editor);
return TRUE;
}
case EM_EMPTYUNDOBUFFER:
ME_EmptyUndoStack(editor);
return 0;
case EM_GETSEL:
{
/* Note: wParam/lParam can be NULL */
UINT from, to;
PUINT pfrom = wParam ? (PUINT)wParam : &from;
PUINT pto = lParam ? (PUINT)lParam : &to;
ME_GetSelection(editor, (int *)pfrom, (int *)pto);
if ((*pfrom|*pto) & 0xFFFF0000)
return -1;
return MAKELONG(*pfrom,*pto);
}
case EM_EXGETSEL:
{
CHARRANGE *pRange = (CHARRANGE *)lParam;
ME_GetSelection(editor, (int *)&pRange->cpMin, (int *)&pRange->cpMax);
TRACE("EM_EXGETSEL = (%d,%d)\n", pRange->cpMin, pRange->cpMax);
return 0;
}
case EM_SETUNDOLIMIT:
{
if ((int)wParam < 0)
editor->nUndoLimit = STACK_SIZE_DEFAULT;
else
editor->nUndoLimit = min(wParam, STACK_SIZE_MAX);
/* Setting a max stack size keeps wine from getting killed
for hogging memory. Windows allocates all this memory at once, so
no program would realistically set a value above our maximum. */
return editor->nUndoLimit;
}
case EM_CANUNDO:
return editor->pUndoStack != NULL;
case EM_CANREDO:
return editor->pRedoStack != NULL;
case WM_UNDO: /* FIXME: actually not the same */
case EM_UNDO:
ME_Undo(editor);
return 0;
case EM_REDO:
ME_Redo(editor);
return 0;
case EM_GETOPTIONS:
{
/* these flags are equivalent to the ES_* counterparts */
DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN;
DWORD settings = GetWindowLongW(hWnd, GWL_STYLE) & mask;
return settings;
}
case EM_SETOPTIONS:
{
/* these flags are equivalent to ES_* counterparts
* ECO_READONLY is already implemented in the code, only requires
* setting the bit to work
*/
DWORD mask = ECO_VERTICAL | ECO_AUTOHSCROLL | ECO_AUTOVSCROLL |
ECO_NOHIDESEL | ECO_READONLY | ECO_WANTRETURN;
DWORD raw = GetWindowLongW(hWnd, GWL_STYLE);
DWORD settings = mask & raw;
switch(wParam)
{
case ECOOP_SET:
settings = lParam;
break;
case ECOOP_OR:
settings |= lParam;
break;
case ECOOP_AND:
settings &= lParam;
break;
case ECOOP_XOR:
settings ^= lParam;
}
SetWindowLongW(hWnd, GWL_STYLE, (raw & ~mask) | (settings & mask));
if (lParam & ECO_AUTOWORDSELECTION)
FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n");
if (lParam & ECO_SELECTIONBAR)
FIXME("ECO_SELECTIONBAR not implemented yet!\n");
if (lParam & ECO_VERTICAL)
FIXME("ECO_VERTICAL not implemented yet!\n");
if (lParam & ECO_AUTOHSCROLL)
FIXME("ECO_AUTOHSCROLL not implemented yet!\n");
if (lParam & ECO_AUTOVSCROLL)
FIXME("ECO_AUTOVSCROLL not implemented yet!\n");
if (lParam & ECO_NOHIDESEL)
FIXME("ECO_NOHIDESEL not implemented yet!\n");
if (lParam & ECO_WANTRETURN)
FIXME("ECO_WANTRETURN not implemented yet!\n");
return settings;
}
case EM_SETSEL:
{
ME_InvalidateSelection(editor);
ME_SetSelection(editor, wParam, lParam);
ME_InvalidateSelection(editor);
ME_SendSelChange(editor);
return 0;
}
case EM_SETSCROLLPOS:
{
POINT *point = (POINT *)lParam;
ME_ScrollAbs(editor, point->y);
return 0;
}
case EM_AUTOURLDETECT:
{
if (wParam==1 || wParam ==0)
{
editor->AutoURLDetect_bEnable = (BOOL)wParam;
return 0;
}
return E_INVALIDARG;
}
case EM_GETAUTOURLDETECT:
{
return editor->AutoURLDetect_bEnable;
}
case EM_EXSETSEL:
{
int end;
CHARRANGE range = *(CHARRANGE *)lParam;
TRACE("EM_EXSETSEL (%d,%d)\n", range.cpMin, range.cpMax);
ME_InvalidateSelection(editor);
end = ME_SetSelection(editor, range.cpMin, range.cpMax);
ME_InvalidateSelection(editor);
ME_SendSelChange(editor);
return end;
}
case EM_SHOWSCROLLBAR:
{
ShowScrollBar(editor->hWnd, wParam, lParam);
return 0;
}
case EM_SETTEXTEX:
{
LPWSTR wszText;
SETTEXTEX *pStruct = (SETTEXTEX *)wParam;
size_t len;
int from, to;
ME_Style *style;
int oldModify = editor->nModifyStep;
if (!pStruct) return 0;
TRACE("EM_SETTEXTEX - %s, flags %d, cp %d\n",
pStruct->codepage == 1200 ? debugstr_w((LPCWSTR)lParam) : debugstr_a((LPCSTR)lParam),
pStruct->flags, pStruct->codepage);
/* FIXME: make use of pStruct->codepage in the to unicode translation */
wszText = lParam ? ME_ToUnicode(pStruct->codepage == 1200, (void *)lParam) : NULL;
len = wszText ? lstrlenW(wszText) : 0;
/* FIXME: this should support RTF strings too, according to MSDN */
if (pStruct->flags & ST_SELECTION) {
ME_GetSelection(editor, &from, &to);
style = ME_GetSelectionInsertStyle(editor);
ME_InternalDeleteText(editor, from, to - from);
ME_InsertTextFromCursor(editor, 0, wszText, len, style);
ME_ReleaseStyle(style);
}
else {
ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
ME_InsertTextFromCursor(editor, 0, wszText, len, editor->pBuffer->pDefaultStyle);
len = 1;
}
ME_CommitUndo(editor);
if (!(pStruct->flags & ST_KEEPUNDO))
{
editor->nModifyStep = oldModify;
ME_EmptyUndoStack(editor);
}
ME_UpdateRepaint(editor);
return len;
}
case EM_SETBKGNDCOLOR:
{
LRESULT lColor = ME_GetBackColor(editor);
if (editor->rgbBackColor != -1)
DeleteObject(editor->hbrBackground);
if (wParam)
{
editor->rgbBackColor = -1;
editor->hbrBackground = GetSysColorBrush(COLOR_WINDOW);
}
else
{
editor->rgbBackColor = lParam;
editor->hbrBackground = CreateSolidBrush(editor->rgbBackColor);
}
if (editor->bRedraw)
{
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
return lColor;
}
case EM_GETMODIFY:
return editor->nModifyStep == 0 ? 0 : 1;
case EM_SETMODIFY:
{
if (wParam)
editor->nModifyStep = 1;
else
editor->nModifyStep = 0;
return 0;
}
case EM_SETREADONLY:
{
long nStyle = GetWindowLongW(hWnd, GWL_STYLE);
if (wParam)
nStyle |= ES_READONLY;
else
nStyle &= ~ES_READONLY;
SetWindowLongW(hWnd, GWL_STYLE, nStyle);
return 0;
}
case EM_SETEVENTMASK:
{
DWORD nOldMask = editor->nEventMask;
editor->nEventMask = lParam;
return nOldMask;
}
case EM_GETEVENTMASK:
return editor->nEventMask;
case EM_SETCHARFORMAT:
{
CHARFORMAT2W buf, *p;
BOOL bRepaint = TRUE;
p = ME_ToCF2W(&buf, (CHARFORMAT2W *)lParam);
if (!wParam || (editor->mode & TM_PLAINTEXT))
ME_SetDefaultCharFormat(editor, p);
else if (wParam == (SCF_WORD | SCF_SELECTION))
FIXME("EM_SETCHARFORMAT: word selection not supported\n");
else if (wParam == SCF_ALL)
ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), p);
else {
int from, to;
ME_GetSelection(editor, &from, &to);
bRepaint = (from != to);
ME_SetSelectionCharFormat(editor, p);
}
editor->nModifyStep = 1;
ME_CommitUndo(editor);
if (bRepaint)
ME_RewrapRepaint(editor);
return 0;
}
case EM_GETCHARFORMAT:
{
CHARFORMAT2W tmp, *dst = (CHARFORMAT2W *)lParam;
if (dst->cbSize != sizeof(CHARFORMATA) &&
dst->cbSize != sizeof(CHARFORMATW) &&
dst->cbSize != sizeof(CHARFORMAT2A) &&
dst->cbSize != sizeof(CHARFORMAT2W))
return 0;
tmp.cbSize = sizeof(tmp);
if (!wParam)
ME_GetDefaultCharFormat(editor, &tmp);
else
ME_GetSelectionCharFormat(editor, &tmp);
ME_CopyToCFAny(dst, &tmp);
return tmp.dwMask;
}
case EM_SETPARAFORMAT:
ME_SetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam);
ME_RewrapRepaint(editor);
ME_CommitUndo(editor);
return 0;
case EM_GETPARAFORMAT:
ME_GetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam);
return 0;
case EM_GETFIRSTVISIBLELINE:
{
ME_DisplayItem *p = editor->pBuffer->pFirst;
int y = ME_GetYScrollPos(editor);
int ypara = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -