📄 edit.c
字号:
current_line->net_length, es->tabs_count, es->tabs));
}
else if (orig_net_length < current_line->net_length &&
current_line == start_line &&
current_line->index != nstart_index) {
/* The previous line expanded but it's still not as wide as the client rect */
/* The expansion is due to an upwards line wrap so we must partially include
it in the update region */
nstart_line = line_index;
nstart_index = current_line->index;
istart = current_line->index + orig_net_length;
}
}
/* Adjust length to include line termination */
switch (current_line->ending) {
case END_SOFT:
current_line->length = current_line->net_length + 3;
break;
case END_RICH:
current_line->length = current_line->net_length + 1;
break;
case END_HARD:
current_line->length = current_line->net_length + 2;
break;
case END_WRAP:
case END_0:
current_line->length = current_line->net_length;
break;
}
es->text_width = max(es->text_width, current_line->width);
current_position += current_line->length;
previous_line = current_line;
current_line = current_line->next;
line_index++;
} while (previous_line->ending != END_0);
/* Finish adjusting line indexes by delta or remove hanging lines */
if (previous_line->ending == END_0)
{
LINEDEF *pnext = NULL;
previous_line->next = NULL;
while (current_line)
{
pnext = current_line->next;
HeapFree(GetProcessHeap(), 0, current_line);
current_line = pnext;
es->line_count--;
}
}
else if (delta != 0)
{
while (current_line)
{
current_line->index += delta;
current_line = current_line->next;
}
}
/* Calculate rest of modification rectangle */
if (hrgn)
{
HRGN tmphrgn;
/*
* We calculate two rectangles. One for the first line which may have
* an indent with respect to the format rect. The other is a format-width
* rectangle that spans the rest of the lines that changed or moved.
*/
rc.top = es->format_rect.top + nstart_line * es->line_height -
(es->y_offset * es->line_height); /* Adjust for vertical scrollbar */
rc.bottom = rc.top + es->line_height;
if ((es->style & ES_CENTER) || (es->style & ES_RIGHT))
rc.left = es->format_rect.left;
else
rc.left = es->format_rect.left + (INT)LOWORD(GetTabbedTextExtentW(dc,
es->text + nstart_index, istart - nstart_index,
es->tabs_count, es->tabs)) - es->x_offset; /* Adjust for horz scroll */
rc.right = es->format_rect.right;
SetRectRgn(hrgn, rc.left, rc.top, rc.right, rc.bottom);
rc.top = rc.bottom;
rc.left = es->format_rect.left;
rc.right = es->format_rect.right;
/*
* If lines were added or removed we must re-paint the remainder of the
* lines since the remaining lines were either shifted up or down.
*/
if (line_count < es->line_count) /* We added lines */
rc.bottom = es->line_count * es->line_height;
else if (line_count > es->line_count) /* We removed lines */
rc.bottom = line_count * es->line_height;
else
rc.bottom = line_index * es->line_height;
rc.bottom += es->format_rect.top;
rc.bottom -= (es->y_offset * es->line_height); /* Adjust for vertical scrollbar */
tmphrgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
CombineRgn(hrgn, hrgn, tmphrgn, RGN_OR);
DeleteObject(tmphrgn);
}
if (es->font)
SelectObject(dc, old_font);
ReleaseDC(es->hwndSelf, dc);
}
/*********************************************************************
*
* EDIT_CalcLineWidth_SL
*
*/
static void EDIT_CalcLineWidth_SL(EDITSTATE *es)
{
SIZE size;
LPWSTR text;
HDC dc;
HFONT old_font = 0;
text = EDIT_GetPasswordPointer_SL(es);
dc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(dc, es->font);
GetTextExtentPoint32W(dc, text, strlenW(text), &size);
if (es->font)
SelectObject(dc, old_font);
ReleaseDC(es->hwndSelf, dc);
if (es->style & ES_PASSWORD)
HeapFree(GetProcessHeap(), 0, text);
es->text_width = size.cx;
}
/*********************************************************************
*
* EDIT_CallWordBreakProc
*
* Call appropriate WordBreakProc (internal or external).
*
* Note: The "start" argument should always be an index referring
* to es->text. The actual wordbreak proc might be
* 16 bit, so we can't always pass any 32 bit LPSTR.
* Hence we assume that es->text is the buffer that holds
* the string under examination (we can decide this for ourselves).
*
*/
static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action)
{
INT ret;
#ifndef __REACTOS__
if (es->word_break_proc16) {
HGLOBAL16 hglob16;
SEGPTR segptr;
INT countA;
WORD args[5];
DWORD result;
countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
hglob16 = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, countA);
segptr = K32WOWGlobalLock16(hglob16);
WideCharToMultiByte(CP_ACP, 0, es->text + start, count, MapSL(segptr), countA, NULL, NULL);
args[4] = SELECTOROF(segptr);
args[3] = OFFSETOF(segptr);
args[2] = index;
args[1] = countA;
args[0] = action;
WOWCallback16Ex((DWORD)es->word_break_proc16, WCB16_PASCAL, sizeof(args), args, &result);
ret = LOWORD(result);
GlobalUnlock16(hglob16);
GlobalFree16(hglob16);
}
else if (es->word_break_proc)
#else
if (es->word_break_proc)
#endif
{
if(es->is_unicode)
{
EDITWORDBREAKPROCW wbpW = (EDITWORDBREAKPROCW)es->word_break_proc;
TRACE_(relay)("(UNICODE wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
es->word_break_proc, debugstr_wn(es->text + start, count), index, count, action);
ret = wbpW(es->text + start, index, count, action);
}
else
{
EDITWORDBREAKPROCA wbpA = (EDITWORDBREAKPROCA)es->word_break_proc;
INT countA;
CHAR *textA;
countA = WideCharToMultiByte(CP_ACP, 0, es->text + start, count, NULL, 0, NULL, NULL);
textA = HeapAlloc(GetProcessHeap(), 0, countA);
WideCharToMultiByte(CP_ACP, 0, es->text + start, count, textA, countA, NULL, NULL);
TRACE_(relay)("(ANSI wordbrk=%p,str=%s,idx=%d,cnt=%d,act=%d)\n",
es->word_break_proc, debugstr_an(textA, countA), index, countA, action);
ret = wbpA(textA, index, countA, action);
HeapFree(GetProcessHeap(), 0, textA);
}
}
else
ret = EDIT_WordBreakProc(es->text + start, index, count, action);
return ret;
}
/*********************************************************************
*
* EDIT_CharFromPos
*
* Beware: This is not the function called on EM_CHARFROMPOS
* The position _can_ be outside the formatting / client
* rectangle
* The return value is only the character index
*
*/
static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
{
INT index;
HDC dc;
HFONT old_font = 0;
INT x_high = 0, x_low = 0;
if (es->style & ES_MULTILINE) {
INT line = (y - es->format_rect.top) / es->line_height + es->y_offset;
INT line_index = 0;
LINEDEF *line_def = es->first_line_def;
INT low, high;
while ((line > 0) && line_def->next) {
line_index += line_def->length;
line_def = line_def->next;
line--;
}
x += es->x_offset - es->format_rect.left;
if (es->style & ES_RIGHT)
x -= (es->format_rect.right - es->format_rect.left) - line_def->width;
else if (es->style & ES_CENTER)
x -= ((es->format_rect.right - es->format_rect.left) - line_def->width) / 2;
if (x >= line_def->width) {
if (after_wrap)
*after_wrap = (line_def->ending == END_WRAP);
return line_index + line_def->net_length;
}
if (x <= 0) {
if (after_wrap)
*after_wrap = FALSE;
return line_index;
}
dc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(dc, es->font);
low = line_index;
high = line_index + line_def->net_length + 1;
while (low < high - 1)
{
INT mid = (low + high) / 2;
INT x_now = LOWORD(GetTabbedTextExtentW(dc, es->text + line_index, mid - line_index, es->tabs_count, es->tabs));
if (x_now > x) {
high = mid;
x_high = x_now;
} else {
low = mid;
x_low = x_now;
}
}
if (abs(x_high - x) + 1 <= abs(x_low - x))
index = high;
else
index = low;
if (after_wrap)
*after_wrap = ((index == line_index + line_def->net_length) &&
(line_def->ending == END_WRAP));
} else {
LPWSTR text;
SIZE size;
if (after_wrap)
*after_wrap = FALSE;
x -= es->format_rect.left;
if (!x)
return es->x_offset;
if (!es->x_offset)
{
INT indent = (es->format_rect.right - es->format_rect.left) - es->text_width;
if (es->style & ES_RIGHT)
x -= indent;
else if (es->style & ES_CENTER)
x -= indent / 2;
}
text = EDIT_GetPasswordPointer_SL(es);
dc = GetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(dc, es->font);
if (x < 0)
{
INT low = 0;
INT high = es->x_offset;
while (low < high - 1)
{
INT mid = (low + high) / 2;
GetTextExtentPoint32W( dc, text + mid,
es->x_offset - mid, &size );
if (size.cx > -x) {
low = mid;
x_low = size.cx;
} else {
high = mid;
x_high = size.cx;
}
}
if (abs(x_high + x) <= abs(x_low + x) + 1)
index = high;
else
index = low;
}
else
{
INT low = es->x_offset;
INT high = strlenW(es->text) + 1;
while (low < high - 1)
{
INT mid = (low + high) / 2;
GetTextExtentPoint32W( dc, text + es->x_offset,
mid - es->x_offset, &size );
if (size.cx > x) {
high = mid;
x_high = size.cx;
} else {
low = mid;
x_low = size.cx;
}
}
if (abs(x_high - x) <= abs(x_low - x) + 1)
index = high;
else
index = low;
}
if (es->style & ES_PASSWORD)
HeapFree(GetProcessHeap(), 0, text);
}
if (es->font)
SelectObject(dc, old_font);
ReleaseDC(es->hwndSelf, dc);
return index;
}
/*********************************************************************
*
* EDIT_ConfinePoint
*
* adjusts the point to be within the formatting rectangle
* (so CharFromPos returns the nearest _visible_ character)
*
*/
static void EDIT_ConfinePoint(EDITSTATE *es, LPINT x, LPINT y)
{
*x = min(max(*x, es->format_rect.left), es->format_rect.right - 1);
*y = min(max(*y, es->format_rect.top), es->format_rect.bottom - 1);
}
/*********************************************************************
*
* EDIT_GetLineRect
*
* Calculates the bounding rectangle for a line from a starting
* column to an ending column.
*
*/
static void EDIT_GetLineRect(EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc)
{
INT line_index = EDIT_EM_LineIndex(es, line);
if (es->style & ES_MULTILINE)
rc->top = es->format_rect.top + (line - es->y_offset) * es->line_height;
else
rc->top = es->format_rect.top;
rc->bottom = rc->top + es->line_height;
rc->left = (scol == 0) ? es->format_rect.left : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + scol, TRUE));
rc->right = (ecol == -1) ? es->format_rect.right : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + ecol, TRUE));
}
/*********************************************************************
*
* EDIT_GetPasswordPointer_SL
*
* note: caller should free the (optionally) allocated buffer
*
*/
static LPWSTR EDIT_GetPasswordPointer_SL(EDITSTATE *es)
{
if (es->style & ES_PASSWORD) {
INT len = strlenW(es->text);
LPWSTR text = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
text[len] = '\0';
while(len) text[--len] = es->password_char;
return text;
} else
return es->text;
}
/*********************************************************************
*
* EDIT_LockBuffer
*
* This acts as a LOCAL_Lock(), but it locks only once. This way
* you can call it whenever you like, without unlocking.
*
* Initially the edit control allocates a HLOCAL32 buffer
* (32 bit linear memory handler). However, 16 bit application
* might send an EM_GETHANDLE message and expect a HLOCAL16 (16 bit SEG:OFF
* handler). From that moment on we have to keep using this 16 bit memory
* handler, because it is supposed to be valid at all times after EM_GETHANDLE.
* What we do is create a HLOCAL16 buffer, copy the text, and do pointer
* conversion.
*
*/
static void EDIT_LockBuffer(EDITSTATE *es)
{
#ifndef __REACTOS__
HINSTANCE16 hInstance = GetWindowLongW( es->hwndSelf, GWL_HINSTANCE );
#endif
if (!es->text) {
CHAR *textA = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -