ReactOS 0.4.15-dev-8058-ga7cbb60
edit.c
Go to the documentation of this file.
1/*
2 * Edit control
3 *
4 * Copyright David W. Metcalfe, 1994
5 * Copyright William Magro, 1995, 1996
6 * Copyright Frans van Dorsselaer, 1996, 1997
7 * Copyright Frank Richter, 2005
8 *
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 *
24 * TODO:
25 * - EDITBALLOONTIP structure
26 * - EM_GETCUEBANNER/Edit_GetCueBannerText
27 * - EM_HIDEBALLOONTIP/Edit_HideBalloonTip
28 * - EM_SETCUEBANNER/Edit_SetCueBannerText
29 * - EM_SHOWBALLOONTIP/Edit_ShowBalloonTip
30 * - EM_GETIMESTATUS, EM_SETIMESTATUS
31 * - EN_ALIGN_LTR_EC
32 * - EN_ALIGN_RTL_EC
33 * - ES_OEMCONVERT
34 *
35 */
36
37#include "config.h"
38
39#include <stdarg.h>
40#include <string.h>
41#include <stdlib.h>
42
43#include "windef.h"
44#include "winbase.h"
45#include "wingdi.h"
46#include "winuser.h"
47#include "imm.h"
48#ifdef __REACTOS__
49 #include <immdev.h>
50 #include <imm32_undoc.h>
51#endif
52#include "usp10.h"
53#include "commctrl.h"
54#include "uxtheme.h"
55#include "vsstyle.h"
56#include "wine/unicode.h"
57#include "wine/debug.h"
58#include "wine/heap.h"
59
61
62#define BUFLIMIT_INITIAL 30000 /* initial buffer size */
63#define GROWLENGTH 32 /* buffers granularity in bytes: must be power of 2 */
64#define ROUND_TO_GROW(size) (((size) + (GROWLENGTH - 1)) & ~(GROWLENGTH - 1))
65#define HSCROLL_FRACTION 3 /* scroll window by 1/3 width */
66
67/*
68 * extra flags for EDITSTATE.flags field
69 */
70#define EF_MODIFIED 0x0001 /* text has been modified */
71#define EF_FOCUSED 0x0002 /* we have input focus */
72#define EF_UPDATE 0x0004 /* notify parent of changed state */
73#define EF_VSCROLL_TRACK 0x0008 /* don't SetScrollPos() since we are tracking the thumb */
74#define EF_HSCROLL_TRACK 0x0010 /* don't SetScrollPos() since we are tracking the thumb */
75#define EF_AFTER_WRAP 0x0080 /* the caret is displayed after the last character of a
76 wrapped line, instead of in front of the next character */
77#define EF_USE_SOFTBRK 0x0100 /* Enable soft breaks in text. */
78#define EF_DIALOGMODE 0x0200 /* Indicates that we are inside a dialog window */
80#define ID_CB_LISTBOX 1000
82typedef enum
84 END_0 = 0, /* line ends with terminating '\0' character */
85 END_WRAP, /* line is wrapped */
86 END_HARD, /* line ends with a hard return '\r\n' */
87 END_SOFT, /* line ends with a soft return '\r\r\n' */
88 END_RICH /* line ends with a single '\n' */
89} LINE_END;
91typedef struct tagLINEDEF {
92 INT length; /* bruto length of a line in bytes */
93 INT net_length; /* netto length of a line in visible characters */
95 INT width; /* width of the line in pixels */
96 INT index; /* line index into the buffer */
97 SCRIPT_STRING_ANALYSIS ssa; /* Uniscribe Data */
99} LINEDEF;
101typedef struct
103 LPWSTR text; /* the actual contents of the control */
104 UINT text_length; /* cached length of text buffer (in WCHARs) - use get_text_length() to retrieve */
105 UINT buffer_size; /* the size of the buffer in characters */
106 UINT buffer_limit; /* the maximum size to which the buffer may grow in characters */
107 HFONT font; /* NULL means standard system font */
108 INT x_offset; /* scroll offset for multi lines this is in pixels
109 for single lines it's in characters */
110#ifdef __REACTOS__
111 DWORD dwCaretWidth;
112#endif
113 INT line_height; /* height of a screen line in pixels */
114 INT char_width; /* average character width in pixels */
115 DWORD style; /* sane version of wnd->dwStyle */
116 WORD flags; /* flags that are not in es->style or wnd->flags (EF_XXX) */
117 INT undo_insert_count; /* number of characters inserted in sequence */
118 UINT undo_position; /* character index of the insertion and deletion */
119 LPWSTR undo_text; /* deleted text */
120 UINT undo_buffer_size; /* size of the deleted text buffer */
121 INT selection_start; /* == selection_end if no selection */
122 INT selection_end; /* == current caret position */
123 WCHAR password_char; /* == 0 if no password char, and for multi line controls */
124 INT left_margin; /* in pixels */
125 INT right_margin; /* in pixels */
126 RECT format_rect;
127 INT text_width; /* width of the widest line in pixels for multi line controls
128 and just line width for single line controls */
129 INT region_posx; /* Position of cursor relative to region: */
130 INT region_posy; /* -1: to left, 0: within, 1: to right */
131 EDITWORDBREAKPROCW word_break_proc;
132 INT line_count; /* number of lines */
133 INT y_offset; /* scroll offset in number of lines */
134 BOOL bCaptureState; /* flag indicating whether mouse was captured */
135 BOOL bEnableState; /* flag keeping the enable state */
136 HWND hwndSelf; /* the our window handle */
137 HWND hwndParent; /* Handle of parent for sending EN_* messages.
138 Even if parent will change, EN_* messages
139 should be sent to the first parent. */
140 HWND hwndListBox; /* handle of ComboBox's listbox or NULL */
141 INT wheelDeltaRemainder; /* scroll wheel delta left over after scrolling whole lines */
142 /*
143 * only for multi line controls
144 */
145 INT lock_count; /* amount of re-entries in the EditWndProc */
146 INT tabs_count;
147 LPINT tabs;
148 LINEDEF *first_line_def; /* linked list of (soft) linebreaks */
149 HLOCAL hloc32W; /* our unicode local memory block */
150 HLOCAL hlocapp; /* The text buffer handle belongs to the app */
151 /*
152 * IME Data
153 */
154#ifndef __REACTOS__ /* Rely on the composition window */
155 UINT composition_len; /* length of composition, 0 == no composition */
156 int composition_start; /* the character position for the composition */
157#endif
158 /*
159 * Uniscribe Data
160 */
162 SCRIPT_STRING_ANALYSIS ssa; /* Uniscribe Data for single line controls */
163} EDITSTATE;
164
166#define SWAP_UINT32(x,y) do { UINT temp = (UINT)(x); (x) = (UINT)(y); (y) = temp; } while(0)
167#define ORDER_UINT(x,y) do { if ((UINT)(y) < (UINT)(x)) SWAP_UINT32((x),(y)); } while(0)
169static inline BOOL notify_parent(const EDITSTATE *es, INT code)
170{
171 HWND hwnd = es->hwndSelf;
172 TRACE("notification %d sent to %p.\n", code, es->hwndParent);
173 SendMessageW(es->hwndParent, WM_COMMAND, MAKEWPARAM(GetWindowLongPtrW(es->hwndSelf, GWLP_ID), code), (LPARAM)es->hwndSelf);
174 return IsWindow(hwnd);
175}
176
177static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap);
178
179/*********************************************************************
180 *
181 * EM_CANUNDO
182 *
183 */
184static inline BOOL EDIT_EM_CanUndo(const EDITSTATE *es)
185{
186 return (es->undo_insert_count || strlenW(es->undo_text));
187}
188
189
190/*********************************************************************
191 *
192 * EM_EMPTYUNDOBUFFER
193 *
194 */
195static inline void EDIT_EM_EmptyUndoBuffer(EDITSTATE *es)
196{
197 es->undo_insert_count = 0;
198 *es->undo_text = '\0';
199}
201static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
202{
203 HBRUSH hbrush;
204 UINT msg;
205
206 if ((!es->bEnableState || (es->style & ES_READONLY)))
208 else
210
211 /* Why do we notify to es->hwndParent, and we send this one to GetParent()? */
212 hbrush = (HBRUSH)SendMessageW(GetParent(es->hwndSelf), msg, (WPARAM)hdc, (LPARAM)es->hwndSelf);
213 if (!hbrush)
214 hbrush = (HBRUSH)DefWindowProcW(GetParent(es->hwndSelf), msg, (WPARAM)hdc, (LPARAM)es->hwndSelf);
215 return hbrush;
216}
217
219static inline UINT get_text_length(EDITSTATE *es)
220{
221 if(es->text_length == (UINT)-1)
222 es->text_length = strlenW(es->text);
223 return es->text_length;
224}
225
226
227/*********************************************************************
228 *
229 * EDIT_WordBreakProc
230 *
231 * Find the beginning of words.
232 * Note: unlike the specs for a WordBreakProc, this function can
233 * only be called without linebreaks between s[0] up to
234 * s[count - 1]. Remember it is only called
235 * internally, so we can decide this for ourselves.
236 * Additionally we will always be breaking the full string.
237 *
238 */
240{
241 INT ret = 0;
242
243 TRACE("s=%p, index=%d, count=%d, action=%d\n", s, index, count, action);
244
245 if(!s) return 0;
246
247 if (!es->logAttr)
248 {
250
251 memset(&psa,0,sizeof(SCRIPT_ANALYSIS));
252 psa.eScript = SCRIPT_UNDEFINED;
253
254 es->logAttr = heap_alloc(sizeof(SCRIPT_LOGATTR) * get_text_length(es));
255 ScriptBreak(es->text, get_text_length(es), &psa, es->logAttr);
256 }
257
258 switch (action) {
259 case WB_LEFT:
260 if (index)
261 index--;
262 while (index && !es->logAttr[index].fSoftBreak)
263 index--;
264 ret = index;
265 break;
266 case WB_RIGHT:
267 if (!count)
268 break;
269 while (index < count && s[index] && !es->logAttr[index].fSoftBreak)
270 index++;
271 ret = index;
272 break;
273 case WB_ISDELIMITER:
274 ret = es->logAttr[index].fWhiteSpace;
275 break;
276 default:
277 ERR("unknown action code, please report !\n");
278 break;
279 }
280 return ret;
281}
282
283
284/*********************************************************************
285 *
286 * EDIT_CallWordBreakProc
287 *
288 * Call appropriate WordBreakProc (internal or external).
289 *
290 * Note: The "start" argument should always be an index referring
291 * to es->text. The actual wordbreak proc might be
292 * 16 bit, so we can't always pass any 32 bit LPSTR.
293 * Hence we assume that es->text is the buffer that holds
294 * the string under examination (we can decide this for ourselves).
295 *
296 */
298{
299 INT ret;
300
301 if (es->word_break_proc)
302 ret = es->word_break_proc(es->text + start, index, count, action);
303 else
305
306 return ret;
307}
309static inline void EDIT_InvalidateUniscribeData_linedef(LINEDEF *line_def)
310{
311 if (line_def->ssa)
312 {
313 ScriptStringFree(&line_def->ssa);
314 line_def->ssa = NULL;
315 }
316}
318static inline void EDIT_InvalidateUniscribeData(EDITSTATE *es)
319{
320 LINEDEF *line_def = es->first_line_def;
321 while (line_def)
322 {
324 line_def = line_def->next;
325 }
326 if (es->ssa)
327 {
328 ScriptStringFree(&es->ssa);
329 es->ssa = NULL;
330 }
331}
334{
335 if (!line_def)
336 return NULL;
337
338 if (line_def->net_length && !line_def->ssa)
339 {
340 int index = line_def->index;
341 HFONT old_font = NULL;
342 HDC udc = dc;
343 SCRIPT_TABDEF tabdef;
344 HRESULT hr;
345
346 if (!udc)
347 udc = GetDC(es->hwndSelf);
348 if (es->font)
349 old_font = SelectObject(udc, es->font);
350
351 tabdef.cTabStops = es->tabs_count;
352 tabdef.iScale = GdiGetCharDimensions(udc, NULL, NULL);
353 tabdef.pTabStops = es->tabs;
354 tabdef.iTabOrigin = 0;
355
356 hr = ScriptStringAnalyse(udc, &es->text[index], line_def->net_length,
357 (1.5*line_def->net_length+16), -1,
359 NULL, NULL, NULL, &tabdef, NULL, &line_def->ssa);
360 if (FAILED(hr))
361 {
362 WARN("ScriptStringAnalyse failed (%x)\n",hr);
363 line_def->ssa = NULL;
364 }
365
366 if (es->font)
367 SelectObject(udc, old_font);
368 if (udc != dc)
369 ReleaseDC(es->hwndSelf, udc);
370 }
371
372 return line_def->ssa;
373}
376{
377 LINEDEF *line_def;
378
379 if (!(es->style & ES_MULTILINE))
380 {
381 if (!es->ssa)
382 {
384 HFONT old_font = NULL;
385 HDC udc = dc;
386
387 if (!udc)
388 udc = GetDC(es->hwndSelf);
389 if (es->font)
390 old_font = SelectObject(udc, es->font);
391
392 if (es->style & ES_PASSWORD)
393 ScriptStringAnalyse(udc, &es->password_char, length, (1.5*length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_PASSWORD, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa);
394 else
395 ScriptStringAnalyse(udc, es->text, length, (1.5*length+16), -1, SSA_LINK|SSA_FALLBACK|SSA_GLYPHS, -1, NULL, NULL, NULL, NULL, NULL, &es->ssa);
396
397 if (es->font)
398 SelectObject(udc, old_font);
399 if (udc != dc)
400 ReleaseDC(es->hwndSelf, udc);
401 }
402 return es->ssa;
403 }
404 else
405 {
406 line_def = es->first_line_def;
407 while (line_def && line)
408 {
409 line_def = line_def->next;
410 line--;
411 }
412
413 return EDIT_UpdateUniscribeData_linedef(es,dc,line_def);
414 }
415}
418{
419 INT vlc = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
420 return max(1,vlc);
421}
422
423/*********************************************************************
424 *
425 * EDIT_BuildLineDefs_ML
426 *
427 * Build linked list of text lines.
428 * Lines can end with '\0' (last line), a character (if it is wrapped),
429 * a soft return '\r\r\n' or a hard return '\r\n'
430 *
431 */
432static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta, HRGN hrgn)
433{
434 LPWSTR current_position, cp;
435 INT fw;
436 LINEDEF *current_line;
437 LINEDEF *previous_line;
438 LINEDEF *start_line;
439 INT line_index = 0, nstart_line, nstart_index;
440 INT line_count = es->line_count;
441 INT orig_net_length;
442 RECT rc;
443 INT vlc;
444
445 if (istart == iend && delta == 0)
446 return;
447
448 previous_line = NULL;
449 current_line = es->first_line_def;
450
451 /* Find starting line. istart must lie inside an existing line or
452 * at the end of buffer */
453 do {
454 if (istart < current_line->index + current_line->length ||
455 current_line->ending == END_0)
456 break;
457
458 previous_line = current_line;
459 current_line = current_line->next;
460 line_index++;
461 } while (current_line);
462
463 if (!current_line) /* Error occurred start is not inside previous buffer */
464 {
465 FIXME(" modification occurred outside buffer\n");
466 return;
467 }
468
469 /* Remember start of modifications in order to calculate update region */
470 nstart_line = line_index;
471 nstart_index = current_line->index;
472
473 /* We must start to reformat from the previous line since the modifications
474 * may have caused the line to wrap upwards. */
475 if (!(es->style & ES_AUTOHSCROLL) && line_index > 0)
476 {
477 line_index--;
478 current_line = previous_line;
479 }
480 start_line = current_line;
481
482 fw = es->format_rect.right - es->format_rect.left;
483 current_position = es->text + current_line->index;
485 do {
486 if (current_line != start_line)
487 {
488 if (!current_line || current_line->index + delta > current_position - es->text)
489 {
490 /* The buffer has been expanded, create a new line and
491 insert it into the link list */
492 LINEDEF *new_line = heap_alloc_zero(sizeof(*new_line));
493 new_line->next = previous_line->next;
494 previous_line->next = new_line;
495 current_line = new_line;
496 es->line_count++;
497 }
498 else if (current_line->index + delta < current_position - es->text)
499 {
500 /* The previous line merged with this line so we delete this extra entry */
501 previous_line->next = current_line->next;
502 heap_free(current_line);
503 current_line = previous_line->next;
504 es->line_count--;
505 continue;
506 }
507 else /* current_line->index + delta == current_position */
508 {
509 if (current_position - es->text > iend)
510 break; /* We reached end of line modifications */
511 /* else recalculate this line */
512 }
513 }
514
515 current_line->index = current_position - es->text;
516 orig_net_length = current_line->net_length;
517
518 /* Find end of line */
519 cp = current_position;
520 while (*cp) {
521 if (*cp == '\n') break;
522 if ((*cp == '\r') && (*(cp + 1) == '\n'))
523 break;
524 cp++;
525 }
526
527 /* Mark type of line termination */
528 if (!(*cp)) {
529 current_line->ending = END_0;
530 current_line->net_length = strlenW(current_position);
531 } else if ((cp > current_position) && (*(cp - 1) == '\r')) {
532 current_line->ending = END_SOFT;
533 current_line->net_length = cp - current_position - 1;
534 } else if (*cp == '\n') {
535 current_line->ending = END_RICH;
536 current_line->net_length = cp - current_position;
537 } else {
538 current_line->ending = END_HARD;
539 current_line->net_length = cp - current_position;
540 }
541
542 if (current_line->net_length)
543 {
544 const SIZE *sz;
547 if (current_line->ssa)
548 {
549 sz = ScriptString_pSize(current_line->ssa);
550 /* Calculate line width */
551 current_line->width = sz->cx;
552 }
553 else current_line->width = es->char_width * current_line->net_length;
554 }
555 else current_line->width = 0;
556
557 /* FIXME: check here for lines that are too wide even in AUTOHSCROLL (> 32767 ???) */
558
559/* Line breaks just look back from the end and find the next break and try that. */
560
561 if (!(es->style & ES_AUTOHSCROLL)) {
562 if (current_line->width > fw && fw > es->char_width) {
563
564 INT prev, next;
565 int w;
566 const SIZE *sz;
567 float d;
568
569 prev = current_line->net_length - 1;
570 w = current_line->net_length;
571 d = (float)current_line->width/(float)fw;
572 if (d > 1.2f) d -= 0.2f;
573 next = prev/d;
574 if (next >= prev) next = prev-1;
575 do {
576 prev = EDIT_CallWordBreakProc(es, current_position - es->text,
577 next, current_line->net_length, WB_LEFT);
578 current_line->net_length = prev;
581 if (current_line->ssa)
582 sz = ScriptString_pSize(current_line->ssa);
583 else sz = 0;
584 if (sz)
585 current_line->width = sz->cx;
586 else
587 prev = 0;
588 next = prev - 1;
589 } while (prev && current_line->width > fw);
590 current_line->net_length = w;
591
592 if (prev == 0) { /* Didn't find a line break so force a break */
593 INT *piDx;
594 const INT *count;
595
598
599 if (current_line->ssa)
600 {
601 count = ScriptString_pcOutChars(current_line->ssa);
602 piDx = heap_alloc(sizeof(INT) * (*count));
603 ScriptStringGetLogicalWidths(current_line->ssa,piDx);
604
605 prev = current_line->net_length-1;
606 do {
607 current_line->width -= piDx[prev];
608 prev--;
609 } while ( prev > 0 && current_line->width > fw);
610 if (prev<=0)
611 prev = 1;
612 heap_free(piDx);
613 }
614 else
615 prev = (fw / es->char_width);
616 }
617
618 /* If the first line we are calculating, wrapped before istart, we must
619 * adjust istart in order for this to be reflected in the update region. */
620 if (current_line->index == nstart_index && istart > current_line->index + prev)
621 istart = current_line->index + prev;
622 /* else if we are updating the previous line before the first line we
623 * are re-calculating and it expanded */
624 else if (current_line == start_line &&
625 current_line->index != nstart_index && orig_net_length < prev)
626 {
627 /* Line expanded due to an upwards line wrap so we must partially include
628 * previous line in update region */
629 nstart_line = line_index;
630 nstart_index = current_line->index;
631 istart = current_line->index + orig_net_length;
632 }
633
634 current_line->net_length = prev;
635 current_line->ending = END_WRAP;
636
637 if (current_line->net_length > 0)
638 {
640 if (current_line->ssa)
641 {
642 sz = ScriptString_pSize(current_line->ssa);
643 current_line->width = sz->cx;
644 }
645 else
646 current_line->width = 0;
647 }
648 else current_line->width = 0;
649 }
650 else if (current_line == start_line &&
651 current_line->index != nstart_index &&
652 orig_net_length < current_line->net_length) {
653 /* The previous line expanded but it's still not as wide as the client rect */
654 /* The expansion is due to an upwards line wrap so we must partially include
655 it in the update region */
656 nstart_line = line_index;
657 nstart_index = current_line->index;
658 istart = current_line->index + orig_net_length;
659 }
660 }
661
662
663 /* Adjust length to include line termination */
664 switch (current_line->ending) {
665 case END_SOFT:
666 current_line->length = current_line->net_length + 3;
667 break;
668 case END_RICH:
669 current_line->length = current_line->net_length + 1;
670 break;
671 case END_HARD:
672 current_line->length = current_line->net_length + 2;
673 break;
674 case END_WRAP:
675 case END_0:
676 current_line->length = current_line->net_length;
677 break;
678 }
679 es->text_width = max(es->text_width, current_line->width);
680 current_position += current_line->length;
681 previous_line = current_line;
682
683 /* Discard data for non-visible lines. It will be calculated as needed */
684 if ((line_index < es->y_offset) || (line_index > es->y_offset + vlc))
686
687 current_line = current_line->next;
688 line_index++;
689 } while (previous_line->ending != END_0);
690
691 /* Finish adjusting line indexes by delta or remove hanging lines */
692 if (previous_line->ending == END_0)
693 {
694 LINEDEF *pnext = NULL;
695
696 previous_line->next = NULL;
697 while (current_line)
698 {
699 pnext = current_line->next;
701 heap_free(current_line);
702 current_line = pnext;
703 es->line_count--;
704 }
705 }
706 else if (delta != 0)
707 {
708 while (current_line)
709 {
710 current_line->index += delta;
711 current_line = current_line->next;
712 }
713 }
714
715 /* Calculate rest of modification rectangle */
716 if (hrgn)
717 {
718 HRGN tmphrgn;
719 /*
720 * We calculate two rectangles. One for the first line which may have
721 * an indent with respect to the format rect. The other is a format-width
722 * rectangle that spans the rest of the lines that changed or moved.
723 */
724 rc.top = es->format_rect.top + nstart_line * es->line_height -
725 (es->y_offset * es->line_height); /* Adjust for vertical scrollbar */
726 rc.bottom = rc.top + es->line_height;
727 if ((es->style & ES_CENTER) || (es->style & ES_RIGHT))
728 rc.left = es->format_rect.left;
729 else
730#ifdef __REACTOS__ /* CORE-11475 */
731 rc.left = (short)LOWORD(EDIT_EM_PosFromChar(es, nstart_index, FALSE));
732#else
733 rc.left = LOWORD(EDIT_EM_PosFromChar(es, nstart_index, FALSE));
734#endif
735 rc.right = es->format_rect.right;
736 SetRectRgn(hrgn, rc.left, rc.top, rc.right, rc.bottom);
737
738 rc.top = rc.bottom;
739 rc.left = es->format_rect.left;
740 rc.right = es->format_rect.right;
741 /*
742 * If lines were added or removed we must re-paint the remainder of the
743 * lines since the remaining lines were either shifted up or down.
744 */
745 if (line_count < es->line_count) /* We added lines */
746 rc.bottom = es->line_count * es->line_height;
747 else if (line_count > es->line_count) /* We removed lines */
748 rc.bottom = line_count * es->line_height;
749 else
750 rc.bottom = line_index * es->line_height;
751 rc.bottom += es->format_rect.top;
752 rc.bottom -= (es->y_offset * es->line_height); /* Adjust for vertical scrollbar */
753 tmphrgn = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
754 CombineRgn(hrgn, hrgn, tmphrgn, RGN_OR);
755 DeleteObject(tmphrgn);
756 }
757}
758
759/*********************************************************************
760 *
761 * EDIT_CalcLineWidth_SL
762 *
763 */
765{
767 if (es->ssa)
768 {
769 const SIZE *size;
770 size = ScriptString_pSize(es->ssa);
771 es->text_width = size->cx;
772 }
773 else
774 es->text_width = 0;
775}
776
777/*********************************************************************
778 *
779 * EDIT_CharFromPos
780 *
781 * Beware: This is not the function called on EM_CHARFROMPOS
782 * The position _can_ be outside the formatting / client
783 * rectangle
784 * The return value is only the character index
785 *
786 */
787static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
788{
789 INT index;
790
791 if (es->style & ES_MULTILINE) {
792 int trailing;
793 INT line = (y - es->format_rect.top) / es->line_height + es->y_offset;
794 INT line_index = 0;
795 LINEDEF *line_def = es->first_line_def;
797 while ((line > 0) && line_def->next) {
798 line_index += line_def->length;
799 line_def = line_def->next;
800 line--;
801 }
802
803 x += es->x_offset - es->format_rect.left;
804 if (es->style & ES_RIGHT)
805 x -= (es->format_rect.right - es->format_rect.left) - line_def->width;
806 else if (es->style & ES_CENTER)
807 x -= ((es->format_rect.right - es->format_rect.left) - line_def->width) / 2;
808 if (x >= line_def->width) {
809 if (after_wrap)
810 *after_wrap = (line_def->ending == END_WRAP);
811 return line_index + line_def->net_length;
812 }
813 if (x <= 0 || !line_def->ssa) {
814 if (after_wrap)
815 *after_wrap = FALSE;
816 return line_index;
817 }
818
819 ScriptStringXtoCP(line_def->ssa, x , &index, &trailing);
820 if (trailing) index++;
821 index += line_index;
822 if (after_wrap)
823 *after_wrap = ((index == line_index + line_def->net_length) &&
824 (line_def->ending == END_WRAP));
825 } else {
826 INT xoff = 0;
827 INT trailing;
828 if (after_wrap)
829 *after_wrap = FALSE;
830 x -= es->format_rect.left;
831 if (!x)
832 return es->x_offset;
833
834 if (!es->x_offset)
835 {
836 INT indent = (es->format_rect.right - es->format_rect.left) - es->text_width;
837 if (es->style & ES_RIGHT)
838 x -= indent;
839 else if (es->style & ES_CENTER)
840 x -= indent / 2;
841 }
842
844 if (es->x_offset)
845 {
846 if (es->ssa)
847 {
848 if (es->x_offset>= get_text_length(es))
849 {
850 const SIZE *size;
851 size = ScriptString_pSize(es->ssa);
852 xoff = size->cx;
853 }
854 ScriptStringCPtoX(es->ssa, es->x_offset, FALSE, &xoff);
855 }
856 else
857 xoff = 0;
858 }
859 if (x < 0)
860 {
861 if (x + xoff > 0 || !es->ssa)
862 {
863 ScriptStringXtoCP(es->ssa, x+xoff, &index, &trailing);
864 if (trailing) index++;
865 }
866 else
867 index = 0;
868 }
869 else
870 {
871 if (x)
872 {
873 const SIZE *size = NULL;
874 if (es->ssa)
875 size = ScriptString_pSize(es->ssa);
876 if (!size)
877 index = 0;
878 else if (x > size->cx)
880 else if (es->ssa)
881 {
882 ScriptStringXtoCP(es->ssa, x+xoff, &index, &trailing);
883 if (trailing) index++;
884 }
885 else
886 index = 0;
887 }
888 else
889 index = es->x_offset;
890 }
891 }
892 return index;
893}
894
895
896/*********************************************************************
897 *
898 * EDIT_ConfinePoint
899 *
900 * adjusts the point to be within the formatting rectangle
901 * (so CharFromPos returns the nearest _visible_ character)
902 *
903 */
904static void EDIT_ConfinePoint(const EDITSTATE *es, LPINT x, LPINT y)
905{
906 *x = min(max(*x, es->format_rect.left), es->format_rect.right - 1);
907 *y = min(max(*y, es->format_rect.top), es->format_rect.bottom - 1);
908}
909
910
911/*********************************************************************
912 *
913 * EM_LINEFROMCHAR
914 *
915 */
917{
918 INT line;
919 LINEDEF *line_def;
920
921 if (!(es->style & ES_MULTILINE))
922 return 0;
923 if (index > (INT)get_text_length(es))
924 return es->line_count - 1;
925 if (index == -1)
926 index = min(es->selection_start, es->selection_end);
927
928 line = 0;
929 line_def = es->first_line_def;
930 index -= line_def->length;
931 while ((index >= 0) && line_def->next) {
932 line++;
933 line_def = line_def->next;
934 index -= line_def->length;
935 }
936 return line;
937}
938
939
940/*********************************************************************
941 *
942 * EM_LINEINDEX
943 *
944 */
946{
947 INT line_index;
948 const LINEDEF *line_def;
949
950 if (!(es->style & ES_MULTILINE))
951 return 0;
952 if (line >= es->line_count)
953 return -1;
954
955 line_index = 0;
956 line_def = es->first_line_def;
957 if (line == -1) {
958 INT index = es->selection_end - line_def->length;
959 while ((index >= 0) && line_def->next) {
960 line_index += line_def->length;
961 line_def = line_def->next;
962 index -= line_def->length;
963 }
964 } else {
965 while (line > 0) {
966 line_index += line_def->length;
967 line_def = line_def->next;
968 line--;
969 }
970 }
971 return line_index;
972}
973
974
975/*********************************************************************
976 *
977 * EM_LINELENGTH
978 *
979 */
981{
982 LINEDEF *line_def;
983
984 if (!(es->style & ES_MULTILINE))
985 return get_text_length(es);
986
987 if (index == -1) {
988 /* get the number of remaining non-selected chars of selected lines */
989 INT32 l; /* line number */
990 INT32 li; /* index of first char in line */
991 INT32 count;
992 l = EDIT_EM_LineFromChar(es, es->selection_start);
993 /* # chars before start of selection area */
994 count = es->selection_start - EDIT_EM_LineIndex(es, l);
995 l = EDIT_EM_LineFromChar(es, es->selection_end);
996 /* # chars after end of selection */
998 count += li + EDIT_EM_LineLength(es, li) - es->selection_end;
999 return count;
1000 }
1001 line_def = es->first_line_def;
1002 index -= line_def->length;
1003 while ((index >= 0) && line_def->next) {
1004 line_def = line_def->next;
1005 index -= line_def->length;
1006 }
1007 return line_def->net_length;
1008}
1009
1010
1011/*********************************************************************
1012 *
1013 * EM_POSFROMCHAR
1014 *
1016static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
1017{
1019 INT l;
1020 INT li;
1021 INT x = 0;
1022 INT y = 0;
1023 INT w;
1024 INT lw;
1025 LINEDEF *line_def;
1026
1027 index = min(index, len);
1028 if (es->style & ES_MULTILINE) {
1031
1032 y = (l - es->y_offset) * es->line_height;
1034 if (after_wrap && (li == index) && l) {
1035 INT l2 = l - 1;
1036 line_def = es->first_line_def;
1037 while (l2) {
1038 line_def = line_def->next;
1039 l2--;
1040 }
1041 if (line_def->ending == END_WRAP) {
1042 l--;
1043 y -= es->line_height;
1045 }
1046 }
1047
1048 line_def = es->first_line_def;
1049 while (line_def->index != li)
1050 line_def = line_def->next;
1051
1052 lw = line_def->width;
1053 w = es->format_rect.right - es->format_rect.left;
1054 if (line_def->ssa)
1055 {
1056 ScriptStringCPtoX(line_def->ssa, (index - 1) - li, TRUE, &x);
1057 x -= es->x_offset;
1058 }
1059 else
1060#ifdef __REACTOS__ /* CORE-15780 */
1061 x = (lw > 0 ? es->x_offset : x - es->x_offset);
1062#else
1063 x = es->x_offset;
1064#endif
1065
1066 if (es->style & ES_RIGHT)
1067 x = w - (lw - x);
1068 else if (es->style & ES_CENTER)
1069 x += (w - lw) / 2;
1070 } else {
1071 INT xoff = 0;
1072 INT xi = 0;
1074 if (es->x_offset)
1075 {
1076 if (es->ssa)
1077 {
1078 if (es->x_offset >= get_text_length(es))
1079 {
1080 int leftover = es->x_offset - get_text_length(es);
1081 if (es->ssa)
1082 {
1083 const SIZE *size;
1084 size = ScriptString_pSize(es->ssa);
1085 xoff = size->cx;
1086 }
1087 else
1088 xoff = 0;
1089 xoff += es->char_width * leftover;
1090 }
1091 else
1092 ScriptStringCPtoX(es->ssa, es->x_offset, FALSE, &xoff);
1093 }
1094 else
1095 xoff = 0;
1096 }
1097 if (index)
1098 {
1099 if (index >= get_text_length(es))
1100 {
1101 if (es->ssa)
1102 {
1103 const SIZE *size;
1104 size = ScriptString_pSize(es->ssa);
1105 xi = size->cx;
1106 }
1107 else
1108 xi = 0;
1109 }
1110 else if (es->ssa)
1111 ScriptStringCPtoX(es->ssa, index, FALSE, &xi);
1112 else
1113 xi = 0;
1114 }
1115 x = xi - xoff;
1116
1117 if (index >= es->x_offset) {
1118 if (!es->x_offset && (es->style & (ES_RIGHT | ES_CENTER)))
1119 {
1120 w = es->format_rect.right - es->format_rect.left;
1121 if (w > es->text_width)
1122 {
1123 if (es->style & ES_RIGHT)
1124 x += w - es->text_width;
1125 else if (es->style & ES_CENTER)
1126 x += (w - es->text_width) / 2;
1127 }
1128 }
1129 }
1130 y = 0;
1131 }
1132 x += es->format_rect.left;
1133 y += es->format_rect.top;
1134 return MAKELONG((INT16)x, (INT16)y);
1135}
1136
1137
1138/*********************************************************************
1139 *
1140 * EDIT_GetLineRect
1141 *
1142 * Calculates the bounding rectangle for a line from a starting
1143 * column to an ending column.
1144 *
1146static void EDIT_GetLineRect(EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc)
1147{
1149 INT line_index = 0;
1150 INT pt1, pt2, pt3;
1151
1152 if (es->style & ES_MULTILINE)
1153 {
1154 const LINEDEF *line_def = NULL;
1155 rc->top = es->format_rect.top + (line - es->y_offset) * es->line_height;
1156 if (line >= es->line_count)
1157 return;
1158
1159 line_def = es->first_line_def;
1160 if (line == -1) {
1161 INT index = es->selection_end - line_def->length;
1162 while ((index >= 0) && line_def->next) {
1163 line_index += line_def->length;
1164 line_def = line_def->next;
1165 index -= line_def->length;
1166 }
1167 } else {
1168 while (line > 0) {
1169 line_index += line_def->length;
1170 line_def = line_def->next;
1171 line--;
1172 }
1173 }
1174 ssa = line_def->ssa;
1175 }
1176 else
1177 {
1178 line_index = 0;
1179 rc->top = es->format_rect.top;
1180 ssa = es->ssa;
1181 }
1182
1183 rc->bottom = rc->top + es->line_height;
1184 pt1 = (scol == 0) ? es->format_rect.left : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + scol, TRUE));
1185 pt2 = (ecol == -1) ? es->format_rect.right : (short)LOWORD(EDIT_EM_PosFromChar(es, line_index + ecol, TRUE));
1186 if (ssa)
1187 {
1188 ScriptStringCPtoX(ssa, scol, FALSE, &pt3);
1189 pt3+=es->format_rect.left;
1190 }
1191 else pt3 = pt1;
1192 rc->right = max(max(pt1 , pt2),pt3);
1193 rc->left = min(min(pt1, pt2),pt3);
1194}
1195
1197static inline void text_buffer_changed(EDITSTATE *es)
1198{
1199 es->text_length = (UINT)-1;
1200
1201 heap_free( es->logAttr );
1202 es->logAttr = NULL;
1204}
1205
1206/*********************************************************************
1207 * EDIT_LockBuffer
1208 *
1210static void EDIT_LockBuffer(EDITSTATE *es)
1211{
1212 if (!es->text)
1213 {
1214 if (!es->hloc32W)
1215 return;
1216
1217 es->text = LocalLock(es->hloc32W);
1218 }
1219
1220 es->lock_count++;
1221}
1222
1223
1224/*********************************************************************
1225 *
1226 * EDIT_UnlockBuffer
1227 *
1229static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force)
1230{
1231 /* Edit window might be already destroyed */
1232 if (!IsWindow(es->hwndSelf))
1233 {
1234 WARN("edit hwnd %p already destroyed\n", es->hwndSelf);
1235 return;
1236 }
1237
1238 if (!es->lock_count)
1239 {
1240 ERR("lock_count == 0 ... please report\n");
1241 return;
1242 }
1243
1244 if (!es->text)
1245 {
1246 ERR("es->text == 0 ... please report\n");
1247 return;
1248 }
1249
1250 if (force || (es->lock_count == 1))
1251 {
1252 if (es->hloc32W)
1253 {
1254 LocalUnlock(es->hloc32W);
1255 es->text = NULL;
1256 }
1257 else
1258 {
1259 ERR("no buffer ... please report\n");
1260 return;
1261 }
1262
1263 }
1264
1265 es->lock_count--;
1266}
1267
1268
1269/*********************************************************************
1270 *
1271 * EDIT_MakeFit
1272 *
1273 * Try to fit size + 1 characters in the buffer.
1276{
1277 HLOCAL hNew32W;
1278
1279 if (size <= es->buffer_size)
1280 return TRUE;
1281
1282 TRACE("trying to ReAlloc to %d+1 characters\n", size);
1283
1284 /* Force edit to unlock its buffer. es->text now NULL */
1286
1287 if (es->hloc32W) {
1288 UINT alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
1289 if ((hNew32W = LocalReAlloc(es->hloc32W, alloc_size, LMEM_MOVEABLE | LMEM_ZEROINIT))) {
1290 TRACE("Old 32 bit handle %p, new handle %p\n", es->hloc32W, hNew32W);
1291 es->hloc32W = hNew32W;
1292 es->buffer_size = LocalSize(hNew32W)/sizeof(WCHAR) - 1;
1293 }
1294 }
1295
1297
1298 if (es->buffer_size < size) {
1299 WARN("FAILED ! We now have %d+1\n", es->buffer_size);
1301 return FALSE;
1302 } else {
1303 TRACE("We now have %d+1\n", es->buffer_size);
1304 return TRUE;
1305 }
1306}
1307
1308
1309/*********************************************************************
1310 *
1311 * EDIT_MakeUndoFit
1312 *
1313 * Try to fit size + 1 bytes in the undo buffer.
1314 *
1317{
1318 UINT alloc_size;
1319
1320 if (size <= es->undo_buffer_size)
1321 return TRUE;
1322
1323 TRACE("trying to ReAlloc to %d+1\n", size);
1324
1325 alloc_size = ROUND_TO_GROW((size + 1) * sizeof(WCHAR));
1326 if ((es->undo_text = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, es->undo_text, alloc_size))) {
1327 es->undo_buffer_size = alloc_size/sizeof(WCHAR) - 1;
1328 return TRUE;
1329 }
1330 else
1331 {
1332 WARN("FAILED ! We now have %d+1\n", es->undo_buffer_size);
1333 return FALSE;
1334 }
1335}
1336
1337
1338/*********************************************************************
1339 *
1340 * EDIT_UpdateTextRegion
1341 *
1343static void EDIT_UpdateTextRegion(EDITSTATE *es, HRGN hrgn, BOOL bErase)
1344{
1345 if (es->flags & EF_UPDATE) {
1346 es->flags &= ~EF_UPDATE;
1347 if (!notify_parent(es, EN_UPDATE)) return;
1348 }
1349 InvalidateRgn(es->hwndSelf, hrgn, bErase);
1350}
1351
1352
1353/*********************************************************************
1354 *
1355 * EDIT_UpdateText
1356 *
1358static void EDIT_UpdateText(EDITSTATE *es, const RECT *rc, BOOL bErase)
1359{
1360 if (es->flags & EF_UPDATE) {
1361 es->flags &= ~EF_UPDATE;
1362 if (!notify_parent(es, EN_UPDATE)) return;
1363 }
1364 InvalidateRect(es->hwndSelf, rc, bErase);
1365}
1366
1367/*********************************************************************
1368 *
1369 * EDIT_SL_InvalidateText
1370 *
1371 * Called from EDIT_InvalidateText().
1372 * Does the job for single-line controls only.
1373 *
1376{
1377 RECT line_rect;
1378 RECT rc;
1379
1380 EDIT_GetLineRect(es, 0, start, end, &line_rect);
1381 if (IntersectRect(&rc, &line_rect, &es->format_rect))
1382 EDIT_UpdateText(es, &rc, TRUE);
1383}
1384
1385/*********************************************************************
1386 *
1387 * EDIT_ML_InvalidateText
1388 *
1389 * Called from EDIT_InvalidateText().
1390 * Does the job for multi-line controls only.
1391 *
1394{
1398 INT sc;
1399 INT ec;
1400 RECT rc1;
1401 RECT rcWnd;
1402 RECT rcLine;
1403 RECT rcUpdate;
1404 INT l;
1405
1406 if ((el < es->y_offset) || (sl > es->y_offset + vlc))
1407 return;
1408
1409 sc = start - EDIT_EM_LineIndex(es, sl);
1410 ec = end - EDIT_EM_LineIndex(es, el);
1411 if (sl < es->y_offset) {
1412 sl = es->y_offset;
1413 sc = 0;
1414 }
1415 if (el > es->y_offset + vlc) {
1416 el = es->y_offset + vlc;
1418 }
1419 GetClientRect(es->hwndSelf, &rc1);
1420 IntersectRect(&rcWnd, &rc1, &es->format_rect);
1421 if (sl == el) {
1422 EDIT_GetLineRect(es, sl, sc, ec, &rcLine);
1423 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
1424 EDIT_UpdateText(es, &rcUpdate, TRUE);
1425 } else {
1426 EDIT_GetLineRect(es, sl, sc,
1428 EDIT_EM_LineIndex(es, sl)),
1429 &rcLine);
1430 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
1431 EDIT_UpdateText(es, &rcUpdate, TRUE);
1432 for (l = sl + 1 ; l < el ; l++) {
1433 EDIT_GetLineRect(es, l, 0,
1436 &rcLine);
1437 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
1438 EDIT_UpdateText(es, &rcUpdate, TRUE);
1439 }
1440 EDIT_GetLineRect(es, el, 0, ec, &rcLine);
1441 if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
1442 EDIT_UpdateText(es, &rcUpdate, TRUE);
1443 }
1444}
1445
1446
1447/*********************************************************************
1448 *
1449 * EDIT_InvalidateText
1450 *
1451 * Invalidate the text from offset start up to, but not including,
1452 * offset end. Useful for (re)painting the selection.
1453 * Regions outside the linewidth are not invalidated.
1454 * end == -1 means end == TextLength.
1455 * start and end need not be ordered.
1456 *
1459{
1460 if (end == start)
1461 return;
1462
1463 if (end == -1)
1465
1466 if (end < start) {
1467 INT tmp = start;
1468 start = end;
1469 end = tmp;
1470 }
1471
1472 if (es->style & ES_MULTILINE)
1474 else
1476}
1477
1478
1479/*********************************************************************
1480 *
1481 * EDIT_EM_SetSel
1482 *
1483 * note: unlike the specs say: the order of start and end
1484 * _is_ preserved in Windows. (i.e. start can be > end)
1485 * In other words: this handler is OK
1486 *
1488static BOOL EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap)
1489{
1490 UINT old_start = es->selection_start;
1491 UINT old_end = es->selection_end;
1493
1494 if (start == old_start && end == old_end)
1495 return FALSE;
1496
1497 if (start == (UINT)-1) {
1498 start = es->selection_end;
1499 end = es->selection_end;
1500 } else {
1501 start = min(start, len);
1502 end = min(end, len);
1503 }
1504 es->selection_start = start;
1505 es->selection_end = end;
1506 if (after_wrap)
1507 es->flags |= EF_AFTER_WRAP;
1508 else
1509 es->flags &= ~EF_AFTER_WRAP;
1510 /* Compute the necessary invalidation region. */
1511 /* Note that we don't need to invalidate regions which have
1512 * "never" been selected, or those which are "still" selected.
1513 * In fact, every time we hit a selection boundary, we can
1514 * *toggle* whether we need to invalidate. Thus we can optimize by
1515 * *sorting* the interval endpoints. Let's assume that we sort them
1516 * in this order:
1517 * start <= end <= old_start <= old_end
1518 * Knuth 5.3.1 (p 183) assures us that this can be done optimally
1519 * in 5 comparisons; i.e. it is impossible to do better than the
1520 * following: */
1521 ORDER_UINT(end, old_end);
1522 ORDER_UINT(start, old_start);
1523 ORDER_UINT(old_start, old_end);
1525 /* Note that at this point 'end' and 'old_start' are not in order, but
1526 * start is definitely the min. and old_end is definitely the max. */
1527 if (end != old_start)
1528 {
1529/*
1530 * One can also do
1531 * ORDER_UINT32(end, old_start);
1532 * EDIT_InvalidateText(es, start, end);
1533 * EDIT_InvalidateText(es, old_start, old_end);
1534 * in place of the following if statement.
1535 * (That would complete the optimal five-comparison four-element sort.)
1536 */
1537 if (old_start > end )
1538 {
1540 EDIT_InvalidateText(es, old_start, old_end);
1541 }
1542 else
1543 {
1544 EDIT_InvalidateText(es, start, old_start);
1545 EDIT_InvalidateText(es, end, old_end);
1546 }
1547 }
1548 else EDIT_InvalidateText(es, start, old_end);
1549
1550 return TRUE;
1551}
1552
1553
1554/*********************************************************************
1555 *
1556 * EDIT_UpdateScrollInfo
1557 *
1560{
1561 if ((es->style & WS_VSCROLL) && !(es->flags & EF_VSCROLL_TRACK))
1562 {
1563 SCROLLINFO si;
1564 si.cbSize = sizeof(SCROLLINFO);
1566 si.nMin = 0;
1567 si.nMax = es->line_count - 1;
1568 si.nPage = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
1569 si.nPos = es->y_offset;
1570 TRACE("SB_VERT, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
1571 si.nMin, si.nMax, si.nPage, si.nPos);
1572 SetScrollInfo(es->hwndSelf, SB_VERT, &si, TRUE);
1573 }
1574
1575 if ((es->style & WS_HSCROLL) && !(es->flags & EF_HSCROLL_TRACK))
1576 {
1577 SCROLLINFO si;
1578 si.cbSize = sizeof(SCROLLINFO);
1580 si.nMin = 0;
1581 si.nMax = es->text_width - 1;
1582 si.nPage = es->format_rect.right - es->format_rect.left;
1583 si.nPos = es->x_offset;
1584 TRACE("SB_HORZ, nMin=%d, nMax=%d, nPage=%d, nPos=%d\n",
1585 si.nMin, si.nMax, si.nPage, si.nPos);
1586 SetScrollInfo(es->hwndSelf, SB_HORZ, &si, TRUE);
1587 }
1588}
1589
1590
1591/*********************************************************************
1592 *
1593 * EDIT_EM_LineScroll_internal
1594 *
1595 * Version of EDIT_EM_LineScroll for internal use.
1596 * It doesn't refuse if ES_MULTILINE is set and assumes that
1597 * dx is in pixels, dy - in lines.
1598 *
1601{
1602 INT nyoff;
1603 INT x_offset_in_pixels;
1604 INT lines_per_page = (es->format_rect.bottom - es->format_rect.top) /
1605 es->line_height;
1606
1607 if (es->style & ES_MULTILINE)
1608 {
1609 x_offset_in_pixels = es->x_offset;
1610 }
1611 else
1612 {
1613 dy = 0;
1614 x_offset_in_pixels = (short)LOWORD(EDIT_EM_PosFromChar(es, es->x_offset, FALSE));
1615 }
1616
1617 if (-dx > x_offset_in_pixels)
1618 dx = -x_offset_in_pixels;
1619 if (dx > es->text_width - x_offset_in_pixels)
1620 dx = es->text_width - x_offset_in_pixels;
1621 nyoff = max(0, es->y_offset + dy);
1622 if (nyoff >= es->line_count - lines_per_page)
1623 nyoff = max(0, es->line_count - lines_per_page);
1624 dy = (es->y_offset - nyoff) * es->line_height;
1625 if (dx || dy) {
1626 RECT rc1;
1627 RECT rc;
1628
1629 es->y_offset = nyoff;
1630 if(es->style & ES_MULTILINE)
1631 es->x_offset += dx;
1632 else
1633 es->x_offset += dx / es->char_width;
1634
1635 GetClientRect(es->hwndSelf, &rc1);
1636 IntersectRect(&rc, &rc1, &es->format_rect);
1637 ScrollWindowEx(es->hwndSelf, -dx, dy,
1638 NULL, &rc, NULL, NULL, SW_INVALIDATE);
1639 /* force scroll info update */
1641 }
1642 if (dx && !(es->flags & EF_HSCROLL_TRACK))
1644 if (dy && !(es->flags & EF_VSCROLL_TRACK))
1646 return TRUE;
1647}
1648
1649/*********************************************************************
1650 *
1651 * EM_LINESCROLL
1652 *
1653 * NOTE: dx is in average character widths, dy - in lines;
1654 *
1657{
1658 if (!(es->style & ES_MULTILINE))
1659 return FALSE;
1660
1661 dx *= es->char_width;
1663}
1664
1665
1666/*********************************************************************
1667 *
1668 * EM_SCROLL
1669 *
1672{
1673 INT dy;
1674
1675 if (!(es->style & ES_MULTILINE))
1676 return (LRESULT)FALSE;
1677
1678 dy = 0;
1679
1680 switch (action) {
1681 case SB_LINEUP:
1682 if (es->y_offset)
1683 dy = -1;
1684 break;
1685 case SB_LINEDOWN:
1686 if (es->y_offset < es->line_count - 1)
1687 dy = 1;
1688 break;
1689 case SB_PAGEUP:
1690 if (es->y_offset)
1691 dy = -(es->format_rect.bottom - es->format_rect.top) / es->line_height;
1692 break;
1693 case SB_PAGEDOWN:
1694 if (es->y_offset < es->line_count - 1)
1695 dy = (es->format_rect.bottom - es->format_rect.top) / es->line_height;
1696 break;
1697 default:
1699 }
1700 if (dy) {
1702 /* check if we are going to move too far */
1703 if(es->y_offset + dy > es->line_count - vlc)
1704 dy = max(es->line_count - vlc, 0) - es->y_offset;
1705
1706 /* Notification is done in EDIT_EM_LineScroll */
1707 if(dy) {
1709 return MAKELONG(dy, TRUE);
1710 }
1711
1712 }
1713 return (LRESULT)FALSE;
1714}
1715
1716
1717#ifdef __REACTOS__
1718static void EDIT_ImmSetCompositionWindow(EDITSTATE *es, POINT pt)
1719{
1720 COMPOSITIONFORM CompForm;
1721 HIMC hIMC = ImmGetContext(es->hwndSelf);
1722 if (!hIMC)
1723 {
1724 ERR("!hIMC\n");
1725 return;
1726 }
1727
1728 CompForm.ptCurrentPos = pt;
1729 if (es->style & ES_MULTILINE)
1730 {
1731 CompForm.dwStyle = CFS_RECT;
1732 CompForm.rcArea = es->format_rect;
1733 }
1734 else
1735 {
1736 CompForm.dwStyle = CFS_POINT;
1737 SetRectEmpty(&CompForm.rcArea);
1738 }
1739
1740 ImmSetCompositionWindow(hIMC, &CompForm);
1741 ImmReleaseContext(es->hwndSelf, hIMC);
1742}
1743#endif
1744/*********************************************************************
1745 *
1746 * EDIT_SetCaretPos
1747 *
1749static void EDIT_SetCaretPos(EDITSTATE *es, INT pos,
1750 BOOL after_wrap)
1751{
1752 LRESULT res = EDIT_EM_PosFromChar(es, pos, after_wrap);
1753#ifdef __REACTOS__
1754 HKL hKL = GetKeyboardLayout(0);
1755 POINT pt = { (short)LOWORD(res), (short)HIWORD(res) };
1756
1757 /* Don't set caret if not focused */
1758 if ((es->flags & EF_FOCUSED) == 0)
1759 return;
1760
1761 SetCaretPos(pt.x, pt.y);
1762
1763 if (!ImmIsIME(hKL))
1764 return;
1765
1766 EDIT_ImmSetCompositionWindow(es, pt);
1767#else
1768 TRACE("%d - %dx%d\n", pos, (short)LOWORD(res), (short)HIWORD(res));
1769 SetCaretPos((short)LOWORD(res), (short)HIWORD(res));
1770#endif
1771}
1772
1773
1774/*********************************************************************
1775 *
1776 * EM_SCROLLCARET
1777 *
1779static void EDIT_EM_ScrollCaret(EDITSTATE *es)
1780{
1781 if (es->style & ES_MULTILINE) {
1782 INT l;
1783 INT vlc;
1784 INT ww;
1785 INT cw = es->char_width;
1786 INT x;
1787 INT dy = 0;
1788 INT dx = 0;
1789
1790 l = EDIT_EM_LineFromChar(es, es->selection_end);
1791 x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP));
1793 if (l >= es->y_offset + vlc)
1794 dy = l - vlc + 1 - es->y_offset;
1795 if (l < es->y_offset)
1796 dy = l - es->y_offset;
1797 ww = es->format_rect.right - es->format_rect.left;
1798 if (x < es->format_rect.left)
1799 dx = x - es->format_rect.left - ww / HSCROLL_FRACTION / cw * cw;
1800 if (x > es->format_rect.right)
1801 dx = x - es->format_rect.left - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
1802 if (dy || dx || (es->y_offset && (es->line_count - es->y_offset < vlc)))
1803 {
1804 /* check if we are going to move too far */
1805 if(es->x_offset + dx + ww > es->text_width)
1806 dx = es->text_width - ww - es->x_offset;
1807 if(dx || dy || (es->y_offset && (es->line_count - es->y_offset < vlc)))
1809 }
1810 } else {
1811 INT x;
1812 INT goal;
1813 INT format_width;
1814
1815 x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
1816 format_width = es->format_rect.right - es->format_rect.left;
1817 if (x < es->format_rect.left) {
1818 goal = es->format_rect.left + format_width / HSCROLL_FRACTION;
1819 do {
1820 es->x_offset--;
1821 x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
1822 } while ((x < goal) && es->x_offset);
1823 /* FIXME: use ScrollWindow() somehow to improve performance */
1825 } else if (x > es->format_rect.right) {
1826 INT x_last;
1828 goal = es->format_rect.right - format_width / HSCROLL_FRACTION;
1829 do {
1830 es->x_offset++;
1831 x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
1833 } while ((x > goal) && (x_last > es->format_rect.right));
1834 /* FIXME: use ScrollWindow() somehow to improve performance */
1836 }
1837 }
1838
1839 if(es->flags & EF_FOCUSED)
1840 EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP);
1841}
1842
1843
1844/*********************************************************************
1845 *
1846 * EDIT_MoveBackward
1847 *
1849static void EDIT_MoveBackward(EDITSTATE *es, BOOL extend)
1850{
1851 INT e = es->selection_end;
1852
1853 if (e) {
1854 e--;
1855 if ((es->style & ES_MULTILINE) && e &&
1856 (es->text[e - 1] == '\r') && (es->text[e] == '\n')) {
1857 e--;
1858 if (e && (es->text[e - 1] == '\r'))
1859 e--;
1860 }
1861 }
1862 EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
1864}
1865
1866
1867/*********************************************************************
1868 *
1869 * EDIT_MoveDown_ML
1870 *
1871 * Only for multi line controls
1872 * Move the caret one line down, on a column with the nearest
1873 * x coordinate on the screen (might be a different column).
1874 *
1876static void EDIT_MoveDown_ML(EDITSTATE *es, BOOL extend)
1877{
1878 INT s = es->selection_start;
1879 INT e = es->selection_end;
1880 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
1881 LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
1882 INT x = (short)LOWORD(pos);
1883 INT y = (short)HIWORD(pos);
1884
1885 e = EDIT_CharFromPos(es, x, y + es->line_height, &after_wrap);
1886 if (!extend)
1887 s = e;
1888 EDIT_EM_SetSel(es, s, e, after_wrap);
1890}
1891
1892
1893/*********************************************************************
1894 *
1895 * EDIT_MoveEnd
1896 *
1898static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend, BOOL ctrl)
1899{
1900 BOOL after_wrap = FALSE;
1901 INT e;
1902
1903 /* Pass a high value in x to make sure of receiving the end of the line */
1904 if (!ctrl && (es->style & ES_MULTILINE))
1905 e = EDIT_CharFromPos(es, 0x3fffffff,
1906 HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap);
1907 else
1908 e = get_text_length(es);
1909 EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, after_wrap);
1911}
1912
1913
1914/*********************************************************************
1915 *
1916 * EDIT_MoveForward
1917 *
1919static void EDIT_MoveForward(EDITSTATE *es, BOOL extend)
1920{
1921 INT e = es->selection_end;
1922
1923 if (es->text[e]) {
1924 e++;
1925 if ((es->style & ES_MULTILINE) && (es->text[e - 1] == '\r')) {
1926 if (es->text[e] == '\n')
1927 e++;
1928 else if ((es->text[e] == '\r') && (es->text[e + 1] == '\n'))
1929 e += 2;
1930 }
1931 }
1932 EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
1934}
1935
1936
1937/*********************************************************************
1938 *
1939 * EDIT_MoveHome
1940 *
1941 * Home key: move to beginning of line.
1942 *
1944static void EDIT_MoveHome(EDITSTATE *es, BOOL extend, BOOL ctrl)
1945{
1946 INT e;
1947
1948 /* Pass the x_offset in x to make sure of receiving the first position of the line */
1949 if (!ctrl && (es->style & ES_MULTILINE))
1950 e = EDIT_CharFromPos(es, -es->x_offset,
1951 HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), NULL);
1952 else
1953 e = 0;
1954 EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
1956}
1957
1958
1959/*********************************************************************
1960 *
1961 * EDIT_MovePageDown_ML
1962 *
1963 * Only for multi line controls
1964 * Move the caret one page down, on a column with the nearest
1965 * x coordinate on the screen (might be a different column).
1966 *
1968static void EDIT_MovePageDown_ML(EDITSTATE *es, BOOL extend)
1969{
1970 INT s = es->selection_start;
1971 INT e = es->selection_end;
1972 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
1973 LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
1974 INT x = (short)LOWORD(pos);
1975 INT y = (short)HIWORD(pos);
1976
1978 y + (es->format_rect.bottom - es->format_rect.top),
1979 &after_wrap);
1980 if (!extend)
1981 s = e;
1982 EDIT_EM_SetSel(es, s, e, after_wrap);
1984}
1985
1986
1987/*********************************************************************
1988 *
1989 * EDIT_MovePageUp_ML
1990 *
1991 * Only for multi line controls
1992 * Move the caret one page up, on a column with the nearest
1993 * x coordinate on the screen (might be a different column).
1994 *
1996static void EDIT_MovePageUp_ML(EDITSTATE *es, BOOL extend)
1997{
1998 INT s = es->selection_start;
1999 INT e = es->selection_end;
2000 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
2001 LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
2002 INT x = (short)LOWORD(pos);
2003 INT y = (short)HIWORD(pos);
2004
2006 y - (es->format_rect.bottom - es->format_rect.top),
2007 &after_wrap);
2008 if (!extend)
2009 s = e;
2010 EDIT_EM_SetSel(es, s, e, after_wrap);
2012}
2013
2014
2015/*********************************************************************
2016 *
2017 * EDIT_MoveUp_ML
2018 *
2019 * Only for multi line controls
2020 * Move the caret one line up, on a column with the nearest
2021 * x coordinate on the screen (might be a different column).
2022 *
2024static void EDIT_MoveUp_ML(EDITSTATE *es, BOOL extend)
2025{
2026 INT s = es->selection_start;
2027 INT e = es->selection_end;
2028 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
2029 LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
2030 INT x = (short)LOWORD(pos);
2031 INT y = (short)HIWORD(pos);
2032
2033 e = EDIT_CharFromPos(es, x, y - es->line_height, &after_wrap);
2034 if (!extend)
2035 s = e;
2036 EDIT_EM_SetSel(es, s, e, after_wrap);
2038}
2039
2040
2041/*********************************************************************
2042 *
2043 * EDIT_MoveWordBackward
2044 *
2046static void EDIT_MoveWordBackward(EDITSTATE *es, BOOL extend)
2047{
2048 INT s = es->selection_start;
2049 INT e = es->selection_end;
2050 INT l;
2051 INT ll;
2052 INT li;
2053
2057 if (e - li == 0) {
2058 if (l) {
2059 li = EDIT_EM_LineIndex(es, l - 1);
2060 e = li + EDIT_EM_LineLength(es, li);
2061 }
2062 } else {
2064 }
2065 if (!extend)
2066 s = e;
2069}
2070
2071
2072/*********************************************************************
2073 *
2074 * EDIT_MoveWordForward
2075 *
2077static void EDIT_MoveWordForward(EDITSTATE *es, BOOL extend)
2078{
2079 INT s = es->selection_start;
2080 INT e = es->selection_end;
2081 INT l;
2082 INT ll;
2083 INT li;
2084
2088 if (e - li == ll) {
2089 if ((es->style & ES_MULTILINE) && (l != es->line_count - 1))
2090 e = EDIT_EM_LineIndex(es, l + 1);
2091 } else {
2093 li, e - li + 1, ll, WB_RIGHT);
2094 }
2095 if (!extend)
2096 s = e;
2099}
2100
2101
2102/*********************************************************************
2103 *
2104 * EDIT_PaintText
2105 *
2108{
2109 COLORREF BkColor;
2110 COLORREF TextColor;
2111 LOGFONTW underline_font;
2112 HFONT hUnderline = 0;
2113 HFONT old_font = 0;
2114 INT ret;
2115 INT li;
2116 INT BkMode;
2117 SIZE size;
2118
2119 if (!count)
2120 return 0;
2121 BkMode = GetBkMode(dc);
2122 BkColor = GetBkColor(dc);
2123 TextColor = GetTextColor(dc);
2124 if (rev) {
2125#ifdef __REACTOS__
2126 if (TRUE)
2127#else
2128 if (es->composition_len == 0)
2129#endif
2130 {
2133 SetBkMode( dc, OPAQUE);
2134 }
2135 else
2136 {
2138 GetObjectW(current,sizeof(LOGFONTW),&underline_font);
2139 underline_font.lfUnderline = TRUE;
2140 hUnderline = CreateFontIndirectW(&underline_font);
2141 old_font = SelectObject(dc,hUnderline);
2142 }
2143 }
2145 if (es->style & ES_MULTILINE) {
2146 ret = (INT)LOWORD(TabbedTextOutW(dc, x, y, es->text + li + col, count,
2147 es->tabs_count, es->tabs, es->format_rect.left - es->x_offset));
2148 } else {
2149 TextOutW(dc, x, y, es->text + li + col, count);
2150 GetTextExtentPoint32W(dc, es->text + li + col, count, &size);
2151 ret = size.cx;
2152 }
2153 if (rev) {
2154#ifdef __REACTOS__
2155 if (TRUE)
2156#else
2157 if (es->composition_len == 0)
2158#endif
2159 {
2160 SetBkColor(dc, BkColor);
2161 SetTextColor(dc, TextColor);
2162 SetBkMode( dc, BkMode);
2163 }
2164 else
2165 {
2166 if (old_font)
2167 SelectObject(dc,old_font);
2168 if (hUnderline)
2169 DeleteObject(hUnderline);
2170 }
2171 }
2172 return ret;
2173}
2174
2175
2176/*********************************************************************
2177 *
2178 * EDIT_PaintLine
2179 *
2181static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
2182{
2183 INT s = 0;
2184 INT e = 0;
2185 INT li = 0;
2186 INT ll = 0;
2187 INT x;
2188 INT y;
2189 LRESULT pos;
2191
2192 if (es->style & ES_MULTILINE) {
2194
2195 if ((line < es->y_offset) || (line > es->y_offset + vlc) || (line >= es->line_count))
2196 return;
2197 } else if (line)
2198 return;
2199
2200 TRACE("line=%d\n", line);
2201
2204 x = (short)LOWORD(pos);
2205 y = (short)HIWORD(pos);
2206
2207 if (es->style & ES_MULTILINE)
2208 {
2209 int line_idx = line;
2210 x = -es->x_offset;
2211 if (es->style & ES_RIGHT || es->style & ES_CENTER)
2212 {
2213 LINEDEF *line_def = es->first_line_def;
2214 int w, lw;
2215
2216 while (line_def && line_idx)
2217 {
2218 line_def = line_def->next;
2219 line_idx--;
2220 }
2221 w = es->format_rect.right - es->format_rect.left;
2222 lw = line_def->width;
2223
2224 if (es->style & ES_RIGHT)
2225 x = w - (lw - x);
2226 else if (es->style & ES_CENTER)
2227 x += (w - lw) / 2;
2228 }
2229 x += es->format_rect.left;
2230 }
2231
2232 if (rev)
2233 {
2236 s = min(es->selection_start, es->selection_end);
2237 e = max(es->selection_start, es->selection_end);
2238 s = min(li + ll, max(li, s));
2239 e = min(li + ll, max(li, e));
2240 }
2241
2242 if (ssa)
2243 ScriptStringOut(ssa, x, y, 0, &es->format_rect, s - li, e - li, FALSE);
2244 else if (rev && (s != e) &&
2245 ((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL))) {
2246 x += EDIT_PaintText(es, dc, x, y, line, 0, s - li, FALSE);
2247 x += EDIT_PaintText(es, dc, x, y, line, s - li, e - s, TRUE);
2248 x += EDIT_PaintText(es, dc, x, y, line, e - li, li + ll - e, FALSE);
2249 } else
2250 x += EDIT_PaintText(es, dc, x, y, line, 0, ll, FALSE);
2251}
2252
2253
2254/*********************************************************************
2255 *
2256 * EDIT_AdjustFormatRect
2257 *
2258 * Adjusts the format rectangle for the current font and the
2259 * current client rectangle.
2260 *
2263{
2264 RECT ClientRect;
2265
2266 es->format_rect.right = max(es->format_rect.right, es->format_rect.left + es->char_width);
2267 if (es->style & ES_MULTILINE)
2268 {
2269 INT fw, vlc, max_x_offset, max_y_offset;
2270
2272 es->format_rect.bottom = es->format_rect.top + vlc * es->line_height;
2273
2274 /* correct es->x_offset */
2275 fw = es->format_rect.right - es->format_rect.left;
2276 max_x_offset = es->text_width - fw;
2277 if(max_x_offset < 0) max_x_offset = 0;
2278 if(es->x_offset > max_x_offset)
2279 es->x_offset = max_x_offset;
2280
2281 /* correct es->y_offset */
2282 max_y_offset = es->line_count - vlc;
2283 if(max_y_offset < 0) max_y_offset = 0;
2284 if(es->y_offset > max_y_offset)
2285 es->y_offset = max_y_offset;
2286
2287 /* force scroll info update */
2289 }
2290 else
2291 /* Windows doesn't care to fix text placement for SL controls */
2292 es->format_rect.bottom = es->format_rect.top + es->line_height;
2293
2294 /* Always stay within the client area */
2295 GetClientRect(es->hwndSelf, &ClientRect);
2296 es->format_rect.bottom = min(es->format_rect.bottom, ClientRect.bottom);
2297
2298 if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL))
2300
2301 EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP);
2302}
2303
2304
2305/*********************************************************************
2306 *
2307 * EDIT_SetRectNP
2308 *
2309 * note: this is not (exactly) the handler called on EM_SETRECTNP
2310 * it is also used to set the rect of a single line control
2311 *
2313static void EDIT_SetRectNP(EDITSTATE *es, const RECT *rc)
2314{
2316 INT bw, bh;
2318
2319 CopyRect(&es->format_rect, rc);
2320
2321 if (ExStyle & WS_EX_CLIENTEDGE) {
2322 es->format_rect.left++;
2323 es->format_rect.right--;
2324
2325 if (es->format_rect.bottom - es->format_rect.top
2326 >= es->line_height + 2)
2327 {
2328 es->format_rect.top++;
2329 es->format_rect.bottom--;
2330 }
2331 }
2332 else if (es->style & WS_BORDER) {
2334 bh = GetSystemMetrics(SM_CYBORDER) + 1;
2335 InflateRect(&es->format_rect, -bw, 0);
2336 if (es->format_rect.bottom - es->format_rect.top >= es->line_height + 2 * bh)
2337 InflateRect(&es->format_rect, 0, -bh);
2338 }
2339
2340 es->format_rect.left += es->left_margin;
2341 es->format_rect.right -= es->right_margin;
2343}
2344
2345
2346/*********************************************************************
2347 *
2348 * EM_CHARFROMPOS
2349 *
2350 * returns line number (not index) in high-order word of result.
2351 * NB : Q137805 is unclear about this. POINT * pointer in lParam apply
2352 * to Richedit, not to the edit control. Original documentation is valid.
2353 * FIXME: do the specs mean to return -1 if outside client area or
2354 * if outside formatting rectangle ???
2355 *
2358{
2359 POINT pt;
2360 RECT rc;
2361 INT index;
2362
2363 pt.x = x;
2364 pt.y = y;
2365 GetClientRect(es->hwndSelf, &rc);
2366 if (!PtInRect(&rc, pt))
2367 return -1;
2368
2371}
2372
2373
2374/*********************************************************************
2375 *
2376 * EM_FMTLINES
2377 *
2378 * Enable or disable soft breaks.
2379 *
2380 * This means: insert or remove the soft linebreak character (\r\r\n).
2381 * Take care to check if the text still fits the buffer after insertion.
2382 * If not, notify with EN_ERRSPACE.
2383 *
2385static BOOL EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol)
2386{
2387 es->flags &= ~EF_USE_SOFTBRK;
2388 if (add_eol) {
2389 es->flags |= EF_USE_SOFTBRK;
2390 FIXME("soft break enabled, not implemented\n");
2391 }
2392 return add_eol;
2393}
2394
2395
2396/*********************************************************************
2397 *
2398 * EM_GETHANDLE
2399 *
2400 * Hopefully this won't fire back at us.
2401 * We always start with a fixed buffer in the local heap.
2402 * Despite of the documentation says that the local heap is used
2403 * only if DS_LOCALEDIT flag is set, NT and 2000 always allocate
2404 * buffer on the local heap.
2405 *
2408{
2409 if (!(es->style & ES_MULTILINE))
2410 return 0;
2411
2413
2414 /* The text buffer handle belongs to the app */
2415 es->hlocapp = es->hloc32W;
2416
2417 TRACE("Returning %p, LocalSize() = %ld\n", es->hlocapp, LocalSize(es->hlocapp));
2418 return es->hlocapp;
2419}
2420
2421
2422/*********************************************************************
2423 *
2424 * EM_GETLINE
2425 *
2428{
2429 INT line_len, dst_len;
2430 LPWSTR src;
2431 INT i;
2432
2433 if (es->style & ES_MULTILINE)
2434 {
2435 if (line >= es->line_count)
2436 return 0;
2437 }
2438 else
2439 line = 0;
2440
2442 src = es->text + i;
2443 line_len = EDIT_EM_LineLength(es, i);
2444 dst_len = *(WORD *)dst;
2445
2446 if (dst_len <= line_len)
2447 {
2448 memcpy(dst, src, dst_len * sizeof(WCHAR));
2449 return dst_len;
2450 }
2451 else /* Append 0 if enough space */
2452 {
2453 memcpy(dst, src, line_len * sizeof(WCHAR));
2454 dst[line_len] = 0;
2455 return line_len;
2456 }
2457}
2458
2459
2460/*********************************************************************
2461 *
2462 * EM_GETSEL
2463 *
2466{
2467 UINT s = es->selection_start;
2468 UINT e = es->selection_end;
2469
2470 ORDER_UINT(s, e);
2471 if (start)
2472 *start = s;
2473 if (end)
2474 *end = e;
2475 return MAKELONG(s, e);
2476}
2477
2478
2479/*********************************************************************
2480 *
2481 * EM_REPLACESEL
2482 *
2483 * FIXME: handle ES_NUMBER and ES_OEMCONVERT here
2484 *
2486static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, const WCHAR *lpsz_replace, UINT strl,
2487 BOOL send_update, BOOL honor_limit)
2488{
2489 UINT tl = get_text_length(es);
2490 UINT utl;
2491 UINT s;
2492 UINT e;
2493 UINT i;
2494 UINT size;
2495 LPWSTR p;
2496 HRGN hrgn = 0;
2497 LPWSTR buf = NULL;
2498 UINT bufl;
2499
2500 TRACE("%s, can_undo %d, send_update %d\n",
2501 debugstr_wn(lpsz_replace, strl), can_undo, send_update);
2502
2503 s = es->selection_start;
2504 e = es->selection_end;
2505
2507 if ((s == e) && !strl)
2508 return;
2509
2510 ORDER_UINT(s, e);
2511
2512 size = tl - (e - s) + strl;
2513 if (!size)
2514 es->text_width = 0;
2515
2516 /* Issue the EN_MAXTEXT notification and continue with replacing text
2517 * so that buffer limit is honored. */
2518 if ((honor_limit) && (size > es->buffer_limit))
2519 {
2520 if (!notify_parent(es, EN_MAXTEXT)) return;
2521 /* Buffer limit can be smaller than the actual length of text in combobox */
2522 if (es->buffer_limit < (tl - (e-s)))
2523 strl = 0;
2524 else
2525 strl = min(strl, es->buffer_limit - (tl - (e-s)));
2526 }
2527
2528 if (!EDIT_MakeFit(es, tl - (e - s) + strl))
2529 return;
2530
2531 if (e != s) {
2532 /* there is something to be deleted */
2533 TRACE("deleting stuff.\n");
2534 bufl = e - s;
2535 buf = heap_alloc((bufl + 1) * sizeof(WCHAR));
2536 if (!buf) return;
2537 memcpy(buf, es->text + s, bufl * sizeof(WCHAR));
2538 buf[bufl] = 0; /* ensure 0 termination */
2539 /* now delete */
2540 strcpyW(es->text + s, es->text + e);
2542 }
2543 if (strl) {
2544 /* there is an insertion */
2545 tl = get_text_length(es);
2546 TRACE("inserting stuff (tl %d, strl %d, selstart %d (%s), text %s)\n", tl, strl, s, debugstr_w(es->text + s), debugstr_w(es->text));
2547 for (p = es->text + tl ; p >= es->text + s ; p--)
2548 p[strl] = p[0];
2549 for (i = 0 , p = es->text + s ; i < strl ; i++)
2550 p[i] = lpsz_replace[i];
2551 if(es->style & ES_UPPERCASE)
2552 CharUpperBuffW(p, strl);
2553 else if(es->style & ES_LOWERCASE)
2554 CharLowerBuffW(p, strl);
2556 }
2557 if (es->style & ES_MULTILINE)
2558 {
2559 INT st = min(es->selection_start, es->selection_end);
2561
2562 hrgn = CreateRectRgn(0, 0, 0, 0);
2563 EDIT_BuildLineDefs_ML(es, st, st + strl,
2564 strl - abs(es->selection_end - es->selection_start), hrgn);
2565 /* if text is too long undo all changes */
2566 if (honor_limit && !(es->style & ES_AUTOVSCROLL) && (es->line_count > vlc)) {
2567 if (strl)
2568 strcpyW(es->text + e, es->text + e + strl);
2569 if (e != s)
2570 for (i = 0 , p = es->text ; i < e - s ; i++)
2571 p[i + s] = buf[i];
2574 abs(es->selection_end - es->selection_start) - strl, hrgn);
2575 strl = 0;
2576 e = s;
2577 SetRectRgn(hrgn, 0, 0, 0, 0);
2578 if (!notify_parent(es, EN_MAXTEXT)) return;
2579 }
2580 }
2581 else {
2582 INT fw = es->format_rect.right - es->format_rect.left;
2585 /* remove chars that don't fit */
2586 if (honor_limit && !(es->style & ES_AUTOHSCROLL) && (es->text_width > fw)) {
2587 while ((es->text_width > fw) && s + strl >= s) {
2588 strcpyW(es->text + s + strl - 1, es->text + s + strl);
2589 strl--;
2590 es->text_length = -1;
2593 }
2595 if (!notify_parent(es, EN_MAXTEXT)) return;
2596 }
2597 }
2598
2599 if (e != s) {
2600 if (can_undo) {
2601 utl = strlenW(es->undo_text);
2602 if (!es->undo_insert_count && (*es->undo_text && (s == es->undo_position))) {
2603 /* undo-buffer is extended to the right */
2604 EDIT_MakeUndoFit(es, utl + e - s);
2605 memcpy(es->undo_text + utl, buf, (e - s)*sizeof(WCHAR));
2606 (es->undo_text + utl)[e - s] = 0; /* ensure 0 termination */
2607 } else if (!es->undo_insert_count && (*es->undo_text && (e == es->undo_position))) {
2608 /* undo-buffer is extended to the left */
2609 EDIT_MakeUndoFit(es, utl + e - s);
2610 for (p = es->undo_text + utl ; p >= es->undo_text ; p--)
2611 p[e - s] = p[0];
2612 for (i = 0 , p = es->undo_text ; i < e - s ; i++)
2613 p[i] = buf[i];
2614 es->undo_position = s;
2615 } else {
2616 /* new undo-buffer */
2617 EDIT_MakeUndoFit(es, e - s);
2618 memcpy(es->undo_text, buf, (e - s)*sizeof(WCHAR));
2619 es->undo_text[e - s] = 0; /* ensure 0 termination */
2620 es->undo_position = s;
2621 }
2622 /* any deletion makes the old insertion-undo invalid */
2623 es->undo_insert_count = 0;
2624 } else
2626 }
2627 if (strl) {
2628 if (can_undo) {
2629 if ((s == es->undo_position) ||
2630 ((es->undo_insert_count) &&
2631 (s == es->undo_position + es->undo_insert_count)))
2632 /*
2633 * insertion is new and at delete position or
2634 * an extension to either left or right
2635 */
2636 es->undo_insert_count += strl;
2637 else {
2638 /* new insertion undo */
2639 es->undo_position = s;
2640 es->undo_insert_count = strl;
2641 /* new insertion makes old delete-buffer invalid */
2642 *es->undo_text = '\0';
2643 }
2644 } else
2646 }
2647
2648 heap_free(buf);
2649
2650 s += strl;
2651
2652 /* If text has been deleted and we're right or center aligned then scroll rightward */
2653 if (es->style & (ES_RIGHT | ES_CENTER))
2654 {
2655 INT delta = strl - abs(es->selection_end - es->selection_start);
2656
2657 if (delta < 0 && es->x_offset)
2658 {
2659 if (abs(delta) > es->x_offset)
2660 es->x_offset = 0;
2661 else
2662 es->x_offset += delta;
2663 }
2664 }
2665
2667 es->flags |= EF_MODIFIED;
2668 if (send_update) es->flags |= EF_UPDATE;
2669 if (hrgn)
2670 {
2673 }
2674 else
2676
2678
2679 /* force scroll info update */
2681
2682
2683 if(send_update || (es->flags & EF_UPDATE))
2684 {
2685 es->flags &= ~EF_UPDATE;
2686 if (!notify_parent(es, EN_CHANGE)) return;
2687 }
2689}
2690
2691
2692/*********************************************************************
2693 *
2694 * EM_SETHANDLE
2695 *
2696 * FIXME: ES_LOWERCASE, ES_UPPERCASE, ES_OEMCONVERT, ES_NUMBER ???
2697 *
2699static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc)
2700{
2701 if (!(es->style & ES_MULTILINE))
2702 return;
2703
2704 if (!hloc)
2705 return;
2706
2708
2709 es->hloc32W = hloc;
2710 es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
2711
2712 /* The text buffer handle belongs to the control */
2713 es->hlocapp = NULL;
2714
2717
2718 es->x_offset = es->y_offset = 0;
2719 es->selection_start = es->selection_end = 0;
2721 es->flags &= ~EF_MODIFIED;
2722 es->flags &= ~EF_UPDATE;
2726 /* force scroll info update */
2728}
2729
2730
2731/*********************************************************************
2732 *
2733 * EM_SETLIMITTEXT
2734 *
2735 * NOTE: this version currently implements WinNT limits
2736 *
2739{
2740 if (!limit) limit = ~0u;
2741 if (!(es->style & ES_MULTILINE)) limit = min(limit, 0x7ffffffe);
2742 es->buffer_limit = limit;
2743}
2744
2745
2746/*********************************************************************
2747 *
2748 * EM_SETMARGINS
2749 *
2750 * EC_USEFONTINFO is used as a left or right value i.e. lParam and not as an
2751 * action wParam despite what the docs say. EC_USEFONTINFO calculates the
2752 * margin according to the textmetrics of the current font.
2753 *
2754 * When EC_USEFONTINFO is used in the non_cjk case the margins only
2755 * change if the edit control is equal to or larger than a certain
2756 * size. Though there is an exception for the empty client rect case
2757 * with small font sizes.
2759static BOOL is_cjk(UINT charset)
2760{
2761 switch(charset)
2762 {
2763 case SHIFTJIS_CHARSET:
2764 case HANGUL_CHARSET:
2765 case GB2312_CHARSET:
2767 return TRUE;
2768 }
2769 /* HANGUL_CHARSET is strange, though treated as CJK by Win 8, it is
2770 * not by other versions including Win 10. */
2771 return FALSE;
2772}
2775 WORD left, WORD right, BOOL repaint)
2776{
2778 INT default_left_margin = 0; /* in pixels */
2779 INT default_right_margin = 0; /* in pixels */
2780
2781 /* Set the default margins depending on the font */
2782 if (es->font && (left == EC_USEFONTINFO || right == EC_USEFONTINFO)) {
2783 HDC dc = GetDC(es->hwndSelf);
2784 HFONT old_font = SelectObject(dc, es->font);
2786 RECT rc;
2787
2788 /* The default margins are only non zero for TrueType or Vector fonts */
2789 if (tm.tmPitchAndFamily & ( TMPF_VECTOR | TMPF_TRUETYPE )) {
2790 if (!is_cjk(tm.tmCharSet)) {
2791 default_left_margin = width / 2;
2792 default_right_margin = width / 2;
2793
2794 GetClientRect(es->hwndSelf, &rc);
2795 if (rc.right - rc.left < (width / 2 + width) * 2 &&
2796 (width >= 28 || !IsRectEmpty(&rc)) ) {
2797 default_left_margin = es->left_margin;
2798 default_right_margin = es->right_margin;
2799 }
2800 } else {
2801 /* FIXME: figure out the CJK values. They are not affected by the client rect. */
2802 default_left_margin = width / 2;
2803 default_right_margin = width / 2;
2804 }
2805 }
2806 SelectObject(dc, old_font);
2807 ReleaseDC(es->hwndSelf, dc);
2808 }
2809
2810 if (action & EC_LEFTMARGIN) {
2811 es->format_rect.left -= es->left_margin;
2812 if (left != EC_USEFONTINFO)
2813 es->left_margin = left;
2814 else
2815 es->left_margin = default_left_margin;
2816 es->format_rect.left += es->left_margin;
2817 }
2818
2819 if (action & EC_RIGHTMARGIN) {
2820 es->format_rect.right += es->right_margin;
2821 if (right != EC_USEFONTINFO)
2822 es->right_margin = right;
2823 else
2824 es->right_margin = default_right_margin;
2825 es->format_rect.right -= es->right_margin;
2826 }
2827
2830 if (repaint) EDIT_UpdateText(es, NULL, TRUE);
2831 }
2832
2833 TRACE("left=%d, right=%d\n", es->left_margin, es->right_margin);
2834}
2835
2836
2837/*********************************************************************
2838 *
2839 * EM_SETPASSWORDCHAR
2840 *
2843{
2844 LONG style;
2845
2846 if (es->style & ES_MULTILINE)
2847 return;
2848
2849 if (es->password_char == c)
2850 return;
2851
2852 style = GetWindowLongW( es->hwndSelf, GWL_STYLE );
2853 es->password_char = c;
2854 if (c) {
2855 SetWindowLongW( es->hwndSelf, GWL_STYLE, style | ES_PASSWORD );
2856 es->style |= ES_PASSWORD;
2857 } else {
2858 SetWindowLongW( es->hwndSelf, GWL_STYLE, style & ~ES_PASSWORD );
2859 es->style &= ~ES_PASSWORD;
2860 }
2863}
2864
2865
2866/*********************************************************************
2867 *
2868 * EM_SETTABSTOPS
2869 *
2871static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, const INT *tabs)
2872{
2873 if (!(es->style & ES_MULTILINE))
2874 return FALSE;
2875 heap_free(es->tabs);
2876 es->tabs_count = count;
2877 if (!count)
2878 es->tabs = NULL;
2879 else {
2880 es->tabs = heap_alloc(count * sizeof(INT));
2881 memcpy(es->tabs, tabs, count * sizeof(INT));
2882 }
2884 return TRUE;
2885}
2886
2887
2888/*********************************************************************
2889 *
2890 * EM_SETWORDBREAKPROC
2891 *
2894{
2895 if (es->word_break_proc == wbp)
2896 return;
2897
2898 es->word_break_proc = wbp;
2899
2900 if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
2903 }
2904}
2905
2906
2907/*********************************************************************
2908 *
2909 * EM_UNDO / WM_UNDO
2910 *
2913{
2914 INT ulength;
2915 LPWSTR utext;
2916
2917 /* As per MSDN spec, for a single-line edit control,
2918 the return value is always TRUE */
2919 if( es->style & ES_READONLY )
2920 return !(es->style & ES_MULTILINE);
2921
2922 ulength = strlenW(es->undo_text);
2923
2924 utext = heap_alloc((ulength + 1) * sizeof(WCHAR));
2925
2926 strcpyW(utext, es->undo_text);
2927
2928 TRACE("before UNDO:insertion length = %d, deletion buffer = %s\n",
2929 es->undo_insert_count, debugstr_w(utext));
2930
2931 EDIT_EM_SetSel(es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
2933 EDIT_EM_ReplaceSel(es, TRUE, utext, ulength, TRUE, TRUE);
2934 EDIT_EM_SetSel(es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
2935 /* send the notification after the selection start and end are set */
2936 if (!notify_parent(es, EN_CHANGE)) return TRUE;
2938 heap_free(utext);
2939
2940 TRACE("after UNDO:insertion length = %d, deletion buffer = %s\n",
2941 es->undo_insert_count, debugstr_w(es->undo_text));
2942 return TRUE;
2943}
2944
2945
2946/* Helper function for WM_CHAR
2947 *
2948 * According to an MSDN blog article titled "Just because you're a control
2949 * doesn't mean that you're necessarily inside a dialog box," multiline edit
2950 * controls without ES_WANTRETURN would attempt to detect whether it is inside
2951 * a dialog box or not.
2953static inline BOOL EDIT_IsInsideDialog(EDITSTATE *es)
2954{
2955 return (es->flags & EF_DIALOGMODE);
2956}
2957
2958
2959/*********************************************************************
2960 *
2961 * WM_PASTE
2962 *
2964static void EDIT_WM_Paste(EDITSTATE *es)
2965{
2966 HGLOBAL hsrc;
2967 LPWSTR src, ptr;
2968 int len;
2969
2970 /* Protect read-only edit control from modification */
2971 if(es->style & ES_READONLY)
2972 return;
2973
2974 OpenClipboard(es->hwndSelf);
2975 if ((hsrc = GetClipboardData(CF_UNICODETEXT))) {
2976 src = GlobalLock(hsrc);
2977 len = strlenW(src);
2978 /* Protect single-line edit against pasting new line character */
2979 if (!(es->style & ES_MULTILINE) && ((ptr = strchrW(src, '\n')))) {
2980 len = ptr - src;
2981 if (len && src[len - 1] == '\r')
2982 --len;
2983 }
2985 GlobalUnlock(hsrc);
2986 }
2987 else if (es->style & ES_PASSWORD) {
2988 /* clear selected text in password edit box even with empty clipboard */
2990 }
2992}
2993
2994
2995/*********************************************************************
2996 *
2997 * WM_COPY
2998 *
3000static void EDIT_WM_Copy(EDITSTATE *es)
3001{
3002 INT s = min(es->selection_start, es->selection_end);
3003 INT e = max(es->selection_start, es->selection_end);
3004 HGLOBAL hdst;
3005 LPWSTR dst;
3006 DWORD len;
3007
3008 if (e == s) return;
3009
3010 len = e - s;
3011 hdst = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (len + 1) * sizeof(WCHAR));
3012 dst = GlobalLock(hdst);
3013 memcpy(dst, es->text + s, len * sizeof(WCHAR));
3014 dst[len] = 0; /* ensure 0 termination */
3015 TRACE("%s\n", debugstr_w(dst));
3016 GlobalUnlock(hdst);
3017 OpenClipboard(es->hwndSelf);
3021}
3022
3023
3024/*********************************************************************
3025 *
3026 * WM_CLEAR
3027 *
3029static inline void EDIT_WM_Clear(EDITSTATE *es)
3030{
3031 /* Protect read-only edit control from modification */
3032 if(es->style & ES_READONLY)
3033 return;
3034
3036}
3037
3038
3039/*********************************************************************
3040 *
3041 * WM_CUT
3042 *
3044static inline void EDIT_WM_Cut(EDITSTATE *es)
3045{
3048}
3049
3050
3051/*********************************************************************
3052 *
3053 * WM_CHAR
3054 *
3057{
3058 BOOL control;
3059
3060#ifdef __REACTOS__
3061 if (es->bCaptureState)
3062 return 0;
3063#endif
3064
3065 control = GetKeyState(VK_CONTROL) & 0x8000;
3066
3067 switch (c) {
3068 case '\r':
3069 /* If it's not a multiline edit box, it would be ignored below.
3070 * For multiline edit without ES_WANTRETURN, we have to make a
3071 * special case.
3072 */
3073 if ((es->style & ES_MULTILINE) && !(es->style & ES_WANTRETURN))
3075 break;
3076 case '\n':
3077 if (es->style & ES_MULTILINE) {
3078 if (es->style & ES_READONLY) {
3081 } else {
3082 static const WCHAR cr_lfW[] = {'\r','\n'};
3083 EDIT_EM_ReplaceSel(es, TRUE, cr_lfW, 2, TRUE, TRUE);
3084 }
3085 }
3086 break;
3087 case '\t':
3088 if ((es->style & ES_MULTILINE) && !(es->style & ES_READONLY))
3089 {
3090 static const WCHAR tabW[] = {'\t'};
3092 break;
3093 EDIT_EM_ReplaceSel(es, TRUE, tabW, 1, TRUE, TRUE);
3094 }
3095 break;
3096 case VK_BACK:
3097 if (!(es->style & ES_READONLY) && !control) {
3098 if (es->selection_start != es->selection_end)
3100 else {
3101 /* delete character left of caret */
3102 EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
3105 }
3106 }
3107 break;
3108 case 0x03: /* ^C */
3109 if (!(es->style & ES_PASSWORD))
3110 SendMessageW(es->hwndSelf, WM_COPY, 0, 0);
3111 break;
3112 case 0x16: /* ^V */
3113 if (!(es->style & ES_READONLY))
3114 SendMessageW(es->hwndSelf, WM_PASTE, 0, 0);
3115 break;
3116 case 0x18: /* ^X */
3117 if (!((es->style & ES_READONLY) || (es->style & ES_PASSWORD)))
3118 SendMessageW(es->hwndSelf, WM_CUT, 0, 0);
3119 break;
3120 case 0x1A: /* ^Z */
3121 if (!(es->style & ES_READONLY))
3122 SendMessageW(es->hwndSelf, WM_UNDO, 0, 0);
3123 break;
3124
3125 default:
3126 /*If Edit control style is ES_NUMBER allow users to key in only numeric values*/
3127 if( (es->style & ES_NUMBER) && !( c >= '0' && c <= '9') )
3128 break;
3129
3130 if (!(es->style & ES_READONLY) && (c >= ' ') && (c != 127))
3132 break;
3133 }
3134 return 1;
3135}
3136
3137
3138/*********************************************************************
3139 *
3140 * EDIT_ContextMenuCommand
3141 *
3143static void EDIT_ContextMenuCommand(EDITSTATE *es, UINT id)
3144{
3145 switch (id) {
3146 case EM_UNDO:
3147 SendMessageW(es->hwndSelf, WM_UNDO, 0, 0);
3148 break;
3149 case WM_CUT:
3150 SendMessageW(es->hwndSelf, WM_CUT, 0, 0);
3151 break;
3152 case WM_COPY:
3153 SendMessageW(es->hwndSelf, WM_COPY, 0, 0);
3154 break;
3155 case WM_PASTE:
3156 SendMessageW(es->hwndSelf, WM_PASTE, 0, 0);
3157 break;
3158 case WM_CLEAR:
3159 SendMessageW(es->hwndSelf, WM_CLEAR, 0, 0);
3160 break;
3161 case EM_SETSEL:
3162 SendMessageW(es->hwndSelf, EM_SETSEL, 0, -1);
3163 break;
3164 default:
3165 ERR("unknown menu item, please report\n");
3166 break;
3167 }
3168}
3169
3170
3171/*********************************************************************
3172 *
3173 * WM_CONTEXTMENU
3174 *
3175 * Note: the resource files resource/sysres_??.rc cannot define a
3176 * single popup menu. Hence we use a (dummy) menubar
3177 * containing the single popup menu as its first item.
3178 *
3179 * FIXME: the message identifiers have been chosen arbitrarily,
3180 * hence we use MF_BYPOSITION.
3181 * We might as well use the "real" values (anybody knows ?)
3182 * The menu definition is in resources/sysres_??.rc.
3183 * Once these are OK, we better use MF_BYCOMMAND here
3184 * (as we do in EDIT_WM_Command()).
3185 *
3187static void EDIT_WM_ContextMenu(EDITSTATE *es, INT x, INT y)
3188{
3189 HMENU menu = LoadMenuA(GetModuleHandleA("user32.dll"), "EDITMENU");
3190 HMENU popup = GetSubMenu(menu, 0);
3191 UINT start = es->selection_start;
3192 UINT end = es->selection_end;
3193 UINT cmd;
3194 POINT pt;
3195
3197
3198 /* undo */
3200 /* cut */
3201 EnableMenuItem(popup, 2, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
3202 /* copy */
3203 EnableMenuItem(popup, 3, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) ? MF_ENABLED : MF_GRAYED));
3204 /* paste */
3206 /* delete */
3207 EnableMenuItem(popup, 5, MF_BYPOSITION | ((end - start) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
3208 /* select all */
3210
3211 pt.x = x;
3212 pt.y = y;
3213
3214 if (pt.x == -1 && pt.y == -1) /* passed via VK_APPS press/release */
3215 {
3216 RECT rc;
3217
3218 /* Windows places the menu at the edit's center in this case */
3219 GetClientRect(es->hwndSelf, &rc);
3220 pt.x = rc.left + (rc.right - rc.left) / 2;
3221 pt.y = rc.top + (rc.bottom - rc.top) / 2;
3222 ClientToScreen(es->hwndSelf, &pt);
3223 }
3224
3225 if (!(es->flags & EF_FOCUSED))
3226 SetFocus(es->hwndSelf);
3227
3229 pt.x, pt.y, 0, es->hwndSelf, NULL);
3230
3231 if (cmd)
3233
3234 DestroyMenu(menu);
3235}
3236
3237
3238/*********************************************************************
3239 *
3240 * WM_GETTEXT
3241 *
3244{
3245 if (!count)
3246 return 0;
3247
3248 lstrcpynW(dst, es->text, count);
3249 return strlenW(dst);
3250}
3251
3252/*********************************************************************
3253 *
3254 * EDIT_CheckCombo
3255 *
3258{
3259 HWND hLBox = es->hwndListBox;
3260 HWND hCombo;
3261 BOOL bDropped;
3262 int nEUI;
3263
3264 if (!hLBox)
3265 return FALSE;
3266
3267 hCombo = GetParent(es->hwndSelf);
3268 bDropped = TRUE;
3269 nEUI = 0;
3270
3271 TRACE("[%p]: handling msg %x (%x)\n", es->hwndSelf, msg, key);
3272
3273 if (key == VK_UP || key == VK_DOWN)
3274 {
3275 if (SendMessageW(hCombo, CB_GETEXTENDEDUI, 0, 0))
3276 nEUI = 1;
3277
3278 if (msg == WM_KEYDOWN || nEUI)
3279 bDropped = (BOOL)SendMessageW(hCombo, CB_GETDROPPEDSTATE, 0, 0);
3280 }
3281
3282 switch (msg)
3283 {
3284 case WM_KEYDOWN:
3285 if (!bDropped && nEUI && (key == VK_UP || key == VK_DOWN))
3286 {
3287 /* make sure ComboLBox pops up */
3288 SendMessageW(hCombo, CB_SETEXTENDEDUI, FALSE, 0);
3289 key = VK_F4;
3290 nEUI = 2;
3291 }
3292
3293 SendMessageW(hLBox, WM_KEYDOWN, key, 0);
3294 break;
3295
3296 case WM_SYSKEYDOWN: /* Handle Alt+up/down arrows */
3297 if (nEUI)
3298 SendMessageW(hCombo, CB_SHOWDROPDOWN, !bDropped, 0);
3299 else
3300 SendMessageW(hLBox, WM_KEYDOWN, VK_F4, 0);
3301 break;
3302 }
3303
3304 if (nEUI == 2)
3305 SendMessageW(hCombo, CB_SETEXTENDEDUI, TRUE, 0);
3306
3307 return TRUE;
3308}
3309
3310
3311/*********************************************************************
3312 *
3313 * WM_KEYDOWN
3314 *
3315 * Handling of special keys that don't produce a WM_CHAR
3316 * (i.e. non-printable keys) & Backspace & Delete
3317 *
3320{
3321 BOOL shift;
3322 BOOL control;
3323
3324 if (GetKeyState(VK_MENU) & 0x8000)
3325 return 0;
3326
3327 shift = GetKeyState(VK_SHIFT) & 0x8000;
3328 control = GetKeyState(VK_CONTROL) & 0x8000;
3329
3330 switch (key) {
3331 case VK_F4:
3332 case VK_UP:
3334 break;
3335
3336 /* fall through */
3337 case VK_LEFT:
3338 if ((es->style & ES_MULTILINE) && (key == VK_UP))
3340 else
3341 if (control)
3343 else
3345 break;
3346 case VK_DOWN:
3348 break;
3349 /* fall through */
3350 case VK_RIGHT:
3351 if ((es->style & ES_MULTILINE) && (key == VK_DOWN))
3353 else if (control)
3355 else
3357 break;
3358 case VK_HOME:
3359 EDIT_MoveHome(es, shift, control);
3360 break;
3361 case VK_END:
3362 EDIT_MoveEnd(es, shift, control);
3363 break;
3364 case VK_PRIOR:
3365 if (es->style & ES_MULTILINE)
3367 else
3369 break;
3370 case VK_NEXT:
3371 if (es->style & ES_MULTILINE)
3373 else
3375 break;
3376 case VK_DELETE:
3377 if (!(es->style & ES_READONLY) && !(shift && control)) {
3378 if (es->selection_start != es->selection_end) {
3379 if (shift)
3380 EDIT_WM_Cut(es);
3381 else
3383 } else {
3384 if (shift) {
3385 /* delete character left of caret */
3386 EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
3389 } else if (control) {
3390 /* delete to end of line */
3391 EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
3394 } else {
3395 /* delete character right of caret */
3396 EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
3399 }
3400 }
3401 }
3402 break;
3403 case VK_INSERT:
3404 if (shift) {
3405 if (!(es->style & ES_READONLY))
3407 } else if (control)
3409 break;
3410 case VK_RETURN:
3411 /* If the edit doesn't want the return send a message to the default object */
3412 if(!(es->style & ES_MULTILINE) || !(es->style & ES_WANTRETURN))
3413 {
3414 DWORD dw;
3415
3416 if (!EDIT_IsInsideDialog(es)) break;
3417 if (control) break;
3418 dw = SendMessageW(es->hwndParent, DM_GETDEFID, 0, 0);
3419 if (HIWORD(dw) == DC_HASDEFID)
3420 {
3421 HWND hwDefCtrl = GetDlgItem(es->hwndParent, LOWORD(dw));
3422 if (hwDefCtrl)
3423 {
3424 SendMessageW(es->hwndParent, WM_NEXTDLGCTL, (WPARAM)hwDefCtrl, TRUE);
3425 PostMessageW(hwDefCtrl, WM_KEYDOWN, VK_RETURN, 0);
3426 }
3427 }
3428 }
3429 break;
3430 case VK_ESCAPE:
3431 if ((es->style & ES_MULTILINE) && EDIT_IsInsideDialog(es))
3432 PostMessageW(es->hwndParent, WM_CLOSE, 0, 0);
3433 break;
3434 case VK_TAB:
3435 if ((es->style & ES_MULTILINE) && EDIT_IsInsideDialog(es))
3436 SendMessageW(es->hwndParent, WM_NEXTDLGCTL, shift, 0);
3437 break;
3438 case 'A':
3439 if (control)
3440 {
3442 {
3443 if (!notify_parent(es, EN_UPDATE)) break;
3445 }
3446 }
3447 break;
3448 }
3449 return TRUE;
3450}
3451
3452
3453/*********************************************************************
3454 *
3455 * WM_KILLFOCUS
3456 *
3459{
3461 HWND hwndSelf = es->hwndSelf;
3462
3463 es->flags &= ~EF_FOCUSED;
3464 DestroyCaret();
3465 if (!(es->style & ES_NOHIDESEL))
3466 EDIT_InvalidateText(es, es->selection_start, es->selection_end);
3467 if (!notify_parent(es, EN_KILLFOCUS)) return 0;
3468 /* Throw away left over scroll when we lose focus */
3469 es->wheelDeltaRemainder = 0;
3470
3471 if (theme)
3472 flags |= RDW_FRAME;
3473
3474 RedrawWindow(hwndSelf, NULL, NULL, flags);
3475 return 0;
3476}
3477
3478
3479/*********************************************************************
3480 *
3481 * WM_LBUTTONDBLCLK
3482 *
3483 * The caret position has been set on the WM_LBUTTONDOWN message
3484 *
3487{
3488 INT s;
3489 INT e = es->selection_end;
3490 INT l;
3491 INT li;
3492 INT ll;
3493
3494 es->bCaptureState = TRUE;
3495 SetCapture(es->hwndSelf);
3496
3504 es->region_posx = es->region_posy = 0;
3505 SetTimer(es->hwndSelf, 0, 100, NULL);
3506 return 0;
3507}
3508
3509
3510/*********************************************************************
3511 *
3512 * WM_LBUTTONDOWN
3513 *
3516{
3517 INT e;
3518 BOOL after_wrap;
3519
3520 es->bCaptureState = TRUE;
3521 SetCapture(es->hwndSelf);
3522 EDIT_ConfinePoint(es, &x, &y);
3523 e = EDIT_CharFromPos(es, x, y, &after_wrap);
3524 EDIT_EM_SetSel(es, (keys & MK_SHIFT) ? es->selection_start : e, e, after_wrap);
3526 es->region_posx = es->region_posy = 0;
3527 SetTimer(es->hwndSelf, 0, 100, NULL);
3528
3529 if (!(es->flags & EF_FOCUSED))
3530 SetFocus(es->hwndSelf);
3531
3532 return 0;
3533}
3534
3535
3536/*********************************************************************
3537 *
3538 * WM_LBUTTONUP
3539 *
3542{
3543 if (es->bCaptureState) {
3544 KillTimer(es->hwndSelf, 0);
3545 if (GetCapture() == es->hwndSelf) ReleaseCapture();
3546 }
3547 es->bCaptureState = FALSE;
3548 return 0;
3549}
3550
3551
3552/*********************************************************************
3553 *
3554 * WM_MBUTTONDOWN
3555 *
3558{
3559 SendMessageW(es->hwndSelf, WM_PASTE, 0, 0);
3560 return 0;
3561}
3562
3563
3564/*********************************************************************
3565 *
3566 * WM_MOUSEMOVE
3567 *
3570{
3571 INT e;
3572 BOOL after_wrap;
3573 INT prex, prey;
3574
3575 /* If the mouse has been captured by process other than the edit control itself,
3576 * the windows edit controls will not select the strings with mouse move.
3577 */
3578 if (!es->bCaptureState || GetCapture() != es->hwndSelf)
3579 return 0;
3580
3581 /*
3582 * FIXME: gotta do some scrolling if outside client
3583 * area. Maybe reset the timer ?
3584 */
3585 prex = x; prey = y;
3586 EDIT_ConfinePoint(es, &x, &y);
3587 es->region_posx = (prex < x) ? -1 : ((prex > x) ? 1 : 0);
3588 es->region_posy = (prey < y) ? -1 : ((prey > y) ? 1 : 0);
3589 e = EDIT_CharFromPos(es, x, y, &after_wrap);
3590 EDIT_EM_SetSel(es, es->selection_start, e, after_wrap);
3591 EDIT_SetCaretPos(es,es->selection_end,es->flags & EF_AFTER_WRAP);
3592 return 0;
3593}
3594
3595
3596/*********************************************************************
3597 *
3598 * WM_PAINT
3599 *
3601static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc)
3602{
3603 PAINTSTRUCT ps;
3604 INT i;
3605 HDC dc;
3606 HFONT old_font = 0;
3607 RECT rc;
3608 RECT rcClient;
3609 RECT rcLine;
3610 RECT rcRgn;
3611 HBRUSH brush;
3612 HBRUSH old_brush;
3613 INT bw, bh;
3614 BOOL rev = es->bEnableState &&
3615 ((es->flags & EF_FOCUSED) ||
3616 (es->style & ES_NOHIDESEL));
3617 dc = hdc ? hdc : BeginPaint(es->hwndSelf, &ps);
3618
3619 /* The dc we use for calculating may not be the one we paint into.
3620 This is the safest action. */
3622 GetClientRect(es->hwndSelf, &rcClient);
3623
3624 /* get the background brush */
3625 brush = EDIT_NotifyCtlColor(es, dc);
3626
3627 /* paint the border and the background */
3628 IntersectClipRect(dc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
3629
3630 if(es->style & WS_BORDER) {
3633 rc = rcClient;
3634 if(es->style & ES_MULTILINE) {
3635 if(es->style & WS_HSCROLL) rc.bottom+=bh;
3636 if(es->style & WS_VSCROLL) rc.right+=bw;
3637 }
3638
3639 /* Draw the frame. Same code as in nonclient.c */
3641 PatBlt(dc, rc.left, rc.top, rc.right - rc.left, bh, PATCOPY);
3642 PatBlt(dc, rc.left, rc.top, bw, rc.bottom - rc.top, PATCOPY);
3643 PatBlt(dc, rc.left, rc.bottom - 1, rc.right - rc.left, -bw, PATCOPY);
3644 PatBlt(dc, rc.right - 1, rc.top, -bw, rc.bottom - rc.top, PATCOPY);
3645 SelectObject(dc, old_brush);
3646
3647 /* Keep the border clean */
3648 IntersectClipRect(dc, rc.left+bw, rc.top+bh,
3649 max(rc.right-bw, rc.left+bw), max(rc.bottom-bh, rc.top+bh));
3650 }
3651
3652 GetClipBox(dc, &rc);
3653 FillRect(dc, &rc, brush);
3654
3655 IntersectClipRect(dc, es->format_rect.left,
3656 es->format_rect.top,
3657 es->format_rect.right,
3658 es->format_rect.bottom);
3659 if (es->style & ES_MULTILINE) {
3660 rc = rcClient;
3661 IntersectClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);
3662 }
3663 if (es->font)
3664 old_font = SelectObject(dc, es->font);
3665
3666 if (!es->bEnableState)
3668 GetClipBox(dc, &rcRgn);
3669 if (es->style & ES_MULTILINE) {
3671 for (i = es->y_offset ; i <= min(es->y_offset + vlc, es->y_offset + es->line_count - 1) ; i++) {
3673 EDIT_GetLineRect(es, i, 0, -1, &rcLine);
3674 if (IntersectRect(&rc, &rcRgn, &rcLine))
3675 EDIT_PaintLine(es, dc, i, rev);
3676 }
3677 } else {
3679 EDIT_GetLineRect(es, 0, 0, -1, &rcLine);
3680 if (IntersectRect(&rc, &rcRgn, &rcLine))
3681 EDIT_PaintLine(es, dc, 0, rev);
3682 }
3683 if (es->font)
3684 SelectObject(dc, old_font);
3685
3686 if (!hdc)
3687 EndPaint(es->hwndSelf, &ps);
3688}
3690static void EDIT_WM_NCPaint(HWND hwnd, HRGN region)
3691{
3693 HTHEME theme = GetWindowTheme(hwnd);
3694 HRGN cliprgn = region;
3695
3696 if (theme && exStyle & WS_EX_CLIENTEDGE)
3697 {
3698 HDC dc;
3699 RECT r;
3700 int cxEdge = GetSystemMetrics(SM_CXEDGE),
3701 cyEdge = GetSystemMetrics(SM_CYEDGE);
3702 const int part = EP_EDITTEXT;
3703 int state = ETS_NORMAL;
3704 DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3705
3706 if (!IsWindowEnabled(hwnd))
3708 else if (dwStyle & ES_READONLY)
3710 else if (GetFocus() == hwnd)
3712
3713 GetWindowRect(hwnd, &r);
3714
3715 /* New clipping region passed to default proc to exclude border */
3716 cliprgn = CreateRectRgn(r.left + cxEdge, r.top + cyEdge,
3717 r.right - cxEdge, r.bottom - cyEdge);
3718 if (region != (HRGN)1)
3719 CombineRgn(cliprgn, cliprgn, region, RGN_AND);
3720 OffsetRect(&r, -r.left, -r.top);
3721
3722#ifdef __REACTOS__ /* r73789 */
3723 dc = GetWindowDC(hwnd);
3724 /* Exclude client part */
3726 r.left + cxEdge,
3727 r.top + cyEdge,
3728 r.right - cxEdge,
3729 r.bottom -cyEdge);
3730#else
3732 OffsetRect(&r, -r.left, -r.top);
3733#endif
3734
3737 DrawThemeBackground(theme, dc, part, state, &r, 0);
3738 ReleaseDC(hwnd, dc);
3739 }
3740
3741 /* Call default proc to get the scrollbars etc. also painted */
3742 DefWindowProcW (hwnd, WM_NCPAINT, (WPARAM)cliprgn, 0);
3743 if (cliprgn != region)
3744 DeleteObject(cliprgn);
3745}
3746
3747/*********************************************************************
3748 *
3749 * WM_SETFOCUS
3750 *
3752static void EDIT_WM_SetFocus(HTHEME theme, EDITSTATE *es)
3753{
3755
3756 es->flags |= EF_FOCUSED;
3757
3758 if (!(es->style & ES_NOHIDESEL))
3759 EDIT_InvalidateText(es, es->selection_start, es->selection_end);
3760
3761#ifdef __REACTOS__
3762 SystemParametersInfo(SPI_GETCARETWIDTH, 0, &es->dwCaretWidth, 0);
3763 CreateCaret(es->hwndSelf, NULL, es->dwCaretWidth, es->line_height);
3764#else
3765 CreateCaret(es->hwndSelf, 0, 1, es->line_height);
3766#endif
3767 EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP);
3768 ShowCaret(es->hwndSelf);
3769 if (!notify_parent(es, EN_SETFOCUS)) return;
3770
3771 if (theme)
3773
3774 RedrawWindow(es->hwndSelf, NULL, NULL, flags);
3775}
3776
3777
3778/*********************************************************************
3779 *
3780 * WM_SETFONT
3781 *
3782 * With Win95 look the margins are set to default font value unless
3783 * the system font (font == 0) is being set, in which case they are left
3784 * unchanged.
3785 *
3788{
3790 HDC dc;
3791 HFONT old_font = 0;
3792 RECT clientRect;
3793
3794 es->font = font;
3796 dc = GetDC(es->hwndSelf);
3797 if (font)
3798 old_font = SelectObject(dc, font);
3800 es->line_height = tm.tmHeight;
3801 es->char_width = tm.tmAveCharWidth;
3802 if (font)
3803 SelectObject(dc, old_font);
3804 ReleaseDC(es->hwndSelf, dc);
3805
3806 /* Reset the format rect and the margins */
3807 GetClientRect(es->hwndSelf, &clientRect);
3808 EDIT_SetRectNP(es, &clientRect);
3811
3812 if (es->style & ES_MULTILINE)
3814 else
3816
3817 if (redraw)
3819 if (es->flags & EF_FOCUSED) {
3820 DestroyCaret();
3821#ifdef __REACTOS__
3822 CreateCaret(es->hwndSelf, NULL, es->dwCaretWidth, es->line_height);
3823#else
3824 CreateCaret(es->hwndSelf, 0, 1, es->line_height);
3825#endif
3826 EDIT_SetCaretPos(es, es->selection_end,
3827 es->flags & EF_AFTER_WRAP);
3828 ShowCaret(es->hwndSelf);
3829 }
3830#ifdef __REACTOS__
3832 {
3833 LOGFONTW lf;
3834 HIMC hIMC = ImmGetContext(es->hwndSelf);
3835 if (font == NULL)
3837 GetObjectW(font, sizeof(lf), &lf);
3838 ImmSetCompositionFontW(hIMC, &lf);
3839 ImmReleaseContext(es->hwndSelf, hIMC);
3840 }
3841#endif
3842}
3843
3844
3845/*********************************************************************
3846 *
3847 * WM_SETTEXT
3848 *
3849 * NOTES
3850 * For multiline controls (ES_MULTILINE), reception of WM_SETTEXT triggers:
3851 * The modified flag is reset. No notifications are sent.
3852 *
3853 * For single-line controls, reception of WM_SETTEXT triggers:
3854 * The modified flag is reset. EN_UPDATE and EN_CHANGE notifications are sent.
3855 *
3858{
3859 if (es->flags & EF_UPDATE)
3860 /* fixed this bug once; complain if we see it about to happen again. */
3861 ERR("SetSel may generate UPDATE message whose handler may reset "
3862 "selection.\n");
3863
3864 EDIT_EM_SetSel(es, 0, (UINT)-1, FALSE);
3865 if (text)
3866 {
3867 TRACE("%s\n", debugstr_w(text));
3869 }
3870 else
3871 {
3872 TRACE("<NULL>\n");
3874 }
3875 es->x_offset = 0;
3876 es->flags &= ~EF_MODIFIED;
3877 EDIT_EM_SetSel(es, 0, 0, FALSE);
3878
3879 /* Send the notification after the selection start and end have been set
3880 * edit control doesn't send notification on WM_SETTEXT
3881 * if it is multiline, or it is part of combobox
3882 */
3883 if( !((es->style & ES_MULTILINE) || es->hwndListBox))
3884 {
3885 if (!notify_parent(es, EN_UPDATE)) return;
3886 if (!notify_parent(es, EN_CHANGE)) return;
3887 }
3891}
3892
3893
3894/*********************************************************************
3895 *
3896 * WM_SIZE
3897 *
3899static void EDIT_WM_Size(EDITSTATE *es, UINT action)
3900{
3901 if ((action == SIZE_MAXIMIZED) || (action == SIZE_RESTORED)) {
3902 RECT rc;
3903 GetClientRect(es->hwndSelf, &rc);
3904 EDIT_SetRectNP(es, &rc);
3906 }
3907}
3908
3909
3910/*********************************************************************
3911 *
3912 * WM_STYLECHANGED
3913 *
3914 * This message is sent by SetWindowLong on having changed either the Style
3915 * or the extended style.
3916 *
3917 * We ensure that the window's version of the styles and the EDITSTATE's agree.
3918 *
3919 * See also EDIT_WM_NCCreate
3920 *
3921 * It appears that the Windows version of the edit control allows the style
3922 * (as retrieved by GetWindowLong) to be any value and maintains an internal
3923 * style variable which will generally be different. In this function we
3924 * update the internal style based on what changed in the externally visible
3925 * style.
3926 *
3927 * Much of this content as based upon the MSDN, especially:
3928 * Platform SDK Documentation -> User Interface Services ->
3929 * Windows User Interface -> Edit Controls -> Edit Control Reference ->
3930 * Edit Control Styles
3933{
3934 if (GWL_STYLE == which) {
3935 DWORD style_change_mask;
3936 DWORD new_style;
3937 /* Only a subset of changes can be applied after the control
3938 * has been created.
3939 */
3940 style_change_mask = ES_UPPERCASE | ES_LOWERCASE |
3941 ES_NUMBER;
3942 if (es->style & ES_MULTILINE)
3943 style_change_mask |= ES_WANTRETURN;
3944
3945 new_style = style->styleNew & style_change_mask;
3946
3947 /* Number overrides lowercase overrides uppercase (at least it
3948 * does in Win95). However I'll bet that ES_NUMBER would be
3949 * invalid under Win 3.1.
3950 */
3951 if (new_style & ES_NUMBER) {
3952 ; /* do not override the ES_NUMBER */
3953 } else if (new_style & ES_LOWERCASE) {
3954 new_style &= ~ES_UPPERCASE;
3955 }
3956
3957 es->style = (es->style & ~style_change_mask) | new_style;
3958 } else if (GWL_EXSTYLE == which) {
3959 ; /* FIXME - what is needed here */
3960 } else {
3961 WARN ("Invalid style change %ld\n",which);
3962 }
3963
3964 return 0;
3965}
3966
3967/*********************************************************************
3968 *
3969 * WM_SYSKEYDOWN
3970 *
3973{
3974 if ((key == VK_BACK) && (key_data & 0x2000)) {
3975 if (EDIT_EM_CanUndo(es))
3977 return 0;
3978 } else if (key == VK_UP || key == VK_DOWN) {
3980 return 0;
3981 }
3982 return DefWindowProcW(es->hwndSelf, WM_SYSKEYDOWN, key, key_data);
3983}
3984
3985
3986/*********************************************************************
3987 *
3988 * WM_TIMER
3989 *
3991static void EDIT_WM_Timer(EDITSTATE *es)
3992{
3993 if (es->region_posx < 0) {
3995 } else if (es->region_posx > 0) {
3997 }
3998/*
3999 * FIXME: gotta do some vertical scrolling here, like
4000 * EDIT_EM_LineScroll(hwnd, 0, 1);
4001 */
4002}
4003
4004/*********************************************************************
4005 *
4006 * WM_HSCROLL
4007 *
4010{
4011 INT dx;
4012 INT fw;
4013
4014 if (!(es->style & ES_MULTILINE))
4015 return 0;
4016
4017 if (!(es->style & ES_AUTOHSCROLL))
4018 return 0;
4019
4020 dx = 0;
4021 fw = es->format_rect.right - es->format_rect.left;
4022 switch (action) {
4023 case SB_LINELEFT:
4024 TRACE("SB_LINELEFT\n");
4025 if (es->x_offset)
4026 dx = -es->char_width;
4027 break;
4028 case SB_LINERIGHT:
4029 TRACE("SB_LINERIGHT\n");
4030 if (es->x_offset < es->text_width)
4031 dx = es->char_width;
4032 break;
4033 case SB_PAGELEFT:
4034 TRACE("SB_PAGELEFT\n");
4035 if (es->x_offset)
4036 dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
4037 break;
4038 case SB_PAGERIGHT:
4039 TRACE("SB_PAGERIGHT\n");
4040 if (es->x_offset < es->text_width)
4041 dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
4042 break;
4043 case SB_LEFT:
4044 TRACE("SB_LEFT\n");
4045 if (es->x_offset)
4046 dx = -es->x_offset;
4047 break;
4048 case SB_RIGHT:
4049 TRACE("SB_RIGHT\n");
4050 if (es->x_offset < es->text_width)
4051 dx = es->text_width - es->x_offset;
4052 break;
4053 case SB_THUMBTRACK:
4054 TRACE("SB_THUMBTRACK %d\n", pos);
4055 es->flags |= EF_HSCROLL_TRACK;
4056 if(es->style & WS_HSCROLL)
4057 dx = pos - es->x_offset;
4058 else
4059 {
4060 INT fw, new_x;
4061 /* Sanity check */
4062 if(pos < 0 || pos > 100) return 0;
4063 /* Assume default scroll range 0-100 */
4064 fw = es->format_rect.right - es->format_rect.left;
4065 new_x = pos * (es->text_width - fw) / 100;
4066 dx = es->text_width ? (new_x - es->x_offset) : 0;
4067 }
4068 break;
4069 case SB_THUMBPOSITION:
4070 TRACE("SB_THUMBPOSITION %d\n", pos);
4071 es->flags &= ~EF_HSCROLL_TRACK;
4072 if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_HSCROLL)
4073 dx = pos - es->x_offset;
4074 else
4075 {
4076 INT fw, new_x;
4077 /* Sanity check */
4078 if(pos < 0 || pos > 100) return 0;
4079 /* Assume default scroll range 0-100 */
4080 fw = es->format_rect.right - es->format_rect.left;
4081 new_x = pos * (es->text_width - fw) / 100;
4082 dx = es->text_width ? (new_x - es->x_offset) : 0;
4083 }
4084 if (!dx) {
4085 /* force scroll info update */
4088 }
4089 break;
4090 case SB_ENDSCROLL:
4091 TRACE("SB_ENDSCROLL\n");
4092 break;
4093 /*
4094 * FIXME : the next two are undocumented !
4095 * Are we doing the right thing ?
4096 * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
4097 * although it's also a regular control message.
4098 */
4099 case EM_GETTHUMB: /* this one is used by NT notepad */
4100 {
4101 LRESULT ret;
4102 if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_HSCROLL)
4103 ret = GetScrollPos(es->hwndSelf, SB_HORZ);
4104 else
4105 {
4106 /* Assume default scroll range 0-100 */
4107 INT fw = es->format_rect.right - es->format_rect.left;
4108 ret = es->text_width ? es->x_offset * 100 / (es->text_width - fw) : 0;
4109 }
4110 TRACE("EM_GETTHUMB: returning %ld\n", ret);
4111 return ret;
4112 }
4113 case EM_LINESCROLL:
4114 TRACE("EM_LINESCROLL16\n");
4115 dx = pos;
4116 break;
4117
4118 default:
4119 ERR("undocumented WM_HSCROLL action %d (0x%04x), please report\n",
4120 action, action);
4121 return 0;
4122 }
4123 if (dx)
4124 {
4125 INT fw = es->format_rect.right - es->format_rect.left;
4126 /* check if we are going to move too far */
4127 if(es->x_offset + dx + fw > es->text_width)
4128 dx = es->text_width - fw - es->x_offset;
4129 if(dx)
4131 }
4132 return 0;
4133}
4134
4135
4136/*********************************************************************
4137 *
4138 * WM_VSCROLL
4139 *
4142{
4143 INT dy;
4144
4145 if (!(es->style & ES_MULTILINE))
4146 return 0;
4147
4148 if (!(es->style & ES_AUTOVSCROLL))
4149 return 0;
4150
4151 dy = 0;
4152 switch (action) {
4153 case SB_LINEUP:
4154 case SB_LINEDOWN:
4155 case SB_PAGEUP:
4156 case SB_PAGEDOWN:
4157 TRACE("action %d (%s)\n", action, (action == SB_LINEUP ? "SB_LINEUP" :
4158 (action == SB_LINEDOWN ? "SB_LINEDOWN" :
4159 (action == SB_PAGEUP ? "SB_PAGEUP" :
4160 "SB_PAGEDOWN"))));
4162 return 0;
4163 case SB_TOP:
4164 TRACE("SB_TOP\n");
4165 dy = -es->y_offset;
4166 break;
4167 case SB_BOTTOM:
4168 TRACE("SB_BOTTOM\n");
4169 dy = es->line_count - 1 - es->y_offset;
4170 break;
4171 case SB_THUMBTRACK:
4172 TRACE("SB_THUMBTRACK %d\n", pos);
4173 es->flags |= EF_VSCROLL_TRACK;
4174 if(es->style & WS_VSCROLL)
4175 dy = pos - es->y_offset;
4176 else
4177 {
4178 /* Assume default scroll range 0-100 */
4179 INT vlc, new_y;
4180 /* Sanity check */
4181 if(pos < 0 || pos > 100) return 0;
4183 new_y = pos * (es->line_count - vlc) / 100;
4184 dy = es->line_count ? (new_y - es->y_offset) : 0;
4185 TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n",
4186 es->line_count, es->y_offset, pos, dy);
4187 }
4188 break;
4189 case SB_THUMBPOSITION:
4190 TRACE("SB_THUMBPOSITION %d\n", pos);
4191 es->flags &= ~EF_VSCROLL_TRACK;
4192 if(es->style & WS_VSCROLL)
4193 dy = pos - es->y_offset;
4194 else
4195 {
4196 /* Assume default scroll range 0-100 */
4197 INT vlc, new_y;
4198 /* Sanity check */
4199 if(pos < 0 || pos > 100) return 0;
4201 new_y = pos * (es->line_count - vlc) / 100;
4202 dy = es->line_count ? (new_y - es->y_offset) : 0;
4203 TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n",
4204 es->line_count, es->y_offset, pos, dy);
4205 }
4206 if (!dy)
4207 {
4208 /* force scroll info update */
4211 }
4212 break;
4213 case SB_ENDSCROLL:
4214 TRACE("SB_ENDSCROLL\n");
4215 break;
4216 /*
4217 * FIXME : the next two are undocumented !
4218 * Are we doing the right thing ?
4219 * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
4220 * although it's also a regular control message.
4221 */
4222 case EM_GETTHUMB: /* this one is used by NT notepad */
4223 {
4224 LRESULT ret;
4225 if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_VSCROLL)
4226 ret = GetScrollPos(es->hwndSelf, SB_VERT);
4227 else
4228 {
4229 /* Assume default scroll range 0-100 */
4231 ret = es->line_count ? es->y_offset * 100 / (es->line_count - vlc) : 0;
4232 }
4233 TRACE("EM_GETTHUMB: returning %ld\n", ret);
4234 return ret;
4235 }
4236 case EM_LINESCROLL:
4237 TRACE("EM_LINESCROLL %d\n", pos);
4238 dy = pos;
4239 break;
4240
4241 default:
4242 ERR("undocumented WM_VSCROLL action %d (0x%04x), please report\n",
4243 action, action);
4244 return 0;
4245 }
4246 if (dy)
4248 return 0;
4249}
4250
4251/*********************************************************************
4252 *
4253 * EM_GETTHUMB
4254 *
4255 * FIXME: is this right ? (or should it be only VSCROLL)
4256 * (and maybe only for edit controls that really have their
4257 * own scrollbars) (and maybe only for multiline controls ?)
4258 * All in all: very poorly documented
4259 *
4262{
4265}
4266
4267
4268/********************************************************************
4269 *
4270 * The Following code is to handle inline editing from IMEs
4271 */
4273static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es)
4274{
4275 LONG buflen;
4276 LPWSTR lpCompStr;
4277 LPSTR lpCompStrAttr = NULL;
4278 DWORD dwBufLenAttr;
4279
4280 buflen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
4281
4282 if (buflen < 0)
4283 {
4284 return;
4285 }
4286
4287 lpCompStr = heap_alloc(buflen);
4288 if (!lpCompStr)
4289 {
4290 ERR("Unable to allocate IME CompositionString\n");
4291 return;
4292 }
4293
4294 if (buflen)
4295 ImmGetCompositionStringW(hIMC, GCS_COMPSTR, lpCompStr, buflen);
4296
4297 if (CompFlag & GCS_COMPATTR)
4298 {
4299 /*
4300 * We do not use the attributes yet. it would tell us what characters
4301 * are in transition and which are converted or decided upon
4302 */
4303 dwBufLenAttr = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
4304 if (dwBufLenAttr)
4305 {
4306 dwBufLenAttr ++;
4307 lpCompStrAttr = heap_alloc(dwBufLenAttr + 1);
4308 if (!lpCompStrAttr)
4309 {
4310 ERR("Unable to allocate IME Attribute String\n");
4311 heap_free(lpCompStr);
4312 return;
4313 }
4314 ImmGetCompositionStringW(hIMC,GCS_COMPATTR, lpCompStrAttr,
4315 dwBufLenAttr);
4316 lpCompStrAttr[dwBufLenAttr] = 0;
4317 }
4318 }
4319
4320#ifndef __REACTOS__ /* We don't use internal composition string. Rely on the composition window */
4321 /* check for change in composition start */
4322 if (es->selection_end < es->composition_start)
4323 es->composition_start = es->selection_end;
4324
4325 /* replace existing selection string */
4326 es->selection_start = es->composition_start;
4327
4328 if (es->composition_len > 0)
4329 es->selection_end = es->composition_start + es->composition_len;
4330 else
4331 es->selection_end = es->selection_start;
4332
4333 EDIT_EM_ReplaceSel(es, FALSE, lpCompStr, buflen / sizeof(WCHAR), TRUE, TRUE);
4334 es->composition_len = abs(es->composition_start - es->selection_end);
4335
4336 es->selection_start = es->composition_start;
4337 es->selection_end = es->selection_start + es->composition_len;
4338#endif
4339
4340 heap_free(lpCompStrAttr);
4341 heap_free(lpCompStr);
4342}
4344static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es)
4345{
4346 LONG buflen;
4347 LPWSTR lpResultStr;
4348
4349 buflen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
4350 if (buflen <= 0)
4351 {
4352 return;
4353 }
4354
4355 lpResultStr = heap_alloc(buflen);
4356 if (!lpResultStr)
4357 {
4358 ERR("Unable to alloc buffer for IME string\n");
4359 return;
4360 }
4361
4362 ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpResultStr, buflen);
4363
4364#ifndef __REACTOS__
4365 /* check for change in composition start */
4366 if (es->selection_end < es->composition_start)
4367 es->composition_start = es->selection_end;
4368
4369 es->selection_start = es->composition_start;
4370 es->selection_end = es->composition_start + es->composition_len;
4371 EDIT_EM_ReplaceSel(es, TRUE, lpResultStr, buflen / sizeof(WCHAR), TRUE, TRUE);
4372 es->composition_start = es->selection_end;
4373 es->composition_len = 0;
4374#endif
4375
4376 heap_free(lpResultStr);
4377}
4379static void EDIT_ImeComposition(HWND hwnd, LPARAM CompFlag, EDITSTATE *es)
4380{
4381 HIMC hIMC;
4382 int cursor;
4383
4384#ifdef __REACTOS__
4385 if (es->selection_start != es->selection_end)
4387#else
4388 if (es->composition_len == 0 && es->selection_start != es->selection_end)
4389 {
4391 es->composition_start = es->selection_end;
4392 }
4393#endif
4394
4395 hIMC = ImmGetContext(hwnd);
4396 if (!hIMC)
4397 return;
4398
4399 if (CompFlag & GCS_RESULTSTR)
4400 {
4401 EDIT_GetResultStr(hIMC, es);
4402 cursor = 0;
4403 }
4404 else
4405 {
4406 if (CompFlag & GCS_COMPSTR)
4407 EDIT_GetCompositionStr(hIMC, CompFlag, es);
4408#ifdef __REACTOS__
4409 cursor = 0;
4410#else
4412#endif
4413 }
4414 ImmReleaseContext(hwnd, hIMC);
4415 EDIT_SetCaretPos(es, es->selection_start + cursor, es->flags & EF_AFTER_WRAP);
4416}
4417
4418
4419/*********************************************************************
4420 *
4421 * WM_NCCREATE
4422 *
4423 * See also EDIT_WM_StyleChanged
4426{
4427 EDITSTATE *es;
4428 UINT alloc_size;
4429
4430 TRACE("Creating edit control, style = %08x\n", lpcs->style);
4431
4432 if (!(es = heap_alloc_zero(sizeof(*es))))
4433 return FALSE;
4435
4436 /*
4437 * Note: since the EDITSTATE has not been fully initialized yet,
4438 * we can't use any API calls that may send
4439 * WM_XXX messages before WM_NCCREATE is completed.
4440 */
4441
4442 es->style = lpcs->style;
4443
4444 es->bEnableState = !(es->style & WS_DISABLED);
4445
4446 es->hwndSelf = hwnd;
4447 /* Save parent, which will be notified by EN_* messages */
4448 es->hwndParent = lpcs->hwndParent;
4449
4450 if (es->style & ES_COMBO)
4451 es->hwndListBox = GetDlgItem(es->hwndParent, ID_CB_LISTBOX);
4452
4453 /* FIXME: should we handle changes to WS_EX_RIGHT style after creation? */
4454 if (lpcs->dwExStyle & WS_EX_RIGHT) es->style |= ES_RIGHT;
4455
4456 /* Number overrides lowercase overrides uppercase (at least it
4457 * does in Win95). However I'll bet that ES_NUMBER would be
4458 * invalid under Win 3.1.
4459 */
4460 if (es->style & ES_NUMBER) {
4461 ; /* do not override the ES_NUMBER */
4462 } else if (es->style & ES_LOWERCASE) {
4463 es->style &= ~ES_UPPERCASE;
4464 }
4465 if (es->style & ES_MULTILINE) {
4466 es->buffer_limit = BUFLIMIT_INITIAL;
4467 if (es->style & WS_VSCROLL)
4468 es->style |= ES_AUTOVSCROLL;
4469 if (es->style & WS_HSCROLL)
4470 es->style |= ES_AUTOHSCROLL;
4471 es->style &= ~ES_PASSWORD;
4472 if ((es->style & ES_CENTER) || (es->style & ES_RIGHT)) {
4473 /* Confirmed - RIGHT overrides CENTER */
4474 if (es->style & ES_RIGHT)
4475 es->style &= ~ES_CENTER;
4476 es->style &= ~WS_HSCROLL;
4477 es->style &= ~ES_AUTOHSCROLL;
4478 }
4479 } else {
4480 es->buffer_limit = BUFLIMIT_INITIAL;
4481 if ((es->style & ES_RIGHT) && (es->style & ES_CENTER))
4482 es->style &= ~ES_CENTER;
4483 es->style &= ~WS_HSCROLL;
4484 es->style &= ~WS_VSCROLL;
4485 if (es->style & ES_PASSWORD)
4486 es->password_char = '*';
4487 }
4488
4489 alloc_size = ROUND_TO_GROW((es->buffer_size + 1) * sizeof(WCHAR));
4490 if(!(es->hloc32W = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
4491 goto cleanup;
4492 es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
4493
4494 if (!(es->undo_text = heap_alloc_zero((es->buffer_size + 1) * sizeof(WCHAR))))
4495 goto cleanup;
4496 es->undo_buffer_size = es->buffer_size;
4497
4498 if (es->style & ES_MULTILINE)
4499 if (!(es->first_line_def = heap_alloc_zero(sizeof(LINEDEF))))
4500 goto cleanup;
4501 es->line_count = 1;
4502
4503 /*
4504 * In Win95 look and feel, the WS_BORDER style is replaced by the
4505 * WS_EX_CLIENTEDGE style for the edit control. This gives the edit
4506 * control a nonclient area so we don't need to draw the border.
4507 * If WS_BORDER without WS_EX_CLIENTEDGE is specified we shouldn't have
4508 * a nonclient area and we should handle painting the border ourselves.
4509 *
4510 * When making modifications please ensure that the code still works
4511 * for edit controls created directly with style 0x50800000, exStyle 0
4512 * (which should have a single pixel border)
4513 */
4514 if (lpcs->dwExStyle & WS_EX_CLIENTEDGE)
4515 es->style &= ~WS_BORDER;
4516 else if (es->style & WS_BORDER)
4518
4519 return TRUE;
4520
4521cleanup:
4522 SetWindowLongPtrW(es->hwndSelf, 0, 0);
4524 heap_free(es->first_line_def);
4525 heap_free(es->undo_text);
4526 if (es->hloc32W) LocalFree(es->hloc32W);
4527 heap_free(es->logAttr);
4528 heap_free(es);
4529 return FALSE;
4530}
4531
4532
4533/*********************************************************************
4534 *
4535 * WM_CREATE
4536 *
4539{
4540 RECT clientRect;
4541
4542 TRACE("%s\n", debugstr_w(name));
4543
4544 /*
4545 * To initialize some final structure members, we call some helper
4546 * functions. However, since the EDITSTATE is not consistent (i.e.
4547 * not fully initialized), we should be very careful which
4548 * functions can be called, and in what order.
4549 */
4552
4553 /* We need to calculate the format rect
4554 (applications may send EM_SETMARGINS before the control gets visible) */
4555 GetClientRect(es->hwndSelf, &clientRect);
4556 EDIT_SetRectNP(es, &clientRect);
4557
4558 if (name && *name)
4559 {
4561 /* if we insert text to the editline, the text scrolls out
4562 * of the window, as the caret is placed after the insert
4563 * pos normally; thus we reset es->selection... to 0 and
4564 * update caret
4565 */
4566 es->selection_start = es->selection_end = 0;
4567 /* Adobe Photoshop does NOT like this. and MSDN says that EN_CHANGE
4568 * Messages are only to be sent when the USER does something to
4569 * change the contents. So I am removing this EN_CHANGE
4570 *
4571 * EDIT_NOTIFY_PARENT(es, EN_CHANGE);
4572 */
4574 }
4575
4576 /* force scroll info update */
4578 OpenThemeData(es->hwndSelf, WC_EDITW);
4579
4580 /* The rule seems to return 1 here for success */
4581 /* Power Builder masked edit controls will crash */
4582 /* if not. */
4583 /* FIXME: is that in all cases so ? */
4584 return 1;
4585}
4586
4587
4588/*********************************************************************
4589 *
4590 * WM_NCDESTROY
4591 *
4594{
4595 LINEDEF *pc, *pp;
4596 HTHEME theme;
4597
4598 theme = GetWindowTheme(es->hwndSelf);
4599 CloseThemeData(theme);
4600
4601 /* The app can own the text buffer handle */
4602 if (es->hloc32W && (es->hloc32W != es->hlocapp))
4603 LocalFree(es->hloc32W);
4604
4606
4607 pc = es->first_line_def;
4608 while (pc)
4609 {
4610 pp = pc->next;
4611 heap_free(pc);
4612 pc = pp;
4613 }
4614
4615 SetWindowLongPtrW( es->hwndSelf, 0, 0 );
4616 heap_free(es->undo_text);
4617 heap_free(es);
4618
4619 return 0;
4620}
4623{
4625 HTHEME theme = GetWindowTheme(hwnd);
4626 LRESULT result = 0;
4627 RECT *rect;
4628
4629 TRACE("hwnd=%p msg=%#x wparam=%lx lparam=%lx\n", hwnd, msg, wParam, lParam);
4630
4631 if (!es && msg != WM_NCCREATE)
4632 return DefWindowProcW(hwnd, msg, wParam, lParam);
4633
4634 if (es && (msg != WM_NCDESTROY))
4636
4637 switch (msg)
4638 {
4639 case EM_GETSEL:
4641 break;
4642
4643 case EM_SETSEL:
4646 result = 1;
4647 break;
4648
4649 case EM_GETRECT:
4650 rect = (RECT *)lParam;
4651 if (rect)
4652 *rect = es->format_rect;
4653 break;
4654
4655 case EM_SETRECT:
4656 if ((es->style & ES_MULTILINE) && lParam)
4657 {
4660 }
4661 break;
4662
4663 case EM_SETRECTNP:
4664 if ((es->style & ES_MULTILINE) && lParam)
4666 break;
4667
4668 case EM_SCROLL:
4670 break;
4671
4672 case EM_LINESCROLL:
4674 break;
4675
4676 case EM_SCROLLCARET:
4678 result = 1;
4679 break;
4680
4681 case EM_GETMODIFY:
4682 result = ((es->flags & EF_MODIFIED) != 0);
4683 break;
4684
4685 case EM_SETMODIFY:
4686 if (wParam)
4687 es->flags |= EF_MODIFIED;
4688 else
4689 es->flags &= ~(EF_MODIFIED | EF_UPDATE); /* reset pending updates */
4690 break;
4691
4692 case EM_GETLINECOUNT:
4693 result = (es->style & ES_MULTILINE) ? es->line_count : 1;
4694 break;
4695
4696 case EM_LINEINDEX:
4698 break;
4699
4700 case EM_SETHANDLE:
4702 break;
4703
4704 case EM_GETHANDLE:
4706 break;
4707
4708 case EM_GETTHUMB:
4710 break;
4711
4712 /* these messages missing from specs */
4713 case 0x00bf:
4714 case 0x00c0:
4715 case 0x00c3:
4716 case 0x00ca:
4717 FIXME("undocumented message 0x%x, please report\n", msg);
4719 break;
4720
4721 case EM_LINELENGTH:
4723 break;
4724
4725 case EM_REPLACESEL:
4726 {
4727 const WCHAR *textW = (const WCHAR *)lParam;
4728
4730 result = 1;
4731 break;
4732 }
4733
4734 case EM_GETLINE:
4736 break;
4737
4738 case EM_SETLIMITTEXT:
4740 break;
4741
4742 case EM_CANUNDO:
4744 break;
4745
4746 case EM_UNDO:
4747 case WM_UNDO:
4749 break;
4750
4751 case EM_FMTLINES:
4753 break;
4754
4755 case EM_LINEFROMCHAR:
4757 break;
4758
4759 case EM_SETTABSTOPS:
4761 break;
4762
4763 case EM_SETPASSWORDCHAR:
4765 break;
4766
4767 case EM_EMPTYUNDOBUFFER:
4769 break;
4770
4772 result = (es->style & ES_MULTILINE) ? es->y_offset : es->x_offset;
4773 break;
4774
4775 case EM_SETREADONLY:
4776 {
4777 DWORD old_style = es->style;
4778
4779 if (wParam)
4780 {
4782 es->style |= ES_READONLY;
4783 }
4784 else
4785 {
4787 es->style &= ~ES_READONLY;
4788 }
4789
4790 if (old_style ^ es->style)
4791 InvalidateRect(es->hwndSelf, NULL, TRUE);
4792
4793 result = 1;
4794 break;
4795 }
4796
4799 result = 1;
4800 break;
4801
4803 result = (LRESULT)es->word_break_proc;
4804 break;
4805
4806 case EM_GETPASSWORDCHAR:
4807 result = es->password_char;
4808 break;
4809
4810 case EM_SETMARGINS:
4812 break;
4813
4814 case EM_GETMARGINS:
4815 result = MAKELONG(es->left_margin, es->right_margin);
4816 break;
4817
4818 case EM_GETLIMITTEXT:
4819 result = es->buffer_limit;
4820 break;
4821
4822 case EM_POSFROMCHAR:
4823 if ((INT)wParam >= get_text_length(es)) result = -1;
4825 break;
4826
4827 case EM_CHARFROMPOS:
4828 result = EDIT_EM_CharFromPos(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
4829 break;
4830
4831 /* End of the EM_ messages which were in numerical order; what order
4832 * are these in? vaguely alphabetical?
4833 */
4834
4835 case WM_NCCREATE:
4837 break;
4838
4839 case WM_NCDESTROY:
4841 es = NULL;
4842 break;
4843
4844 case WM_GETDLGCODE:
4846
4847 if (es->style & ES_MULTILINE)
4849
4850 if (lParam)
4851 {
4852 MSG *msg = (MSG *)lParam;
4853 es->flags |= EF_DIALOGMODE;
4854
4855 if (msg->message == WM_KEYDOWN)
4856 {
4857 int vk = (int)msg->wParam;
4858
4859 if (es->hwndListBox)
4860 {
4861 if (vk == VK_RETURN || vk == VK_ESCAPE)
4864 }
4865 }
4866 }
4867 break;
4868
4869 case WM_IME_CHAR:
4870#ifdef __REACTOS__
4872 break;
4873#endif
4874 case WM_CHAR:
4875 {
4876 WCHAR charW = wParam;
4877
4878 if (es->hwndListBox)
4879 {
4880 if (charW == VK_RETURN || charW == VK_ESCAPE)
4881 {
4884 break;
4885 }
4886 }
4887 result = EDIT_WM_Char(es, charW);
4888 break;
4889 }
4890
4891 case WM_UNICHAR:
4892 if (wParam == UNICODE_NOCHAR) return TRUE;
4893 if (wParam <= 0x000fffff)
4894 {
4895 if (wParam > 0xffff) /* convert to surrogates */
4896 {
4897 wParam -= 0x10000;
4898 EDIT_WM_Char(es, (wParam >> 10) + 0xd800);
4899 EDIT_WM_Char(es, (wParam & 0x03ff) + 0xdc00);
4900 }
4901 else
4903 }
4904 return 0;
4905
4906 case WM_CLEAR:
4908 break;
4909
4910 case WM_CONTEXTMENU:
4911 EDIT_WM_ContextMenu(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
4912 break;
4913
4914 case WM_COPY:
4916 break;
4917
4918 case WM_CREATE:
4920 break;
4921
4922 case WM_CUT:
4923 EDIT_WM_Cut(es);
4924 break;
4925
4926 case WM_ENABLE:
4927 es->bEnableState = (BOOL) wParam;
4929 if (theme)
4931 break;
4932
4933 case WM_ERASEBKGND:
4934 /* we do the proper erase in EDIT_WM_Paint */
4935 result = 1;
4936 break;
4937
4938 case WM_GETFONT:
4939 result = (LRESULT)es->font;
4940 break;
4941
4942 case WM_GETTEXT:
4944 break;
4945
4946 case WM_GETTEXTLENGTH:
4948 break;
4949
4950 case WM_HSCROLL:
4952 break;
4953
4954 case WM_KEYDOWN:
4956 break;
4957
4958 case WM_KILLFOCUS:
4959 result = EDIT_WM_KillFocus(theme, es);
4960 break;
4961
4962 case WM_LBUTTONDBLCLK:
4964 break;
4965
4966 case WM_LBUTTONDOWN:
4968 break;
4969
4970 case WM_LBUTTONUP:
4972 break;
4973
4974 case WM_MBUTTONDOWN:
4976 break;
4977
4978 case WM_MOUSEMOVE:
4979 result = EDIT_WM_MouseMove(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
4980 break;
4981
4982 case WM_PRINTCLIENT:
4983 case WM_PAINT:
4985 break;
4986
4987 case WM_NCPAINT:
4988 EDIT_WM_NCPaint(hwnd, (HRGN)wParam);
4989 break;
4990
4991 case WM_PASTE:
4993 break;
4994
4995 case WM_SETFOCUS:
4996 EDIT_WM_SetFocus(theme, es);
4997 break;
4998
4999 case WM_SETFONT:
5001 break;
5002
5003 case WM_SETREDRAW:
5004 /* FIXME: actually set an internal flag and behave accordingly */
5005 break;
5006
5007 case WM_SETTEXT:
5008 EDIT_WM_SetText(es, (const WCHAR *)lParam);
5009 result = TRUE;
5010 break;
5011
5012 case WM_SIZE:
5014 break;
5015
5016 case WM_STYLECHANGED:
5018 break;
5019
5020 case WM_STYLECHANGING:
5021 result = 0; /* See EDIT_WM_StyleChanged */
5022 break;
5023
5024 case WM_SYSKEYDOWN:
5026 break;
5027
5028 case WM_TIMER:
5030 break;
5031
5032 case WM_VSCROLL:
5034 break;
5035
5036 case WM_MOUSEWHEEL:
5037 {
5038 int wheelDelta;
5039 UINT pulScrollLines = 3;
5040 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
5041
5042 if (wParam & (MK_SHIFT | MK_CONTROL))
5043 {
5045 break;
5046 }
5047
5048 wheelDelta = GET_WHEEL_DELTA_WPARAM(wParam);
5049 /* if scrolling changes direction, ignore left overs */
5050 if ((wheelDelta < 0 && es->wheelDeltaRemainder < 0) ||
5051 (wheelDelta > 0 && es->wheelDeltaRemainder > 0))
5052 es->wheelDeltaRemainder += wheelDelta;
5053 else
5054 es->wheelDeltaRemainder = wheelDelta;
5055
5056 if (es->wheelDeltaRemainder && pulScrollLines)
5057 {
5058 int cLineScroll;
5059 pulScrollLines = (int) min((UINT) es->line_count, pulScrollLines);
5060 cLineScroll = pulScrollLines * (float)es->wheelDeltaRemainder / WHEEL_DELTA;
5061 es->wheelDeltaRemainder -= WHEEL_DELTA * cLineScroll / (int)pulScrollLines;
5062 result = EDIT_EM_LineScroll(es, 0, -cLineScroll);
5063 }
5064 break;
5065 }
5066
5067 /* IME messages to make the edit control IME aware */
5068 case WM_IME_SETCONTEXT:
5069#ifdef __REACTOS__
5070 if (FALSE) /* FIXME: Condition */
5071 lParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
5072
5073 if (wParam)
5074 {
5075 HIMC hIMC = ImmGetContext(hwnd);
5077 if (pIC)
5078 {
5079 pIC->dwUIFlags &= ~0x40000;
5080 ImmUnlockIMC(hIMC);
5081 }
5082 if (FALSE) /* FIXME: Condition */
5084 ImmReleaseContext(hwnd, hIMC);
5085 }
5086
5088#endif
5089 break;
5090
5091 case WM_IME_STARTCOMPOSITION:
5092#ifdef __REACTOS__
5093 if (FALSE) /* FIXME: Condition */
5094 return TRUE;
5096#else
5097 es->composition_start = es->selection_end;
5098 es->composition_len = 0;
5099#endif
5100 break;
5101
5102 case WM_IME_COMPOSITION:
5104#ifdef __REACTOS__
5106#endif
5107 break;
5108
5109 case WM_IME_ENDCOMPOSITION:
5110#ifdef __REACTOS__
5112#else
5113 if (es->composition_len > 0)
5114 {
5116 es->selection_end = es->selection_start;
5117 es->composition_len= 0;
5118 }
5119#endif
5120 break;
5121
5123 break;
5124
5125 case WM_IME_SELECT:
5126#ifdef __REACTOS__
5128#endif
5129 break;
5130
5131 case WM_IME_CONTROL:
5132#ifdef __REACTOS__
5134#endif
5135 break;
5136
5137 case WM_IME_REQUEST:
5138 switch (wParam)
5139 {
5140 case IMR_QUERYCHARPOSITION:
5141 {
5142 IMECHARPOSITION *chpos = (IMECHARPOSITION *)lParam;
5143 LRESULT pos;
5144
5145 pos = EDIT_EM_PosFromChar(es, es->selection_start + chpos->dwCharPos, FALSE);
5146 chpos->pt.x = LOWORD(pos);
5147 chpos->pt.y = HIWORD(pos);
5148 chpos->cLineHeight = es->line_height;
5149 chpos->rcDocument = es->format_rect;
5150 MapWindowPoints(hwnd, 0, &chpos->pt, 1);
5151 MapWindowPoints(hwnd, 0, (POINT*)&chpos->rcDocument, 2);
5152 result = 1;
5153 break;
5154 }
5155 }
5156 break;
5157
5158 case WM_THEMECHANGED:
5159 CloseThemeData (theme);
5161 break;
5162
5163 default:
5165 break;
5166 }
5167
5168 if (IsWindow(hwnd) && es && msg != EM_GETHANDLE)
5170
5171 TRACE("hwnd=%p msg=%x -- 0x%08lx\n", hwnd, msg, result);
5172
5173 return result;
5174}
5176void EDIT_Register(void)
5177{
5178 WNDCLASSW wndClass;
5179
5180 memset(&wndClass, 0, sizeof(wndClass));
5182 wndClass.lpfnWndProc = EDIT_WindowProc;
5183 wndClass.cbClsExtra = 0;
5184#ifdef __i386__
5185 wndClass.cbWndExtra = sizeof(EDITSTATE *) + sizeof(WORD);
5186#else
5187 wndClass.cbWndExtra = sizeof(EDITSTATE *);
5188#endif
5189 wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_IBEAM);
5190 wndClass.hbrBackground = NULL;
5191 wndClass.lpszClassName = WC_EDITW;
5192 RegisterClassW(&wndClass);
5193}
5194
5195#ifdef __REACTOS__
5196void EDIT_Unregister(void)
5197{
5199}
5200#endif
static HRGN hrgn
static HBRUSH hbrush
signed int INT32
signed short INT16
Arabic default style
Definition: afstyles.h:94
static int bw
Definition: maze.c:120
static int state
Definition: maze.c:121
const DWORD ExStyle
Definition: appswitch.c:72
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define msg(x)
Definition: auth_time.c:54
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
int rev
Definition: sort.c:17
#define CF_UNICODETEXT
Definition: constants.h:408
#define index(s, c)
Definition: various.h:29
#define FIXME(fmt,...)
Definition: debug.h:114
#define WARN(fmt,...)
Definition: debug.h:115
#define ERR(fmt,...)
Definition: debug.h:113
w ll
Definition: byte_order.h:167
r l[0]
Definition: byte_order.h:168
return
Definition: dirsup.c:529
CFF_Charset charset
Definition: cffcmap.c:138
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
Definition: compstr.c:899
static HWND hwndParent
Definition: cryptui.c:300
DWORD HIMC
Definition: dimm.idl:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static LRESULT CALLBACK EDIT_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: edit.c:4621
static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc)
Definition: edit.c:3600
static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend, BOOL ctrl)
Definition: edit.c:1897
static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
Definition: edit.c:2180
static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es)
Definition: edit.c:4343
static BOOL EDIT_IsInsideDialog(EDITSTATE *es)
Definition: edit.c:2952
#define EF_MODIFIED
Definition: edit.c:70
static INT get_vertical_line_count(EDITSTATE *es)
Definition: edit.c:416
static INT EDIT_WordBreakProc(EDITSTATE *es, LPWSTR s, INT index, INT count, INT action)
Definition: edit.c:238
static LRESULT EDIT_WM_LButtonDblClk(EDITSTATE *es)
Definition: edit.c:3485
static void EDIT_MoveBackward(EDITSTATE *es, BOOL extend)
Definition: edit.c:1848
static LRESULT EDIT_WM_Char(EDITSTATE *es, WCHAR c)
Definition: edit.c:3055
static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw)
Definition: edit.c:3786
static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData(EDITSTATE *es, HDC dc, INT line)
Definition: edit.c:374
static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, const WCHAR *lpsz_replace, UINT strl, BOOL send_update, BOOL honor_limit)
Definition: edit.c:2485
#define EF_AFTER_WRAP
Definition: edit.c:75
static void EDIT_CalcLineWidth_SL(EDITSTATE *es)
Definition: edit.c:763
static LRESULT EDIT_WM_MButtonDown(EDITSTATE *es)
Definition: edit.c:3556
static void EDIT_EM_ScrollCaret(EDITSTATE *es)
Definition: edit.c:1778
#define ID_CB_LISTBOX
Definition: edit.c:79
static void EDIT_InvalidateUniscribeData_linedef(LINEDEF *line_def)
Definition: edit.c:308
#define ROUND_TO_GROW(size)
Definition: edit.c:64
static BOOL EDIT_CheckCombo(EDITSTATE *es, UINT msg, INT key)
Definition: edit.c:3256
static void EDIT_SetRectNP(EDITSTATE *es, const RECT *rc)
Definition: edit.c:2312
static BOOL EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol)
Definition: edit.c:2384
static void EDIT_WM_Copy(EDITSTATE *es)
Definition: edit.c:2999
static void EDIT_ML_InvalidateText(EDITSTATE *es, INT start, INT end)
Definition: edit.c:1392
static void EDIT_GetLineRect(EDITSTATE *es, INT line, INT scol, INT ecol, LPRECT rc)
Definition: edit.c:1145
static BOOL EDIT_EM_LineScroll_internal(EDITSTATE *es, INT dx, INT dy)
Definition: edit.c:1599
static void EDIT_SetCaretPos(EDITSTATE *es, INT pos, BOOL after_wrap)
Definition: edit.c:1748
static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es)
Definition: edit.c:4272
static void EDIT_BuildLineDefs_ML(EDITSTATE *es, INT istart, INT iend, INT delta, HRGN hrgn)
Definition: edit.c:431
static void EDIT_MoveUp_ML(EDITSTATE *es, BOOL extend)
Definition: edit.c:2023
static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col, INT count, BOOL rev)
Definition: edit.c:2106
static LRESULT EDIT_EM_CharFromPos(EDITSTATE *es, INT x, INT y)
Definition: edit.c:2356
static void EDIT_MoveHome(EDITSTATE *es, BOOL extend, BOOL ctrl)
Definition: edit.c:1943
static LRESULT EDIT_WM_HScroll(EDITSTATE *es, INT action, INT pos)
Definition: edit.c:4008
static void EDIT_WM_Cut(EDITSTATE *es)
Definition: edit.c:3043
static void EDIT_EM_SetPasswordChar(EDITSTATE *es, WCHAR c)
Definition: edit.c:2841
static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData_linedef(EDITSTATE *es, HDC dc, LINEDEF *line_def)
Definition: edit.c:332
#define EF_FOCUSED
Definition: edit.c:71
static void EDIT_WM_NCPaint(HWND hwnd, HRGN region)
Definition: edit.c:3689
struct tagLINEDEF LINEDEF
static void EDIT_AdjustFormatRect(EDITSTATE *es)
Definition: edit.c:2261
static INT EDIT_WM_GetText(const EDITSTATE *es, INT count, LPWSTR dst)
Definition: edit.c:3242
static void EDIT_WM_ContextMenu(EDITSTATE *es, INT x, INT y)
Definition: edit.c:3186
static LRESULT EDIT_WM_MouseMove(EDITSTATE *es, INT x, INT y)
Definition: edit.c:3568
static void EDIT_MovePageUp_ML(EDITSTATE *es, BOOL extend)
Definition: edit.c:1995
void EDIT_Register(void)
Definition: edit.c:5175
static void EDIT_LockBuffer(EDITSTATE *es)
Definition: edit.c:1209
static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force)
Definition: edit.c:1228
static LRESULT EDIT_WM_NCDestroy(EDITSTATE *es)
Definition: edit.c:4592
static LRESULT EDIT_WM_LButtonDown(EDITSTATE *es, DWORD keys, INT x, INT y)
Definition: edit.c:3514
static BOOL notify_parent(const EDITSTATE *es, INT code)
Definition: edit.c:168
static INT EDIT_EM_LineIndex(const EDITSTATE *es, INT line)
Definition: edit.c:944
static void EDIT_ConfinePoint(const EDITSTATE *es, LPINT x, LPINT y)
Definition: edit.c:903
static HLOCAL EDIT_EM_GetHandle(EDITSTATE *es)
Definition: edit.c:2406
static INT EDIT_EM_GetLine(EDITSTATE *es, INT line, LPWSTR dst)
Definition: edit.c:2426
#define EF_UPDATE
Definition: edit.c:72
static BOOL EDIT_EM_Undo(EDITSTATE *es)
Definition: edit.c:2911
static UINT get_text_length(EDITSTATE *es)
Definition: edit.c:218
static void EDIT_InvalidateUniscribeData(EDITSTATE *es)
Definition: edit.c:317
static void EDIT_WM_Paste(EDITSTATE *es)
Definition: edit.c:2963
#define EF_HSCROLL_TRACK
Definition: edit.c:74
static void EDIT_UpdateScrollInfo(EDITSTATE *es)
Definition: edit.c:1558
static void EDIT_MovePageDown_ML(EDITSTATE *es, BOOL extend)
Definition: edit.c:1967
static LRESULT EDIT_WM_KillFocus(HTHEME theme, EDITSTATE *es)
Definition: edit.c:3457
static void EDIT_MoveWordForward(EDITSTATE *es, BOOL extend)
Definition: edit.c:2076
static LRESULT EDIT_WM_SysKeyDown(EDITSTATE *es, INT key, DWORD key_data)
Definition: edit.c:3971
static LRESULT EDIT_EM_GetThumb(EDITSTATE *es)
Definition: edit.c:4260
static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs)
Definition: edit.c:4424
static LRESULT EDIT_WM_LButtonUp(EDITSTATE *es)
Definition: edit.c:3540
static void EDIT_WM_Clear(EDITSTATE *es)
Definition: edit.c:3028
static BOOL EDIT_EM_CanUndo(const EDITSTATE *es)
Definition: edit.c:183
static void EDIT_EM_EmptyUndoBuffer(EDITSTATE *es)
Definition: edit.c:194
static INT EDIT_CharFromPos(EDITSTATE *es, INT x, INT y, LPBOOL after_wrap)
Definition: edit.c:786
static void EDIT_EM_SetMargins(EDITSTATE *es, INT action, WORD left, WORD right, BOOL repaint)
Definition: edit.c:2773
static void EDIT_MoveWordBackward(EDITSTATE *es, BOOL extend)
Definition: edit.c:2045
static void text_buffer_changed(EDITSTATE *es)
Definition: edit.c:1196
#define EF_USE_SOFTBRK
Definition: edit.c:76
static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc)
Definition: edit.c:200
static void EDIT_WM_SetFocus(HTHEME theme, EDITSTATE *es)
Definition: edit.c:3751
#define HSCROLL_FRACTION
Definition: edit.c:65
static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc)
Definition: edit.c:2698
static LRESULT EDIT_WM_Create(EDITSTATE *es, const WCHAR *name)
Definition: edit.c:4537
static void EDIT_InvalidateText(EDITSTATE *es, INT start, INT end)
Definition: edit.c:1457
static LRESULT EDIT_WM_KeyDown(EDITSTATE *es, INT key)
Definition: edit.c:3318
static void EDIT_EM_SetLimitText(EDITSTATE *es, UINT limit)
Definition: edit.c:2737
static void EDIT_WM_Timer(EDITSTATE *es)
Definition: edit.c:3990
static LRESULT EDIT_EM_PosFromChar(EDITSTATE *es, INT index, BOOL after_wrap)
Definition: edit.c:1015
#define BUFLIMIT_INITIAL
Definition: edit.c:62
static void EDIT_MoveForward(EDITSTATE *es, BOOL extend)
Definition: edit.c:1918
#define EF_DIALOGMODE
Definition: edit.c:77
static LRESULT EDIT_EM_Scroll(EDITSTATE *es, INT action)
Definition: edit.c:1670
static LRESULT EDIT_EM_GetSel(const EDITSTATE *es, PUINT start, PUINT end)
Definition: edit.c:2464
static void EDIT_EM_SetWordBreakProc(EDITSTATE *es, EDITWORDBREAKPROCW wbp)
Definition: edit.c:2892
static void EDIT_SL_InvalidateText(EDITSTATE *es, INT start, INT end)
Definition: edit.c:1374
LINE_END
Definition: edit.c:82
@ END_SOFT
Definition: edit.c:86
@ END_RICH
Definition: edit.c:87
@ END_HARD
Definition: edit.c:85
@ END_0
Definition: edit.c:83
@ END_WRAP
Definition: edit.c:84
static void EDIT_MoveDown_ML(EDITSTATE *es, BOOL extend)
Definition: edit.c:1875
#define EF_VSCROLL_TRACK
Definition: edit.c:73
static LRESULT EDIT_WM_StyleChanged(EDITSTATE *es, WPARAM which, const STYLESTRUCT *style)
Definition: edit.c:3931
static INT EDIT_CallWordBreakProc(EDITSTATE *es, INT start, INT index, INT count, INT action)
Definition: edit.c:296
static INT EDIT_EM_LineFromChar(EDITSTATE *es, INT index)
Definition: edit.c:915
static void EDIT_ContextMenuCommand(EDITSTATE *es, UINT id)
Definition: edit.c:3142
#define ORDER_UINT(x, y)
Definition: edit.c:166
static LRESULT EDIT_WM_VScroll(EDITSTATE *es, INT action, INT pos)
Definition: edit.c:4140
static BOOL EDIT_MakeFit(EDITSTATE *es, UINT size)
Definition: edit.c:1274
static void EDIT_WM_SetText(EDITSTATE *es, LPCWSTR text)
Definition: edit.c:3856
static BOOL EDIT_MakeUndoFit(EDITSTATE *es, UINT size)
Definition: edit.c:1315
static void EDIT_UpdateTextRegion(EDITSTATE *es, HRGN hrgn, BOOL bErase)
Definition: edit.c:1342
static void EDIT_UpdateText(EDITSTATE *es, const RECT *rc, BOOL bErase)
Definition: edit.c:1357
static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, const INT *tabs)
Definition: edit.c:2870
static BOOL EDIT_EM_SetSel(EDITSTATE *es, UINT start, UINT end, BOOL after_wrap)
Definition: edit.c:1487
static void EDIT_ImeComposition(HWND hwnd, LPARAM CompFlag, EDITSTATE *es)
Definition: edit.c:4378
static BOOL EDIT_EM_LineScroll(EDITSTATE *es, INT dx, INT dy)
Definition: edit.c:1655
static void EDIT_WM_Size(EDITSTATE *es, UINT action)
Definition: edit.c:3898
static INT EDIT_EM_LineLength(EDITSTATE *es, INT index)
Definition: edit.c:979
static const WCHAR indent[]
Definition: object.c:1156
#define GetProcessHeap()
Definition: compat.h:736
#define HeapReAlloc
Definition: compat.h:734
#define CALLBACK
Definition: compat.h:35
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrcpynW
Definition: compat.h:738
BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
Definition: ime.c:1744
BOOL WINAPI ImmIsIME(HKL hKL)
Definition: ime.c:880
BOOL WINAPI ImmNotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD_PTR dwValue)
Definition: ime.c:907
BOOL WINAPI ImmSetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
Definition: ime.c:1583
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
Definition: imm.c:1066
HIMC WINAPI ImmGetContext(HWND hWnd)
Definition: imm.c:1044
BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
Definition: imm.c:1085
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
Definition: imm.c:1057
static void cleanup(void)
Definition: main.c:1335
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
const WCHAR * action
Definition: action.c:7479
const WCHAR * text
Definition: package.c:1799
HRESULT WINAPI ScriptStringFree(SCRIPT_STRING_ANALYSIS *pssa)
Definition: usp10.c:2556
HRESULT WINAPI ScriptStringGetLogicalWidths(SCRIPT_STRING_ANALYSIS ssa, int *piDx)
Definition: usp10.c:3804
HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, int cGlyphs, int iCharset, DWORD dwFlags, int iReqWidth, SCRIPT_CONTROL *psControl, SCRIPT_STATE *psState, const int *piDx, SCRIPT_TABDEF *pTabdef, const BYTE *pbInClass, SCRIPT_STRING_ANALYSIS *pssa)
Definition: usp10.c:1985
HRESULT WINAPI ScriptStringOut(SCRIPT_STRING_ANALYSIS ssa, int iX, int iY, UINT uOptions, const RECT *prc, int iMinSel, int iMaxSel, BOOL fDisabled)
Definition: usp10.c:2366
const SIZE *WINAPI ScriptString_pSize(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3876
const int *WINAPI ScriptString_pcOutChars(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3938
HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int *piCh, int *piTrailing)
Definition: usp10.c:2474
HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrailing, int *pX)
Definition: usp10.c:2411
HRESULT WINAPI ScriptBreak(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
Definition: usp10.c:3047
HRESULT WINAPI DrawThemeBackground(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect)
Definition: draw.c:128
BOOL WINAPI IsThemeBackgroundPartiallyTransparent(HTHEME hTheme, int iPartId, int iStateId)
Definition: draw.c:1883
HRESULT WINAPI DrawThemeParentBackground(HWND hwnd, HDC hdc, RECT *prc)
Definition: draw.c:72
HTHEME WINAPI OpenThemeData(HWND hwnd, LPCWSTR classlist)
Definition: system.c:835
HTHEME WINAPI GetWindowTheme(HWND hwnd)
Definition: system.c:851
HRESULT WINAPI CloseThemeData(HTHEME hTheme)
Definition: system.c:950
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
#define pt(x, y)
Definition: drawing.c:79
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
pKey DeleteObject()
LARGE_INTEGER li
Definition: fxtimerapi.cpp:235
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLdouble GLdouble right
Definition: glext.h:10859
GLint limit
Definition: glext.h:10326
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint left
Definition: glext.h:7726
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
HLOCAL NTAPI LocalReAlloc(HLOCAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:1625
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
LPVOID NTAPI LocalLock(HLOCAL hMem)
Definition: heapmem.c:1616
BOOL NTAPI LocalUnlock(HLOCAL hMem)
Definition: heapmem.c:1805
SIZE_T NTAPI LocalSize(HLOCAL hMem)
Definition: heapmem.c:1794
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
#define es
Definition: i386-dis.c:440
const char cursor[]
Definition: icontest.c:13
struct INPUTCONTEXTDX * LPINPUTCONTEXTDX
#define CFS_RECT
Definition: imm.h:324
#define CPS_CANCEL
Definition: imm.h:181
#define GCS_COMPATTR
Definition: imm.h:228
#define GCS_RESULTSTR
Definition: imm.h:234
#define CFS_POINT
Definition: imm.h:325
#define GCS_COMPSTR
Definition: imm.h:227
#define GCS_CURSORPOS
Definition: imm.h:230
#define NI_COMPOSITIONSTR
Definition: immdev.h:403
REFIID LPVOID DWORD_PTR dw
Definition: atlbase.h:40
#define FAILED(hr)
Definition: intsafe.h:51
#define d
Definition: ke_i.h:81
#define e
Definition: ke_i.h:82
#define c
Definition: ke_i.h:80
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
GLint dy
Definition: linetemp.h:97
if(dx< 0)
Definition: linetemp.h:194
GLint dx
Definition: linetemp.h:97
POINT cp
Definition: magnifier.c:59
static const WCHAR dc[]
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
struct task_struct * current
Definition: linux.c:32
static PVOID ptr
Definition: dispmode.c:27
HDC hdc
Definition: main.c:9
#define ES_COMBO
Definition: edit.c:29
static HDC
Definition: imagelist.c:92
static const WCHAR textW[]
Definition: itemdlg.c:1559
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static float(__cdecl *square_half_float)(float x
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
static BOOL is_cjk(void)
Definition: dde.c:46
#define shift
Definition: input.c:1755
WORD vk
Definition: input.c:77
#define ctrl
Definition: input.c:1756
static SCRIPT_CACHE SCRIPT_ANALYSIS * psa
Definition: usp10.c:64
static HTHEME(WINAPI *pOpenThemeDataEx)(HWND
#define min(a, b)
Definition: monoChain.cc:55
UINT_PTR HKL
Definition: msctf.idl:143
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
Definition: mk_font.cpp:20
unsigned int * PUINT
Definition: ndis.h:50
unsigned int UINT
Definition: ndis.h:50
#define BOOL
Definition: nt_native.h:43
#define OBJ_FONT
Definition: objidl.idl:1414
#define LRESULT
Definition: ole.h:14
#define LOWORD(l)
Definition: pedump.c:82
#define ES_PASSWORD
Definition: pedump.c:670
#define ES_READONLY
Definition: pedump.c:675
#define ES_LOWERCASE
Definition: pedump.c:669
#define ES_AUTOVSCROLL
Definition: pedump.c:671
#define ES_WANTRETURN
Definition: pedump.c:676
#define ES_UPPERCASE
Definition: pedump.c:668
#define WS_BORDER
Definition: pedump.c:625
#define ES_NOHIDESEL
Definition: pedump.c:673
#define WS_VSCROLL
Definition: pedump.c:627
#define ES_AUTOHSCROLL
Definition: pedump.c:672
long LONG
Definition: pedump.c:60
#define WS_DISABLED
Definition: pedump.c:621
#define WS_HSCROLL
Definition: pedump.c:628
#define ES_CENTER
Definition: pedump.c:665
#define ES_RIGHT
Definition: pedump.c:666
#define ES_MULTILINE
Definition: pedump.c:667
#define INT
Definition: polytest.cpp:20
#define WC_EDITW
Definition: commctrl.h:4687
void redraw(int x, int y, int cx, int cy)
Definition: qtewin.cpp:1248
static unsigned __int64 next
Definition: rand_nt.c:6
#define strchrW(s, c)
Definition: unicode.h:40
#define strlenW(s)
Definition: unicode.h:34
#define strcpyW(d, s)
Definition: unicode.h:35
#define EM_SCROLLCARET
Definition: richedit.h:81
#define WM_UNICHAR
Definition: richedit.h:67
#define EM_POSFROMCHAR
Definition: richedit.h:77
#define WM_CONTEXTMENU
Definition: richedit.h:64
#define EM_CHARFROMPOS
Definition: richedit.h:78
#define WM_PRINTCLIENT
Definition: richedit.h:70
#define EM_GETLIMITTEXT
Definition: richedit.h:74
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
& rect
Definition: startmenu.cpp:1413
RECT rcArea
Definition: dimm.idl:88
DWORD dwStyle
Definition: dimm.idl:86
POINT ptCurrentPos
Definition: dimm.idl:87
BYTE lfUnderline
Definition: dimm.idl:65
LONG cx
Definition: kdterminal.h:27
LPCWSTR lpszClassName
Definition: winuser.h:3185
HBRUSH hbrBackground
Definition: winuser.h:3183
int cbClsExtra
Definition: winuser.h:3178
UINT style
Definition: winuser.h:3176
WNDPROC lpfnWndProc
Definition: winuser.h:3177
int cbWndExtra
Definition: winuser.h:3179
HCURSOR hCursor
Definition: winuser.h:3182
Definition: ftp_var.h:139
Definition: inflate.c:139
Definition: copy.c:22
Definition: parser.c:49
Definition: name.c:39
INT width
Definition: edit.c:94
struct tagLINEDEF * next
Definition: edit.c:97
INT length
Definition: edit.c:91
SCRIPT_STRING_ANALYSIS ssa
Definition: edit.c:96
INT index
Definition: edit.c:95
INT net_length
Definition: edit.c:92
LINE_END ending
Definition: edit.c:93
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
int * pTabStops
Definition: usp10.h:173
Definition: time.h:68
#define max(a, b)
Definition: svc.c:63
static void buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
Definition: swimpl.c:888
#define WHEEL_DELTA
Definition: treelist.c:99
#define WM_MOUSEWHEEL
Definition: treelist.c:96
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
int32_t INT
Definition: typedefs.h:58
#define MAKELONG(a, b)
Definition: typedefs.h:249
#define HIWORD(l)
Definition: typedefs.h:247
#define SSA_TAB
Definition: usp10.h:34
#define SSA_FALLBACK
Definition: usp10.h:38
#define SSA_LINK
Definition: usp10.h:45
#define SSA_PASSWORD
Definition: usp10.h:33
#define SSA_GLYPHS
Definition: usp10.h:40
#define SCRIPT_UNDEFINED
Definition: usp10.h:69
@ EP_EDITTEXT
Definition: vsstyle.h:419
@ ETS_DISABLED
Definition: vsstyle.h:436
@ ETS_READONLY
Definition: vsstyle.h:438
@ ETS_NORMAL
Definition: vsstyle.h:433
@ ETS_FOCUSED
Definition: vsstyle.h:437
int ret
static GLenum which
Definition: wgl_font.c:159
LINE_END
Definition: edit.c:84
#define LMEM_MOVEABLE
Definition: winbase.h:369
#define LMEM_ZEROINIT
Definition: winbase.h:375
#define GMEM_MOVEABLE
Definition: winbase.h:294
#define GMEM_DDESHARE
Definition: winbase.h:298
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
BOOL * LPBOOL
Definition: windef.h:162
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
int * LPINT
Definition: windef.h:178
DWORD COLORREF
Definition: windef.h:300
#define HANGUL_CHARSET
Definition: wingdi.h:388
int WINAPI GetBkMode(_In_ HDC)
BOOL WINAPI GetTextMetricsW(_In_ HDC, _Out_ LPTEXTMETRICW)
Definition: text.c:221
HGDIOBJ WINAPI GetStockObject(_In_ int)
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
int WINAPI GetClipBox(_In_ HDC, _Out_ LPRECT)
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:999
HRGN WINAPI CreateRectRgn(_In_ int, _In_ int, _In_ int, _In_ int)
LONG WINAPI GdiGetCharDimensions(HDC, LPTEXTMETRICW, LONG *)
Definition: font.c:2145
COLORREF WINAPI GetTextColor(_In_ HDC)
Definition: text.c:861
int WINAPI IntersectClipRect(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
int WINAPI ExcludeClipRect(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int)
HGDIOBJ WINAPI GetCurrentObject(_In_ HDC, _In_ UINT)
Definition: dc.c:428
#define DEFAULT_GUI_FONT
Definition: wingdi.h:909
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
int WINAPI CombineRgn(_In_opt_ HRGN hrgnDest, _In_opt_ HRGN hrgnSrc1, _In_opt_ HRGN hrgnSrc2, _In_ int fnCombineMode)
#define TMPF_TRUETYPE
Definition: wingdi.h:1313
#define RGN_AND
Definition: wingdi.h:356
COLORREF WINAPI GetBkColor(_In_ HDC)
Definition: dc.c:978
#define PATCOPY
Definition: wingdi.h:335
#define CHINESEBIG5_CHARSET
Definition: wingdi.h:390
#define TMPF_VECTOR
Definition: wingdi.h:1312
#define OPAQUE
Definition: wingdi.h:949
#define RGN_OR
Definition: wingdi.h:359
BOOL WINAPI PatBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
BOOL WINAPI TextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_reads_(c) LPCWSTR lpString, _In_ int c)
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
HFONT WINAPI CreateFontIndirectW(_In_ const LOGFONTW *)
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1056
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:918
BOOL WINAPI SetRectRgn(_In_ HRGN, _In_ int, _In_ int, _In_ int, _In_ int)
#define SHIFTJIS_CHARSET
Definition: wingdi.h:386
#define GB2312_CHARSET
Definition: wingdi.h:389
BOOL WINAPI GetTextExtentPoint32W(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpString, _In_ int c, _Out_ LPSIZE psizl)
#define WM_PAINT
Definition: winuser.h:1620
HWND WINAPI GetFocus(void)
Definition: window.c:1893
HWND WINAPI SetCapture(_In_ HWND hWnd)
#define EM_SETREADONLY
Definition: winuser.h:2015
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define WM_ERASEBKGND
Definition: winuser.h:1625
DWORD WINAPI GetSysColor(_In_ int)
#define MAKEWPARAM(l, h)
Definition: winuser.h:4009
BOOL WINAPI CopyRect(_Out_ LPRECT, _In_ LPCRECT)
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define WM_CTLCOLORSTATIC
Definition: winuser.h:1772
#define MK_SHIFT
Definition: winuser.h:2369
#define WM_GETTEXTLENGTH
Definition: winuser.h:1619
#define EM_GETRECT
Definition: winuser.h:1996
HKL WINAPI GetKeyboardLayout(_In_ DWORD)
#define WM_IME_REQUEST
Definition: winuser.h:1836
#define WM_CLOSE
Definition: winuser.h:1621
BOOL WINAPI RedrawWindow(_In_opt_ HWND, _In_opt_ LPCRECT, _In_opt_ HRGN, _In_ UINT)
#define SB_THUMBTRACK
Definition: winuser.h:573
#define GetWindowLongPtrW
Definition: winuser.h:4829
BOOL WINAPI ShowCaret(_In_opt_ HWND)
#define EM_LINEFROMCHAR
Definition: winuser.h:2001
#define VK_TAB
Definition: winuser.h:2199
HDC WINAPI GetWindowDC(_In_opt_ HWND)
#define WM_ENABLE
Definition: winuser.h:1615
#define SM_CYEDGE
Definition: winuser.h:1009
#define SB_LINEUP
Definition: winuser.h:564
#define WM_HSCROLL
Definition: winuser.h:1743
#define WM_PASTE
Definition: winuser.h:1863
#define EN_KILLFOCUS
Definition: winuser.h:2025
#define COLOR_GRAYTEXT
Definition: winuser.h:932
#define EM_GETWORDBREAKPROC
Definition: winuser.h:1999
#define EM_FMTLINES
Definition: winuser.h:1986
BOOL WINAPI ReleaseCapture(void)
Definition: message.c:2890
#define EM_GETPASSWORDCHAR
Definition: winuser.h:1995
#define COLOR_WINDOWFRAME
Definition: winuser.h:919
#define DCX_WINDOW
Definition: winuser.h:2113
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define EC_RIGHTMARGIN
Definition: winuser.h:2607
#define SM_CXEDGE
Definition: winuser.h:1008
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
struct tagSCROLLINFO SCROLLINFO
#define WM_VSCROLL
Definition: winuser.h:1744
#define TPM_RIGHTBUTTON
Definition: winuser.h:2380
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
#define SIF_RANGE
Definition: winuser.h:1235
#define WM_CREATE
Definition: winuser.h:1608
#define DLGC_WANTCHARS
Definition: winuser.h:2618
#define CB_SHOWDROPDOWN
Definition: winuser.h:1970
#define EM_GETSEL
Definition: winuser.h:1997
#define EN_SETFOCUS
Definition: winuser.h:2027
#define EM_SETPASSWORDCHAR
Definition: winuser.h:2014
#define EN_UPDATE
Definition: winuser.h:2028
#define EM_GETMODIFY
Definition: winuser.h:1994
#define SB_PAGERIGHT
Definition: winuser.h:571
#define WB_ISDELIMITER
Definition: winuser.h:549
#define WM_SIZE
Definition: winuser.h:1611
#define COLOR_HIGHLIGHT
Definition: winuser.h:926
HBRUSH WINAPI GetSysColorBrush(_In_ int)
HANDLE WINAPI SetClipboardData(_In_ UINT, _In_opt_ HANDLE)
#define SB_VERT
Definition: winuser.h:553
#define EM_EMPTYUNDOBUFFER
Definition: winuser.h:1985
#define SB_LEFT
Definition: winuser.h:575
LONG WINAPI SetWindowLongW(_In_ HWND, _In_ int, _In_ LONG)
LONG WINAPI GetWindowLongW(_In_ HWND, _In_ int)
#define SB_BOTTOM
Definition: winuser.h:577
#define DLGC_WANTALLKEYS
Definition: winuser.h:2612
#define WM_LBUTTONDBLCLK
Definition: winuser.h:1778
#define WM_COMMAND
Definition: winuser.h:1740
#define SW_INVALIDATE
Definition: winuser.h:2579
#define EM_REPLACESEL
Definition: winuser.h:2006
#define EC_USEFONTINFO
Definition: winuser.h:2608
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
BOOL WINAPI CloseClipboard(void)
Definition: ntwrapper.h:178
#define VK_CONTROL
Definition: winuser.h:2203
#define EM_SETRECT
Definition: winuser.h:2016
#define DC_HASDEFID
Definition: winuser.h:2609
#define VK_UP
Definition: winuser.h:2225
BOOL WINAPI IsRectEmpty(_In_ LPCRECT)
#define WM_SETFOCUS
Definition: winuser.h:1613
#define SIF_PAGE
Definition: winuser.h:1233
#define WM_MOUSEMOVE
Definition: winuser.h:1775
#define WM_GETTEXT
Definition: winuser.h:1618
HDC WINAPI GetDCEx(_In_opt_ HWND, _In_opt_ HRGN, _In_ DWORD)
#define RDW_UPDATENOW
Definition: winuser.h:1220
HWND WINAPI GetCapture(void)
Definition: message.c:2881
#define RDW_ERASE
Definition: winuser.h:1211
#define TPM_NONOTIFY
Definition: winuser.h:2386
BOOL WINAPI OpenClipboard(_In_opt_ HWND)
#define WM_CUT
Definition: winuser.h:1861
#define SB_LINERIGHT
Definition: winuser.h:567
#define CS_DBLCLKS
Definition: winuser.h:651
#define EN_MAXTEXT
Definition: winuser.h:2026
#define WM_LBUTTONDOWN
Definition: winuser.h:1776
#define EM_LINEINDEX
Definition: winuser.h:2002
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2136
#define EN_HSCROLL
Definition: winuser.h:2024
HANDLE WINAPI GetClipboardData(_In_ UINT)
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
#define WM_GETFONT
Definition: winuser.h:1651
#define EM_LINESCROLL
Definition: winuser.h:2004
#define EM_GETFIRSTVISIBLELINE
Definition: winuser.h:1988
#define EM_GETHANDLE
Definition: winuser.h:1989
BOOL WINAPI ClientToScreen(_In_ HWND, _Inout_ LPPOINT)
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
#define WM_NEXTDLGCTL
Definition: winuser.h:1643
#define WM_UNDO
Definition: winuser.h:1865
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
#define VK_NEXT
Definition: winuser.h:2221
#define WM_NCCREATE
Definition: winuser.h:1683
#define WM_IME_SETCONTEXT
Definition: winuser.h:1829
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
#define WM_SETTEXT
Definition: winuser.h:1617
#define EM_CANUNDO
Definition: winuser.h:1983
#define EM_LINELENGTH
Definition: winuser.h:2003
#define SM_CYBORDER
Definition: winuser.h:965
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define DCX_INTERSECTRGN
Definition: winuser.h:2122
#define WM_IME_CHAR
Definition: winuser.h:1834
#define EM_SETHANDLE
Definition: winuser.h:2009
#define VK_RETURN
Definition: winuser.h:2201
#define EM_GETLINE
Definition: winuser.h:1991
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
#define EM_SETRECTNP
Definition: winuser.h:2017
#define SB_LINELEFT
Definition: winuser.h:566
HWND WINAPI SetFocus(_In_opt_ HWND)
#define SIZE_MAXIMIZED
Definition: winuser.h:2507
#define MF_ENABLED
Definition: winuser.h:128
#define MK_CONTROL
Definition: winuser.h:2370
#define EM_SETLIMITTEXT
Definition: winuser.h:2011
#define WB_LEFT
Definition: winuser.h:550
#define WM_SETFONT
Definition: winuser.h:1650
#define WM_TIMER
Definition: winuser.h:1742
#define VK_END
Definition: winuser.h:2222
#define TPM_LEFTALIGN
Definition: winuser.h:2377
#define VK_HOME
Definition: winuser.h:2223
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define MF_BYPOSITION
Definition: winuser.h:203
#define EM_UNDO
Definition: winuser.h:2021
#define SM_CXBORDER
Definition: winuser.h:964
#define DLGC_WANTARROWS
Definition: winuser.h:2610
#define SIF_DISABLENOSCROLL
Definition: winuser.h:1236
#define EM_SCROLL
Definition: winuser.h:2007
BOOL WINAPI IntersectRect(_Out_ LPRECT, _In_ LPCRECT, _In_ LPCRECT)
#define RDW_FRAME
Definition: winuser.h:1212
BOOL WINAPI EmptyClipboard(void)
Definition: ntwrapper.h:190
#define SB_PAGEDOWN
Definition: winuser.h:569
#define EM_SETWORDBREAKPROC
Definition: winuser.h:2020
#define IDC_IBEAM
Definition: winuser.h:688
#define VK_BACK
Definition: winuser.h:2198
#define COLOR_HIGHLIGHTTEXT
Definition: winuser.h:927
HDC WINAPI GetDC(_In_opt_ HWND)
BOOL WINAPI InvalidateRgn(_In_ HWND, _In_opt_ HRGN, _In_ BOOL)
#define SB_LINEDOWN
Definition: winuser.h:565
#define EM_SETSEL
Definition: winuser.h:2018
DWORD WINAPI CharUpperBuffW(_Inout_updates_(cchLength) LPWSTR lpsz, _In_ DWORD cchLength)
#define VK_F4
Definition: winuser.h:2258
int(CALLBACK * EDITWORDBREAKPROCW)(LPWSTR, int, int, int)
Definition: winuser.h:2905
#define CB_GETDROPPEDSTATE
Definition: winuser.h:1945
#define ES_NUMBER
Definition: winuser.h:301
#define WM_LBUTTONUP
Definition: winuser.h:1777
#define WB_RIGHT
Definition: winuser.h:551
BOOL WINAPI SystemParametersInfoW(_In_ UINT uiAction, _In_ UINT uiParam, _Inout_opt_ PVOID pvParam, _In_ UINT fWinIni)
#define WM_IME_COMPOSITIONFULL
Definition: winuser.h:1832
#define WM_CHAR
Definition: winuser.h:1717
BOOL WINAPI SetRectEmpty(_Out_ LPRECT)
BOOL WINAPI IsWindowEnabled(_In_ HWND)
HWND WINAPI GetParent(_In_ HWND)
BOOL WINAPI DestroyMenu(_In_ HMENU)
#define CS_GLOBALCLASS
Definition: winuser.h:652
#define VK_LEFT
Definition: winuser.h:2224
#define WM_NCDESTROY
Definition: winuser.h:1684
#define VK_RIGHT
Definition: winuser.h:2226
#define SIZE_RESTORED
Definition: winuser.h:2505
#define SB_TOP
Definition: winuser.h:578
#define EN_VSCROLL
Definition: winuser.h:2029
#define CB_GETEXTENDEDUI
Definition: winuser.h:1948
#define SIF_POS
Definition: winuser.h:1234
#define VK_DOWN
Definition: winuser.h:2227
#define GWLP_ID
Definition: winuser.h:860
#define WM_COPY
Definition: winuser.h:1862
#define EM_GETTHUMB
Definition: winuser.h:1998
#define SB_ENDSCROLL
Definition: winuser.h:574
#define EM_GETMARGINS
Definition: winuser.h:1993
#define WM_IME_CONTROL
Definition: winuser.h:1831
BOOL WINAPI OffsetRect(_Inout_ LPRECT, _In_ int, _In_ int)
#define VK_SHIFT
Definition: winuser.h:2202
#define EM_SETTABSTOPS
Definition: winuser.h:2019
#define DLGC_WANTMESSAGE
Definition: winuser.h:2613
BOOL WINAPI TrackPopupMenu(_In_ HMENU, _In_ UINT, _In_ int, _In_ int, _Reserved_ int, _In_ HWND, _Reserved_ LPCRECT)
#define VK_PRIOR
Definition: winuser.h:2220
int WINAPI SetScrollInfo(_In_ HWND, _In_ int, _In_ LPCSCROLLINFO, _In_ BOOL)
#define VK_DELETE
Definition: winuser.h:2233
#define WM_IME_SELECT
Definition: winuser.h:1833
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
#define WS_EX_CLIENTEDGE
Definition: winuser.h:384
#define WM_CLEAR
Definition: winuser.h:1864
#define WM_KEYDOWN
Definition: winuser.h:1715
#define CB_SETEXTENDEDUI
Definition: winuser.h:1964
#define EM_GETLINECOUNT
Definition: winuser.h:1992
#define SB_RIGHT
Definition: winuser.h:576
BOOL WINAPI SetCaretPos(_In_ int, _In_ int)
int WINAPI GetScrollPos(_In_ HWND, _In_ int)
BOOL WINAPI CreateCaret(_In_ HWND, _In_opt_ HBITMAP, _In_ int, _In_ int)
BOOL WINAPI DestroyCaret(void)
Definition: caret.c:35
BOOL WINAPI InvalidateRect(_In_opt_ HWND, _In_opt_ LPCRECT, _In_ BOOL)
#define EC_LEFTMARGIN
Definition: winuser.h:2606
#define DM_GETDEFID
Definition: winuser.h:2098
#define TPM_RETURNCMD
Definition: winuser.h:2387
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
#define SystemParametersInfo
Definition: winuser.h:5858
#define SetWindowLongPtrW
Definition: winuser.h:5346
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
#define EN_ERRSPACE
Definition: winuser.h:2023
#define GWL_STYLE
Definition: winuser.h:852
#define CS_PARENTDC
Definition: winuser.h:656
#define EM_SETMARGINS
Definition: winuser.h:2012
#define WM_CTLCOLOREDIT
Definition: winuser.h:1767
#define VK_ESCAPE
Definition: winuser.h:2214
#define DLGC_HASSETSEL
Definition: winuser.h:2614
BOOL WINAPI EnableMenuItem(_In_ HMENU, _In_ UINT, _In_ UINT)
int WINAPI ScrollWindowEx(_In_ HWND, _In_ int, _In_ int, _In_opt_ LPCRECT, _In_opt_ LPCRECT, _In_opt_ HRGN, _Out_opt_ LPRECT, _In_ UINT)
#define WM_KILLFOCUS
Definition: winuser.h:1614
int WINAPI GetSystemMetrics(_In_ int)
#define SB_PAGEUP
Definition: winuser.h:568
#define WM_SYSKEYDOWN
Definition: winuser.h:1719
BOOL WINAPI IsClipboardFormatAvailable(_In_ UINT)
#define VK_INSERT
Definition: winuser.h:2232
#define RDW_INVALIDATE
Definition: winuser.h:1214
#define WM_GETDLGCODE
Definition: winuser.h:1689
#define WM_MBUTTONDOWN
Definition: winuser.h:1782
#define EM_SETMODIFY
Definition: winuser.h:2013
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define SB_HORZ
Definition: winuser.h:552
SHORT WINAPI GetKeyState(_In_ int)
#define VK_MENU
Definition: winuser.h:2204
#define WM_NCPAINT
Definition: winuser.h:1687
#define WS_EX_RIGHT
Definition: winuser.h:400
#define SB_PAGELEFT
Definition: winuser.h:570
#define GWL_EXSTYLE
Definition: winuser.h:851
#define MF_GRAYED
Definition: winuser.h:129
#define EN_CHANGE
Definition: winuser.h:2022
#define WM_SETREDRAW
Definition: winuser.h:1616
DWORD WINAPI CharLowerBuffW(_Inout_updates_(cchLength) LPWSTR lpsz, _In_ DWORD cchLength)
#define SB_THUMBPOSITION
Definition: winuser.h:572
LONG WINAPI TabbedTextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_reads_(chCount) LPCWSTR lpString, _In_ int chCount, _In_ int nTabPositions, _In_reads_opt_(nTabPositions) CONST INT *lpnTabStopPositions, _In_ int nTabOrigin)
HMENU WINAPI LoadMenuA(_In_opt_ HINSTANCE, _In_ LPCSTR)
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185