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