📄 edit.c
字号:
UINT countA = 0;
#ifndef __REACTOS__
BOOL _16bit = FALSE;
#endif
if(es->hloc32W)
{
if(es->hloc32A)
{
TRACE("Synchronizing with 32-bit ANSI buffer\n");
textA = LocalLock(es->hloc32A);
countA = strlen(textA) + 1;
}
#ifndef __REACTOS__
else if(es->hloc16)
{
TRACE("Synchronizing with 16-bit ANSI buffer\n");
textA = LOCAL_Lock(hInstance, es->hloc16);
countA = strlen(textA) + 1;
_16bit = TRUE;
}
#endif
}
else {
ERR("no buffer ... please report\n");
return;
}
if(textA)
{
HLOCAL hloc32W_new;
UINT countW_new = MultiByteToWideChar(CP_ACP, 0, textA, countA, NULL, 0);
TRACE("%d bytes translated to %d WCHARs\n", countA, countW_new);
if(countW_new > es->buffer_size + 1)
{
UINT alloc_size = ROUND_TO_GROW(countW_new * sizeof(WCHAR));
TRACE("Resizing 32-bit UNICODE buffer from %d+1 to %d WCHARs\n", es->buffer_size, countW_new);
hloc32W_new = LocalReAlloc(es->hloc32W, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT);
if(hloc32W_new)
{
es->hloc32W = hloc32W_new;
es->buffer_size = LocalSize(hloc32W_new)/sizeof(WCHAR) - 1;
TRACE("Real new size %d+1 WCHARs\n", es->buffer_size);
}
else
WARN("FAILED! Will synchronize partially\n");
}
}
/*TRACE("Locking 32-bit UNICODE buffer\n");*/
es->text = LocalLock(es->hloc32W);
if(textA)
{
MultiByteToWideChar(CP_ACP, 0, textA, countA, es->text, es->buffer_size + 1);
#ifndef __REACTOS__
if(_16bit)
LOCAL_Unlock(hInstance, es->hloc16);
else
#endif
LocalUnlock(es->hloc32A);
}
}
es->lock_count++;
}
/*********************************************************************
*
* EDIT_SL_InvalidateText
*
* Called from EDIT_InvalidateText().
* Does the job for single-line controls only.
*
*/
static void EDIT_SL_InvalidateText(EDITSTATE *es, INT start, INT end)
{
RECT line_rect;
RECT rc;
EDIT_GetLineRect(es, 0, start, end, &line_rect);
if (IntersectRect(&rc, &line_rect, &es->format_rect))
EDIT_UpdateText(es, &rc, TRUE);
}
/*********************************************************************
*
* EDIT_ML_InvalidateText
*
* Called from EDIT_InvalidateText().
* Does the job for multi-line controls only.
*
*/
static void EDIT_ML_InvalidateText(EDITSTATE *es, INT start, INT end)
{
INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
INT sl = EDIT_EM_LineFromChar(es, start);
INT el = EDIT_EM_LineFromChar(es, end);
INT sc;
INT ec;
RECT rc1;
RECT rcWnd;
RECT rcLine;
RECT rcUpdate;
INT l;
if ((el < es->y_offset) || (sl > es->y_offset + vlc))
return;
sc = start - EDIT_EM_LineIndex(es, sl);
ec = end - EDIT_EM_LineIndex(es, el);
if (sl < es->y_offset) {
sl = es->y_offset;
sc = 0;
}
if (el > es->y_offset + vlc) {
el = es->y_offset + vlc;
ec = EDIT_EM_LineLength(es, EDIT_EM_LineIndex(es, el));
}
GetClientRect(es->hwndSelf, &rc1);
IntersectRect(&rcWnd, &rc1, &es->format_rect);
if (sl == el) {
EDIT_GetLineRect(es, sl, sc, ec, &rcLine);
if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
EDIT_UpdateText(es, &rcUpdate, TRUE);
} else {
EDIT_GetLineRect(es, sl, sc,
EDIT_EM_LineLength(es,
EDIT_EM_LineIndex(es, sl)),
&rcLine);
if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
EDIT_UpdateText(es, &rcUpdate, TRUE);
for (l = sl + 1 ; l < el ; l++) {
EDIT_GetLineRect(es, l, 0,
EDIT_EM_LineLength(es,
EDIT_EM_LineIndex(es, l)),
&rcLine);
if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
EDIT_UpdateText(es, &rcUpdate, TRUE);
}
EDIT_GetLineRect(es, el, 0, ec, &rcLine);
if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
EDIT_UpdateText(es, &rcUpdate, TRUE);
}
}
/*********************************************************************
*
* EDIT_InvalidateText
*
* Invalidate the text from offset start up to, but not including,
* offset end. Useful for (re)painting the selection.
* Regions outside the linewidth are not invalidated.
* end == -1 means end == TextLength.
* start and end need not be ordered.
*
*/
static void EDIT_InvalidateText(EDITSTATE *es, INT start, INT end)
{
if (end == start)
return;
if (end == -1)
end = strlenW(es->text);
if (end < start) {
INT tmp = start;
start = end;
end = tmp;
}
if (es->style & ES_MULTILINE)
EDIT_ML_InvalidateText(es, start, end);
else
EDIT_SL_InvalidateText(es, start, end);
}
/*********************************************************************
*
* EDIT_MakeFit
*
* Try to fit size + 1 characters in the buffer.
*/
static BOOL EDIT_MakeFit(EDITSTATE *es, UINT size)
{
HLOCAL hNew32W;
if (size <= es->buffer_size)
return TRUE;
TRACE("trying to ReAlloc to %d+1 characters\n", size);
/* Force edit to unlock it's buffer. es->text now NULL */
EDIT_UnlockBuffer(es, TRUE);
if (es->hloc32W) {
UINT alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
if ((hNew32W = LocalReAlloc(es->hloc32W, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT))) {
TRACE("Old 32 bit handle %p, new handle %p\n", es->hloc32W, hNew32W);
es->hloc32W = hNew32W;
es->buffer_size = LocalSize(hNew32W)/sizeof(WCHAR) - 1;
}
}
EDIT_LockBuffer(es);
if (es->buffer_size < size) {
WARN("FAILED ! We now have %d+1\n", es->buffer_size);
EDIT_NOTIFY_PARENT(es, EN_ERRSPACE);
return FALSE;
} else {
TRACE("We now have %d+1\n", es->buffer_size);
return TRUE;
}
}
/*********************************************************************
*
* EDIT_MakeUndoFit
*
* Try to fit size + 1 bytes in the undo buffer.
*
*/
static BOOL EDIT_MakeUndoFit(EDITSTATE *es, UINT size)
{
UINT alloc_size;
if (size <= es->undo_buffer_size)
return TRUE;
TRACE("trying to ReAlloc to %d+1\n", size);
alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
if ((es->undo_text = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, es->undo_text, alloc_size))) {
es->undo_buffer_size = alloc_size/sizeof(WCHAR) - 1;
return TRUE;
}
else
{
WARN("FAILED ! We now have %d+1\n", es->undo_buffer_size);
return FALSE;
}
}
/*********************************************************************
*
* EDIT_MoveBackward
*
*/
static void EDIT_MoveBackward(EDITSTATE *es, BOOL extend)
{
INT e = es->selection_end;
if (e) {
e--;
if ((es->style & ES_MULTILINE) && e &&
(es->text[e - 1] == '\r') && (es->text[e] == '\n')) {
e--;
if (e && (es->text[e - 1] == '\r'))
e--;
}
}
EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
EDIT_EM_ScrollCaret(es);
}
/*********************************************************************
*
* EDIT_MoveDown_ML
*
* Only for multi line controls
* Move the caret one line down, on a column with the nearest
* x coordinate on the screen (might be a different column).
*
*/
static void EDIT_MoveDown_ML(EDITSTATE *es, BOOL extend)
{
INT s = es->selection_start;
INT e = es->selection_end;
BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
INT x = (short)LOWORD(pos);
INT y = (short)HIWORD(pos);
e = EDIT_CharFromPos(es, x, y + es->line_height, &after_wrap);
if (!extend)
s = e;
EDIT_EM_SetSel(es, s, e, after_wrap);
EDIT_EM_ScrollCaret(es);
}
/*********************************************************************
*
* EDIT_MoveEnd
*
*/
static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend)
{
BOOL after_wrap = FALSE;
INT e;
/* Pass a high value in x to make sure of receiving the end of the line */
if (es->style & ES_MULTILINE)
e = EDIT_CharFromPos(es, 0x3fffffff,
HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap);
else
e = strlenW(es->text);
EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, after_wrap);
EDIT_EM_ScrollCaret(es);
}
/*********************************************************************
*
* EDIT_MoveForward
*
*/
static void EDIT_MoveForward(EDITSTATE *es, BOOL extend)
{
INT e = es->selection_end;
if (es->text[e]) {
e++;
if ((es->style & ES_MULTILINE) && (es->text[e - 1] == '\r')) {
if (es->text[e] == '\n')
e++;
else if ((es->text[e] == '\r') && (es->text[e + 1] == '\n'))
e += 2;
}
}
EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
EDIT_EM_ScrollCaret(es);
}
/*********************************************************************
*
* EDIT_MoveHome
*
* Home key: move to beginning of line.
*
*/
static void EDIT_MoveHome(EDITSTATE *es, BOOL extend)
{
INT e;
/* Pass the x_offset in x to make sure of receiving the first position of the line */
if (es->style & ES_MULTILINE)
e = EDIT_CharFromPos(es, -es->x_offset,
HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), NULL);
else
e = 0;
EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
EDIT_EM_ScrollCaret(es);
}
/*********************************************************************
*
* EDIT_MovePageDown_ML
*
* Only for multi line controls
* Move the caret one page down, on a column with the nearest
* x coordinate on the screen (might be a different column).
*
*/
static void EDIT_MovePageDown_ML(EDITSTATE *es, BOOL extend)
{
INT s = es->selection_start;
INT e = es->selection_end;
BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
INT x = (short)LOWORD(pos);
INT y = (short)HIWORD(pos);
e = EDIT_CharFromPos(es, x,
y + (es->format_rect.bottom - es->format_rect.top),
&after_wrap);
if (!extend)
s = e;
EDIT_EM_SetSel(es, s, e, after_wrap);
EDIT_EM_ScrollCaret(es);
}
/*********************************************************************
*
* EDIT_MovePageUp_ML
*
* Only for multi line controls
* Move the caret one page up, on a column with the nearest
* x coordinate on the screen (might be a different column).
*
*/
static void EDIT_MovePageUp_ML(EDITSTATE *es, BOOL extend)
{
INT s = es->selection_start;
INT e = es->selection_end;
BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
INT x = (short)LOWORD(pos);
INT y = (short)HIWORD(pos);
e = EDIT_CharFromPos(es, x,
y - (es->format_rect.bottom - es->format_rect.top),
&after_wrap);
if (!extend)
s = e;
EDIT_EM_SetSel(es, s, e, after_wrap);
EDIT_EM_ScrollCaret(es);
}
/*********************************************************************
*
* EDIT_MoveUp_ML
*
* Only for multi line controls
* Move the caret one line up, on a column with the nearest
* x coordinate on the screen (might be a different column).
*
*/
static void EDIT_MoveUp_ML(EDITSTATE *es, BOOL extend)
{
INT s = es->selection_start;
INT e = es->selection_end;
BOOL after_wrap = (e
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -