ReactOS 0.4.16-dev-1339-gd8bfa93
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 (IS_IME_HKL(hKL))
1766 EDIT_ImmSetCompositionWindow(es, pt);
1767#else
1768 TRACE("%d - %dx%d\n", pos, (short)LOWORD(res), (short)HIWORD(res));
1769 SetCaretPos((short)LOWORD(res), (short)HIWORD(res));
1770#endif
1771}
1772
1773
1774/*********************************************************************
1775 *
1776 * EM_SCROLLCARET
1777 *
1779static void EDIT_EM_ScrollCaret(EDITSTATE *es)
1780{
1781 if (es->style & ES_MULTILINE) {
1782 INT l;
1783 INT vlc;
1784 INT ww;
1785 INT cw = es->char_width;
1786 INT x;
1787 INT dy = 0;
1788 INT dx = 0;
1789
1790 l = EDIT_EM_LineFromChar(es, es->selection_end);
1791 x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP));
1793 if (l >= es->y_offset + vlc)
1794 dy = l - vlc + 1 - es->y_offset;
1795 if (l < es->y_offset)
1796 dy = l - es->y_offset;
1797 ww = es->format_rect.right - es->format_rect.left;
1798 if (x < es->format_rect.left)
1799 dx = x - es->format_rect.left - ww / HSCROLL_FRACTION / cw * cw;
1800 if (x > es->format_rect.right)
1801 dx = x - es->format_rect.left - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
1802 if (dy || dx || (es->y_offset && (es->line_count - es->y_offset < vlc)))
1803 {
1804 /* check if we are going to move too far */
1805 if(es->x_offset + dx + ww > es->text_width)
1806 dx = es->text_width - ww - es->x_offset;
1807 if(dx || dy || (es->y_offset && (es->line_count - es->y_offset < vlc)))
1809 }
1810 } else {
1811 INT x;
1812 INT goal;
1813 INT format_width;
1814
1815 x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
1816 format_width = es->format_rect.right - es->format_rect.left;
1817 if (x < es->format_rect.left) {
1818 goal = es->format_rect.left + format_width / HSCROLL_FRACTION;
1819 do {
1820 es->x_offset--;
1821 x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
1822 } while ((x < goal) && es->x_offset);
1823 /* FIXME: use ScrollWindow() somehow to improve performance */
1825 } else if (x > es->format_rect.right) {
1826 INT x_last;
1828 goal = es->format_rect.right - format_width / HSCROLL_FRACTION;
1829 do {
1830 es->x_offset++;
1831 x = (short)LOWORD(EDIT_EM_PosFromChar(es, es->selection_end, FALSE));
1833 } while ((x > goal) && (x_last > es->format_rect.right));
1834 /* FIXME: use ScrollWindow() somehow to improve performance */
1836 }
1837 }
1838
1839 EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP);
1840}
1841
1842
1843/*********************************************************************
1844 *
1845 * EDIT_MoveBackward
1846 *
1848static void EDIT_MoveBackward(EDITSTATE *es, BOOL extend)
1849{
1850 INT e = es->selection_end;
1851
1852 if (e) {
1853 e--;
1854 if ((es->style & ES_MULTILINE) && e &&
1855 (es->text[e - 1] == '\r') && (es->text[e] == '\n')) {
1856 e--;
1857 if (e && (es->text[e - 1] == '\r'))
1858 e--;
1859 }
1860 }
1861 EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
1863}
1864
1865
1866/*********************************************************************
1867 *
1868 * EDIT_MoveDown_ML
1869 *
1870 * Only for multi line controls
1871 * Move the caret one line down, on a column with the nearest
1872 * x coordinate on the screen (might be a different column).
1873 *
1875static void EDIT_MoveDown_ML(EDITSTATE *es, BOOL extend)
1876{
1877 INT s = es->selection_start;
1878 INT e = es->selection_end;
1879 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
1880 LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
1881 INT x = (short)LOWORD(pos);
1882 INT y = (short)HIWORD(pos);
1883
1884 e = EDIT_CharFromPos(es, x, y + es->line_height, &after_wrap);
1885 if (!extend)
1886 s = e;
1887 EDIT_EM_SetSel(es, s, e, after_wrap);
1889}
1890
1891
1892/*********************************************************************
1893 *
1894 * EDIT_MoveEnd
1895 *
1897static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend, BOOL ctrl)
1898{
1899 BOOL after_wrap = FALSE;
1900 INT e;
1901
1902 /* Pass a high value in x to make sure of receiving the end of the line */
1903 if (!ctrl && (es->style & ES_MULTILINE))
1904 e = EDIT_CharFromPos(es, 0x3fffffff,
1905 HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), &after_wrap);
1906 else
1907 e = get_text_length(es);
1908 EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, after_wrap);
1910}
1911
1912
1913/*********************************************************************
1914 *
1915 * EDIT_MoveForward
1916 *
1918static void EDIT_MoveForward(EDITSTATE *es, BOOL extend)
1919{
1920 INT e = es->selection_end;
1921
1922 if (es->text[e]) {
1923 e++;
1924 if ((es->style & ES_MULTILINE) && (es->text[e - 1] == '\r')) {
1925 if (es->text[e] == '\n')
1926 e++;
1927 else if ((es->text[e] == '\r') && (es->text[e + 1] == '\n'))
1928 e += 2;
1929 }
1930 }
1931 EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
1933}
1934
1935
1936/*********************************************************************
1937 *
1938 * EDIT_MoveHome
1939 *
1940 * Home key: move to beginning of line.
1941 *
1943static void EDIT_MoveHome(EDITSTATE *es, BOOL extend, BOOL ctrl)
1944{
1945 INT e;
1946
1947 /* Pass the x_offset in x to make sure of receiving the first position of the line */
1948 if (!ctrl && (es->style & ES_MULTILINE))
1949 e = EDIT_CharFromPos(es, -es->x_offset,
1950 HIWORD(EDIT_EM_PosFromChar(es, es->selection_end, es->flags & EF_AFTER_WRAP)), NULL);
1951 else
1952 e = 0;
1953 EDIT_EM_SetSel(es, extend ? es->selection_start : e, e, FALSE);
1955}
1956
1957
1958/*********************************************************************
1959 *
1960 * EDIT_MovePageDown_ML
1961 *
1962 * Only for multi line controls
1963 * Move the caret one page down, on a column with the nearest
1964 * x coordinate on the screen (might be a different column).
1965 *
1967static void EDIT_MovePageDown_ML(EDITSTATE *es, BOOL extend)
1968{
1969 INT s = es->selection_start;
1970 INT e = es->selection_end;
1971 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
1972 LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
1973 INT x = (short)LOWORD(pos);
1974 INT y = (short)HIWORD(pos);
1975
1977 y + (es->format_rect.bottom - es->format_rect.top),
1978 &after_wrap);
1979 if (!extend)
1980 s = e;
1981 EDIT_EM_SetSel(es, s, e, after_wrap);
1983}
1984
1985
1986/*********************************************************************
1987 *
1988 * EDIT_MovePageUp_ML
1989 *
1990 * Only for multi line controls
1991 * Move the caret one page up, on a column with the nearest
1992 * x coordinate on the screen (might be a different column).
1993 *
1995static void EDIT_MovePageUp_ML(EDITSTATE *es, BOOL extend)
1996{
1997 INT s = es->selection_start;
1998 INT e = es->selection_end;
1999 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
2000 LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
2001 INT x = (short)LOWORD(pos);
2002 INT y = (short)HIWORD(pos);
2003
2005 y - (es->format_rect.bottom - es->format_rect.top),
2006 &after_wrap);
2007 if (!extend)
2008 s = e;
2009 EDIT_EM_SetSel(es, s, e, after_wrap);
2011}
2012
2013
2014/*********************************************************************
2015 *
2016 * EDIT_MoveUp_ML
2017 *
2018 * Only for multi line controls
2019 * Move the caret one line up, on a column with the nearest
2020 * x coordinate on the screen (might be a different column).
2021 *
2023static void EDIT_MoveUp_ML(EDITSTATE *es, BOOL extend)
2024{
2025 INT s = es->selection_start;
2026 INT e = es->selection_end;
2027 BOOL after_wrap = (es->flags & EF_AFTER_WRAP);
2028 LRESULT pos = EDIT_EM_PosFromChar(es, e, after_wrap);
2029 INT x = (short)LOWORD(pos);
2030 INT y = (short)HIWORD(pos);
2031
2032 e = EDIT_CharFromPos(es, x, y - es->line_height, &after_wrap);
2033 if (!extend)
2034 s = e;
2035 EDIT_EM_SetSel(es, s, e, after_wrap);
2037}
2038
2039
2040/*********************************************************************
2041 *
2042 * EDIT_MoveWordBackward
2043 *
2045static void EDIT_MoveWordBackward(EDITSTATE *es, BOOL extend)
2046{
2047 INT s = es->selection_start;
2048 INT e = es->selection_end;
2049 INT l;
2050 INT ll;
2051 INT li;
2052
2056 if (e - li == 0) {
2057 if (l) {
2058 li = EDIT_EM_LineIndex(es, l - 1);
2059 e = li + EDIT_EM_LineLength(es, li);
2060 }
2061 } else {
2063 }
2064 if (!extend)
2065 s = e;
2068}
2069
2070
2071/*********************************************************************
2072 *
2073 * EDIT_MoveWordForward
2074 *
2076static void EDIT_MoveWordForward(EDITSTATE *es, BOOL extend)
2077{
2078 INT s = es->selection_start;
2079 INT e = es->selection_end;
2080 INT l;
2081 INT ll;
2082 INT li;
2083
2087 if (e - li == ll) {
2088 if ((es->style & ES_MULTILINE) && (l != es->line_count - 1))
2089 e = EDIT_EM_LineIndex(es, l + 1);
2090 } else {
2092 li, e - li + 1, ll, WB_RIGHT);
2093 }
2094 if (!extend)
2095 s = e;
2098}
2099
2100
2101/*********************************************************************
2102 *
2103 * EDIT_PaintText
2104 *
2107{
2108 COLORREF BkColor;
2109 COLORREF TextColor;
2110 LOGFONTW underline_font;
2111 HFONT hUnderline = 0;
2112 HFONT old_font = 0;
2113 INT ret;
2114 INT li;
2115 INT BkMode;
2116 SIZE size;
2117
2118 if (!count)
2119 return 0;
2120 BkMode = GetBkMode(dc);
2121 BkColor = GetBkColor(dc);
2122 TextColor = GetTextColor(dc);
2123 if (rev) {
2124#ifdef __REACTOS__
2125 if (TRUE)
2126#else
2127 if (es->composition_len == 0)
2128#endif
2129 {
2132 SetBkMode( dc, OPAQUE);
2133 }
2134 else
2135 {
2137 GetObjectW(current,sizeof(LOGFONTW),&underline_font);
2138 underline_font.lfUnderline = TRUE;
2139 hUnderline = CreateFontIndirectW(&underline_font);
2140 old_font = SelectObject(dc,hUnderline);
2141 }
2142 }
2144 if (es->style & ES_MULTILINE) {
2145 ret = (INT)LOWORD(TabbedTextOutW(dc, x, y, es->text + li + col, count,
2146 es->tabs_count, es->tabs, es->format_rect.left - es->x_offset));
2147 } else {
2148 TextOutW(dc, x, y, es->text + li + col, count);
2149 GetTextExtentPoint32W(dc, es->text + li + col, count, &size);
2150 ret = size.cx;
2151 }
2152 if (rev) {
2153#ifdef __REACTOS__
2154 if (TRUE)
2155#else
2156 if (es->composition_len == 0)
2157#endif
2158 {
2159 SetBkColor(dc, BkColor);
2160 SetTextColor(dc, TextColor);
2161 SetBkMode( dc, BkMode);
2162 }
2163 else
2164 {
2165 if (old_font)
2166 SelectObject(dc,old_font);
2167 if (hUnderline)
2168 DeleteObject(hUnderline);
2169 }
2170 }
2171 return ret;
2172}
2173
2174
2175/*********************************************************************
2176 *
2177 * EDIT_PaintLine
2178 *
2180static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
2181{
2182 INT s = 0;
2183 INT e = 0;
2184 INT li = 0;
2185 INT ll = 0;
2186 INT x;
2187 INT y;
2188 LRESULT pos;
2190
2191 if (es->style & ES_MULTILINE) {
2193
2194 if ((line < es->y_offset) || (line > es->y_offset + vlc) || (line >= es->line_count))
2195 return;
2196 } else if (line)
2197 return;
2198
2199 TRACE("line=%d\n", line);
2200
2203 x = (short)LOWORD(pos);
2204 y = (short)HIWORD(pos);
2205
2206 if (es->style & ES_MULTILINE)
2207 {
2208 int line_idx = line;
2209 x = -es->x_offset;
2210 if (es->style & ES_RIGHT || es->style & ES_CENTER)
2211 {
2212 LINEDEF *line_def = es->first_line_def;
2213 int w, lw;
2214
2215 while (line_def && line_idx)
2216 {
2217 line_def = line_def->next;
2218 line_idx--;
2219 }
2220 w = es->format_rect.right - es->format_rect.left;
2221 lw = line_def->width;
2222
2223 if (es->style & ES_RIGHT)
2224 x = w - (lw - x);
2225 else if (es->style & ES_CENTER)
2226 x += (w - lw) / 2;
2227 }
2228 x += es->format_rect.left;
2229 }
2230
2231 if (rev)
2232 {
2235 s = min(es->selection_start, es->selection_end);
2236 e = max(es->selection_start, es->selection_end);
2237 s = min(li + ll, max(li, s));
2238 e = min(li + ll, max(li, e));
2239 }
2240
2241 if (ssa)
2242 ScriptStringOut(ssa, x, y, 0, &es->format_rect, s - li, e - li, FALSE);
2243 else if (rev && (s != e) &&
2244 ((es->flags & EF_FOCUSED) || (es->style & ES_NOHIDESEL))) {
2245 x += EDIT_PaintText(es, dc, x, y, line, 0, s - li, FALSE);
2246 x += EDIT_PaintText(es, dc, x, y, line, s - li, e - s, TRUE);
2247 x += EDIT_PaintText(es, dc, x, y, line, e - li, li + ll - e, FALSE);
2248 } else
2249 x += EDIT_PaintText(es, dc, x, y, line, 0, ll, FALSE);
2250
2251 if (es->cue_banner_text && es->text_length == 0 && (!(es->flags & EF_FOCUSED) || es->cue_banner_draw_focused))
2252 {
2254 TextOutW(dc, x, y, es->cue_banner_text, lstrlenW(es->cue_banner_text));
2255 }
2256}
2257
2258
2259/*********************************************************************
2260 *
2261 * EDIT_AdjustFormatRect
2262 *
2263 * Adjusts the format rectangle for the current font and the
2264 * current client rectangle.
2265 *
2268{
2269 RECT ClientRect;
2270
2271 es->format_rect.right = max(es->format_rect.right, es->format_rect.left + es->char_width);
2272 if (es->style & ES_MULTILINE)
2273 {
2274 INT fw, vlc, max_x_offset, max_y_offset;
2275
2277 es->format_rect.bottom = es->format_rect.top + vlc * es->line_height;
2278
2279 /* correct es->x_offset */
2280 fw = es->format_rect.right - es->format_rect.left;
2281 max_x_offset = es->text_width - fw;
2282 if(max_x_offset < 0) max_x_offset = 0;
2283 if(es->x_offset > max_x_offset)
2284 es->x_offset = max_x_offset;
2285
2286 /* correct es->y_offset */
2287 max_y_offset = es->line_count - vlc;
2288 if(max_y_offset < 0) max_y_offset = 0;
2289 if(es->y_offset > max_y_offset)
2290 es->y_offset = max_y_offset;
2291
2292 /* force scroll info update */
2294 }
2295 else
2296 /* Windows doesn't care to fix text placement for SL controls */
2297 es->format_rect.bottom = es->format_rect.top + es->line_height;
2298
2299 /* Always stay within the client area */
2300 GetClientRect(es->hwndSelf, &ClientRect);
2301 es->format_rect.bottom = min(es->format_rect.bottom, ClientRect.bottom);
2302
2303 if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL))
2305
2306 EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP);
2307}
2308
2309
2310/*********************************************************************
2311 *
2312 * EDIT_SetRectNP
2313 *
2314 * note: this is not (exactly) the handler called on EM_SETRECTNP
2315 * it is also used to set the rect of a single line control
2316 *
2318static void EDIT_SetRectNP(EDITSTATE *es, const RECT *rc)
2319{
2321 INT bw, bh;
2323
2324 CopyRect(&es->format_rect, rc);
2325
2326 if (ExStyle & WS_EX_CLIENTEDGE) {
2327 es->format_rect.left++;
2328 es->format_rect.right--;
2329
2330 if (es->format_rect.bottom - es->format_rect.top
2331 >= es->line_height + 2)
2332 {
2333 es->format_rect.top++;
2334 es->format_rect.bottom--;
2335 }
2336 }
2337 else if (es->style & WS_BORDER) {
2339 bh = GetSystemMetrics(SM_CYBORDER) + 1;
2340 InflateRect(&es->format_rect, -bw, 0);
2341 if (es->format_rect.bottom - es->format_rect.top >= es->line_height + 2 * bh)
2342 InflateRect(&es->format_rect, 0, -bh);
2343 }
2344
2345 es->format_rect.left += es->left_margin;
2346 es->format_rect.right -= es->right_margin;
2348}
2349
2350
2351/*********************************************************************
2352 *
2353 * EM_CHARFROMPOS
2354 *
2355 * returns line number (not index) in high-order word of result.
2356 * NB : Q137805 is unclear about this. POINT * pointer in lParam apply
2357 * to Richedit, not to the edit control. Original documentation is valid.
2358 * FIXME: do the specs mean to return -1 if outside client area or
2359 * if outside formatting rectangle ???
2360 *
2363{
2364 POINT pt;
2365 RECT rc;
2366 INT index;
2367
2368 pt.x = x;
2369 pt.y = y;
2370 GetClientRect(es->hwndSelf, &rc);
2371 if (!PtInRect(&rc, pt))
2372 return -1;
2373
2376}
2377
2378
2379/*********************************************************************
2380 *
2381 * EM_FMTLINES
2382 *
2383 * Enable or disable soft breaks.
2384 *
2385 * This means: insert or remove the soft linebreak character (\r\r\n).
2386 * Take care to check if the text still fits the buffer after insertion.
2387 * If not, notify with EN_ERRSPACE.
2388 *
2390static BOOL EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol)
2391{
2392 es->flags &= ~EF_USE_SOFTBRK;
2393 if (add_eol) {
2394 es->flags |= EF_USE_SOFTBRK;
2395 FIXME("soft break enabled, not implemented\n");
2396 }
2397 return add_eol;
2398}
2399
2400
2401/*********************************************************************
2402 *
2403 * EM_GETHANDLE
2404 *
2405 * Hopefully this won't fire back at us.
2406 * We always start with a fixed buffer in the local heap.
2407 * Despite of the documentation says that the local heap is used
2408 * only if DS_LOCALEDIT flag is set, NT and 2000 always allocate
2409 * buffer on the local heap.
2410 *
2413{
2414 if (!(es->style & ES_MULTILINE))
2415 return 0;
2416
2418
2419 /* The text buffer handle belongs to the app */
2420 es->hlocapp = es->hloc32W;
2421
2422 TRACE("Returning %p, LocalSize() = %ld\n", es->hlocapp, LocalSize(es->hlocapp));
2423 return es->hlocapp;
2424}
2425
2426
2427/*********************************************************************
2428 *
2429 * EM_GETLINE
2430 *
2433{
2434 INT line_len, dst_len;
2435 LPWSTR src;
2436 INT i;
2437
2438 if (es->style & ES_MULTILINE)
2439 {
2440 if (line >= es->line_count)
2441 return 0;
2442 }
2443 else
2444 line = 0;
2445
2447 src = es->text + i;
2448 line_len = EDIT_EM_LineLength(es, i);
2449 dst_len = *(WORD *)dst;
2450
2451 if (dst_len <= line_len)
2452 {
2453 memcpy(dst, src, dst_len * sizeof(WCHAR));
2454 return dst_len;
2455 }
2456 else /* Append 0 if enough space */
2457 {
2458 memcpy(dst, src, line_len * sizeof(WCHAR));
2459 dst[line_len] = 0;
2460 return line_len;
2461 }
2462}
2463
2464
2465/*********************************************************************
2466 *
2467 * EM_GETSEL
2468 *
2471{
2472 UINT s = es->selection_start;
2473 UINT e = es->selection_end;
2474
2475 ORDER_UINT(s, e);
2476 if (start)
2477 *start = s;
2478 if (end)
2479 *end = e;
2480 return MAKELONG(s, e);
2481}
2482
2483
2484/*********************************************************************
2485 *
2486 * EM_REPLACESEL
2487 *
2488 * FIXME: handle ES_NUMBER and ES_OEMCONVERT here
2489 *
2491static void EDIT_EM_ReplaceSel(EDITSTATE *es, BOOL can_undo, const WCHAR *lpsz_replace, UINT strl,
2492 BOOL send_update, BOOL honor_limit)
2493{
2494 UINT tl = get_text_length(es);
2495 UINT utl;
2496 UINT s;
2497 UINT e;
2498 UINT i;
2499 UINT size;
2500 LPWSTR p;
2501 HRGN hrgn = 0;
2502 LPWSTR buf = NULL;
2503 UINT bufl;
2504
2505 TRACE("%s, can_undo %d, send_update %d\n",
2506 debugstr_wn(lpsz_replace, strl), can_undo, send_update);
2507
2508 s = es->selection_start;
2509 e = es->selection_end;
2510
2512 if ((s == e) && !strl)
2513 return;
2514
2515 ORDER_UINT(s, e);
2516
2517 size = tl - (e - s) + strl;
2518 if (!size)
2519 es->text_width = 0;
2520
2521 /* Issue the EN_MAXTEXT notification and continue with replacing text
2522 * so that buffer limit is honored. */
2523 if ((honor_limit) && (size > es->buffer_limit))
2524 {
2525 if (!notify_parent(es, EN_MAXTEXT)) return;
2526 /* Buffer limit can be smaller than the actual length of text in combobox */
2527 if (es->buffer_limit < (tl - (e-s)))
2528 strl = 0;
2529 else
2530 strl = min(strl, es->buffer_limit - (tl - (e-s)));
2531 }
2532
2533 if (!EDIT_MakeFit(es, tl - (e - s) + strl))
2534 return;
2535
2536 if (e != s) {
2537 /* there is something to be deleted */
2538 TRACE("deleting stuff.\n");
2539 bufl = e - s;
2540 buf = heap_alloc((bufl + 1) * sizeof(WCHAR));
2541 if (!buf) return;
2542 memcpy(buf, es->text + s, bufl * sizeof(WCHAR));
2543 buf[bufl] = 0; /* ensure 0 termination */
2544 /* now delete */
2545 lstrcpyW(es->text + s, es->text + e);
2547 }
2548 if (strl) {
2549 /* there is an insertion */
2550 tl = get_text_length(es);
2551 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));
2552 for (p = es->text + tl ; p >= es->text + s ; p--)
2553 p[strl] = p[0];
2554 for (i = 0 , p = es->text + s ; i < strl ; i++)
2555 p[i] = lpsz_replace[i];
2556 if(es->style & ES_UPPERCASE)
2557 CharUpperBuffW(p, strl);
2558 else if(es->style & ES_LOWERCASE)
2559 CharLowerBuffW(p, strl);
2561 }
2562 if (es->style & ES_MULTILINE)
2563 {
2564 INT st = min(es->selection_start, es->selection_end);
2566
2567 hrgn = CreateRectRgn(0, 0, 0, 0);
2568 EDIT_BuildLineDefs_ML(es, st, st + strl,
2569 strl - abs(es->selection_end - es->selection_start), hrgn);
2570 /* if text is too long undo all changes */
2571 if (honor_limit && !(es->style & ES_AUTOVSCROLL) && (es->line_count > vlc)) {
2572 if (strl)
2573 lstrcpyW(es->text + e, es->text + e + strl);
2574 if (e != s)
2575 for (i = 0 , p = es->text ; i < e - s ; i++)
2576 p[i + s] = buf[i];
2579 abs(es->selection_end - es->selection_start) - strl, hrgn);
2580 strl = 0;
2581 e = s;
2582 SetRectRgn(hrgn, 0, 0, 0, 0);
2583 if (!notify_parent(es, EN_MAXTEXT)) return;
2584 }
2585 }
2586 else {
2587 INT fw = es->format_rect.right - es->format_rect.left;
2590 /* remove chars that don't fit */
2591 if (honor_limit && !(es->style & ES_AUTOHSCROLL) && (es->text_width > fw)) {
2592#ifdef __REACTOS__
2593 while ((es->text_width > fw) && s + strl > 0) {
2594#else
2595 while ((es->text_width > fw) && s + strl >= s) {
2596#endif
2597 lstrcpyW(es->text + s + strl - 1, es->text + s + strl);
2598 strl--;
2599 es->text_length = -1;
2602 }
2604 if (!notify_parent(es, EN_MAXTEXT)) return;
2605 }
2606 }
2607
2608 if (e != s) {
2609 if (can_undo) {
2610 utl = lstrlenW(es->undo_text);
2611 if (!es->undo_insert_count && (*es->undo_text && (s == es->undo_position))) {
2612 /* undo-buffer is extended to the right */
2613 EDIT_MakeUndoFit(es, utl + e - s);
2614 memcpy(es->undo_text + utl, buf, (e - s)*sizeof(WCHAR));
2615 (es->undo_text + utl)[e - s] = 0; /* ensure 0 termination */
2616 } else if (!es->undo_insert_count && (*es->undo_text && (e == es->undo_position))) {
2617 /* undo-buffer is extended to the left */
2618 EDIT_MakeUndoFit(es, utl + e - s);
2619 for (p = es->undo_text + utl ; p >= es->undo_text ; p--)
2620 p[e - s] = p[0];
2621 for (i = 0 , p = es->undo_text ; i < e - s ; i++)
2622 p[i] = buf[i];
2623 es->undo_position = s;
2624 } else {
2625 /* new undo-buffer */
2626 EDIT_MakeUndoFit(es, e - s);
2627 memcpy(es->undo_text, buf, (e - s)*sizeof(WCHAR));
2628 es->undo_text[e - s] = 0; /* ensure 0 termination */
2629 es->undo_position = s;
2630 }
2631 /* any deletion makes the old insertion-undo invalid */
2632 es->undo_insert_count = 0;
2633 } else
2635 }
2636 if (strl) {
2637 if (can_undo) {
2638 if ((s == es->undo_position) ||
2639 ((es->undo_insert_count) &&
2640 (s == es->undo_position + es->undo_insert_count)))
2641 /*
2642 * insertion is new and at delete position or
2643 * an extension to either left or right
2644 */
2645 es->undo_insert_count += strl;
2646 else {
2647 /* new insertion undo */
2648 es->undo_position = s;
2649 es->undo_insert_count = strl;
2650 /* new insertion makes old delete-buffer invalid */
2651 *es->undo_text = '\0';
2652 }
2653 } else
2655 }
2656
2657 heap_free(buf);
2658
2659 s += strl;
2660
2661 /* If text has been deleted and we're right or center aligned then scroll rightward */
2662 if (es->style & (ES_RIGHT | ES_CENTER))
2663 {
2664 INT delta = strl - abs(es->selection_end - es->selection_start);
2665
2666 if (delta < 0 && es->x_offset)
2667 {
2668 if (abs(delta) > es->x_offset)
2669 es->x_offset = 0;
2670 else
2671 es->x_offset += delta;
2672 }
2673 }
2674
2676 es->flags |= EF_MODIFIED;
2677 if (send_update) es->flags |= EF_UPDATE;
2678 if (hrgn)
2679 {
2682 }
2683 else
2685
2687
2688 /* force scroll info update */
2690
2691
2692 if(send_update || (es->flags & EF_UPDATE))
2693 {
2694 es->flags &= ~EF_UPDATE;
2695 if (!notify_parent(es, EN_CHANGE)) return;
2696 }
2698}
2699
2700
2701/*********************************************************************
2702 *
2703 * EM_SETHANDLE
2704 *
2705 * FIXME: ES_LOWERCASE, ES_UPPERCASE, ES_OEMCONVERT, ES_NUMBER ???
2706 *
2708static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc)
2709{
2710 if (!(es->style & ES_MULTILINE))
2711 return;
2712
2713 if (!hloc)
2714 return;
2715
2716#ifdef __REACTOS__
2717 if (es->text)
2718#endif
2720
2721 es->hloc32W = hloc;
2722 es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
2723
2724 /* The text buffer handle belongs to the control */
2725 es->hlocapp = NULL;
2726
2729
2730 es->x_offset = es->y_offset = 0;
2731 es->selection_start = es->selection_end = 0;
2733 es->flags &= ~EF_MODIFIED;
2734 es->flags &= ~EF_UPDATE;
2738 /* force scroll info update */
2740}
2741
2742
2743/*********************************************************************
2744 *
2745 * EM_SETLIMITTEXT
2746 *
2747 * NOTE: this version currently implements WinNT limits
2748 *
2751{
2752 if (!limit) limit = ~0u;
2753 if (!(es->style & ES_MULTILINE)) limit = min(limit, 0x7ffffffe);
2754 es->buffer_limit = limit;
2755}
2757static BOOL is_cjk(HDC dc)
2758{
2761
2762 switch (GdiGetCodePage(dc)) {
2763 case 932: case 936: case 949: case 950: case 1361:
2764 return TRUE;
2765 default:
2766 return (GetTextCharsetInfo(dc, &fs, 0) != DEFAULT_CHARSET &&
2767 (fs.fsCsb[0] & FS_DBCS_MASK));
2768 }
2769}
2771static int get_cjk_fontinfo_margin(int width, int side_bearing)
2772{
2773 int margin;
2774 if (side_bearing < 0)
2775 margin = min(-side_bearing, width/2);
2776 else
2777 margin = 0;
2778 return margin;
2779}
2783};
2784
2785/* Undocumented gdi32 export */
2787
2788/*********************************************************************
2789 *
2790 * EM_SETMARGINS
2791 *
2792 * EC_USEFONTINFO is used as a left or right value i.e. lParam and not as an
2793 * action wParam despite what the docs say. EC_USEFONTINFO calculates the
2794 * margin according to the textmetrics of the current font.
2795 *
2796 * When EC_USEFONTINFO is used, the margins only change if the edit control is
2797 * equal to or larger than a certain size. The empty client rect is treated as
2798 * 80 pixels width.
2801 WORD left, WORD right, BOOL repaint)
2802{
2804 INT default_left_margin = 0; /* in pixels */
2805 INT default_right_margin = 0; /* in pixels */
2806
2807 /* Set the default margins depending on the font */
2808 if (es->font && (left == EC_USEFONTINFO || right == EC_USEFONTINFO)) {
2809 HDC dc = GetDC(es->hwndSelf);
2810 HFONT old_font = SelectObject(dc, es->font);
2811 LONG width = GdiGetCharDimensions(dc, &tm, NULL), rc_width;
2812 RECT rc;
2813
2814 /* The default margins are only non zero for TrueType or Vector fonts */
2815 if (tm.tmPitchAndFamily & ( TMPF_VECTOR | TMPF_TRUETYPE )) {
2816 struct char_width_info width_info;
2817
2818 if (is_cjk(dc) && GetCharWidthInfo(dc, &width_info))
2819 {
2820 default_left_margin = get_cjk_fontinfo_margin(width, width_info.min_lsb);
2821 default_right_margin = get_cjk_fontinfo_margin(width, width_info.min_rsb);
2822 }
2823 else
2824 {
2825 default_left_margin = width / 2;
2826 default_right_margin = width / 2;
2827 }
2828
2829 GetClientRect(es->hwndSelf, &rc);
2830 rc_width = !IsRectEmpty(&rc) ? rc.right - rc.left : 80;
2831 if (rc_width < default_left_margin + default_right_margin + width * 2) {
2832 default_left_margin = es->left_margin;
2833 default_right_margin = es->right_margin;
2834 }
2835 }
2836 SelectObject(dc, old_font);
2837 ReleaseDC(es->hwndSelf, dc);
2838 }
2839
2840 if (action & EC_LEFTMARGIN) {
2841 es->format_rect.left -= es->left_margin;
2842 if (left != EC_USEFONTINFO)
2843 es->left_margin = left;
2844 else
2845 es->left_margin = default_left_margin;
2846 es->format_rect.left += es->left_margin;
2847 }
2848
2849 if (action & EC_RIGHTMARGIN) {
2850 es->format_rect.right += es->right_margin;
2851 if (right != EC_USEFONTINFO)
2852 es->right_margin = right;
2853 else
2854 es->right_margin = default_right_margin;
2855 es->format_rect.right -= es->right_margin;
2856 }
2857
2860 if (repaint) EDIT_UpdateText(es, NULL, TRUE);
2861 }
2862
2863 TRACE("left=%d, right=%d\n", es->left_margin, es->right_margin);
2864}
2865
2866
2867/*********************************************************************
2868 *
2869 * EM_SETPASSWORDCHAR
2870 *
2873{
2874 LONG style;
2875
2876 if (es->style & ES_MULTILINE)
2877 return;
2878
2879 if (es->password_char == c)
2880 return;
2881
2882 style = GetWindowLongW( es->hwndSelf, GWL_STYLE );
2883 es->password_char = c;
2884 if (c) {
2885 SetWindowLongW( es->hwndSelf, GWL_STYLE, style | ES_PASSWORD );
2886 es->style |= ES_PASSWORD;
2887 } else {
2888 SetWindowLongW( es->hwndSelf, GWL_STYLE, style & ~ES_PASSWORD );
2889 es->style &= ~ES_PASSWORD;
2890 }
2893}
2894
2895
2896/*********************************************************************
2897 *
2898 * EM_SETTABSTOPS
2899 *
2901static BOOL EDIT_EM_SetTabStops(EDITSTATE *es, INT count, const INT *tabs)
2902{
2903 if (!(es->style & ES_MULTILINE))
2904 return FALSE;
2905 heap_free(es->tabs);
2906 es->tabs_count = count;
2907 if (!count)
2908 es->tabs = NULL;
2909 else {
2910 es->tabs = heap_alloc(count * sizeof(INT));
2911 memcpy(es->tabs, tabs, count * sizeof(INT));
2912 }
2914 return TRUE;
2915}
2916
2917
2918/*********************************************************************
2919 *
2920 * EM_SETWORDBREAKPROC
2921 *
2924{
2925 if (es->word_break_proc == wbp)
2926 return;
2927
2928 es->word_break_proc = wbp;
2929
2930 if ((es->style & ES_MULTILINE) && !(es->style & ES_AUTOHSCROLL)) {
2933 }
2934}
2935
2936
2937/*********************************************************************
2938 *
2939 * EM_UNDO / WM_UNDO
2940 *
2943{
2944 INT ulength;
2945 LPWSTR utext;
2946
2947 /* As per MSDN spec, for a single-line edit control,
2948 the return value is always TRUE */
2949 if( es->style & ES_READONLY )
2950 return !(es->style & ES_MULTILINE);
2951
2952 ulength = lstrlenW(es->undo_text);
2953
2954 utext = heap_alloc((ulength + 1) * sizeof(WCHAR));
2955
2956 lstrcpyW(utext, es->undo_text);
2957
2958 TRACE("before UNDO:insertion length = %d, deletion buffer = %s\n",
2959 es->undo_insert_count, debugstr_w(utext));
2960
2961 EDIT_EM_SetSel(es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
2963 EDIT_EM_ReplaceSel(es, TRUE, utext, ulength, TRUE, TRUE);
2964 EDIT_EM_SetSel(es, es->undo_position, es->undo_position + es->undo_insert_count, FALSE);
2965 /* send the notification after the selection start and end are set */
2966 if (!notify_parent(es, EN_CHANGE)) return TRUE;
2968 heap_free(utext);
2969
2970 TRACE("after UNDO:insertion length = %d, deletion buffer = %s\n",
2971 es->undo_insert_count, debugstr_w(es->undo_text));
2972 return TRUE;
2973}
2974
2975
2976/* Helper function for WM_CHAR
2977 *
2978 * According to an MSDN blog article titled "Just because you're a control
2979 * doesn't mean that you're necessarily inside a dialog box," multiline edit
2980 * controls without ES_WANTRETURN would attempt to detect whether it is inside
2981 * a dialog box or not.
2983static inline BOOL EDIT_IsInsideDialog(EDITSTATE *es)
2984{
2985 return (es->flags & EF_DIALOGMODE);
2986}
2987
2988
2989/*********************************************************************
2990 *
2991 * WM_PASTE
2992 *
2994static void EDIT_WM_Paste(EDITSTATE *es)
2995{
2996 HGLOBAL hsrc;
2997 LPWSTR src, ptr;
2998 int len;
2999
3000 /* Protect read-only edit control from modification */
3001 if(es->style & ES_READONLY)
3002 return;
3003
3004 OpenClipboard(es->hwndSelf);
3005 if ((hsrc = GetClipboardData(CF_UNICODETEXT))) {
3006 src = GlobalLock(hsrc);
3007 len = lstrlenW(src);
3008 /* Protect single-line edit against pasting new line character */
3009 if (!(es->style & ES_MULTILINE) && ((ptr = wcschr(src, '\n')))) {
3010 len = ptr - src;
3011 if (len && src[len - 1] == '\r')
3012 --len;
3013 }
3015 GlobalUnlock(hsrc);
3016 }
3017 else if (es->style & ES_PASSWORD) {
3018 /* clear selected text in password edit box even with empty clipboard */
3020 }
3022}
3023
3024
3025/*********************************************************************
3026 *
3027 * WM_COPY
3028 *
3030static void EDIT_WM_Copy(EDITSTATE *es)
3031{
3032 INT s = min(es->selection_start, es->selection_end);
3033 INT e = max(es->selection_start, es->selection_end);
3034 HGLOBAL hdst;
3035 LPWSTR dst;
3036 DWORD len;
3037
3038 if (e == s) return;
3039
3040 len = e - s;
3041 hdst = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (len + 1) * sizeof(WCHAR));
3042 dst = GlobalLock(hdst);
3043 memcpy(dst, es->text + s, len * sizeof(WCHAR));
3044 dst[len] = 0; /* ensure 0 termination */
3045 TRACE("%s\n", debugstr_w(dst));
3046 GlobalUnlock(hdst);
3047 OpenClipboard(es->hwndSelf);
3051}
3052
3053
3054/*********************************************************************
3055 *
3056 * WM_CLEAR
3057 *
3059static inline void EDIT_WM_Clear(EDITSTATE *es)
3060{
3061 /* Protect read-only edit control from modification */
3062 if(es->style & ES_READONLY)
3063 return;
3064
3066}
3067
3068
3069/*********************************************************************
3070 *
3071 * WM_CUT
3072 *
3074static inline void EDIT_WM_Cut(EDITSTATE *es)
3075{
3078}
3079
3080
3081/*********************************************************************
3082 *
3083 * WM_CHAR
3084 *
3087{
3088 BOOL control;
3089
3090#ifdef __REACTOS__
3091 if (es->bCaptureState)
3092 return 0;
3093#endif
3094
3095 control = GetKeyState(VK_CONTROL) & 0x8000;
3096
3097 switch (c) {
3098 case '\r':
3099 /* If it's not a multiline edit box, it would be ignored below.
3100 * For multiline edit without ES_WANTRETURN, we have to make a
3101 * special case.
3102 */
3103 if ((es->style & ES_MULTILINE) && !(es->style & ES_WANTRETURN))
3105 break;
3106 case '\n':
3107 if (es->style & ES_MULTILINE) {
3108 if (es->style & ES_READONLY) {
3111 } else {
3112 static const WCHAR cr_lfW[] = {'\r','\n'};
3113 EDIT_EM_ReplaceSel(es, TRUE, cr_lfW, 2, TRUE, TRUE);
3114 }
3115 }
3116 break;
3117 case '\t':
3118 if ((es->style & ES_MULTILINE) && !(es->style & ES_READONLY))
3119 {
3120 static const WCHAR tabW[] = {'\t'};
3122 break;
3123 EDIT_EM_ReplaceSel(es, TRUE, tabW, 1, TRUE, TRUE);
3124 }
3125 break;
3126 case VK_BACK:
3127 if (!(es->style & ES_READONLY) && !control) {
3128 if (es->selection_start != es->selection_end)
3130 else {
3131 /* delete character left of caret */
3132 EDIT_EM_SetSel(es, (UINT)-1, 0, FALSE);
3135 }
3136 }
3137 break;
3138 case 0x03: /* ^C */
3139 if (!(es->style & ES_PASSWORD))
3140 SendMessageW(es->hwndSelf, WM_COPY, 0, 0);
3141 break;
3142 case 0x16: /* ^V */
3143 if (!(es->style & ES_READONLY))
3144 SendMessageW(es->hwndSelf, WM_PASTE, 0, 0);
3145 break;
3146 case 0x18: /* ^X */
3147 if (!((es->style & ES_READONLY) || (es->style & ES_PASSWORD)))
3148 SendMessageW(es->hwndSelf, WM_CUT, 0, 0);
3149 break;
3150 case 0x1A: /* ^Z */
3151 if (!(es->style & ES_READONLY))
3152 SendMessageW(es->hwndSelf, WM_UNDO, 0, 0);
3153 break;
3154
3155 default:
3156 /*If Edit control style is ES_NUMBER allow users to key in only numeric values*/
3157 if( (es->style & ES_NUMBER) && !( c >= '0' && c <= '9') )
3158 break;
3159
3160 if (!(es->style & ES_READONLY) && (c >= ' ') && (c != 127))
3162 break;
3163 }
3164 return 1;
3165}
3166
3167
3168/*********************************************************************
3169 *
3170 * EDIT_ContextMenuCommand
3171 *
3173static void EDIT_ContextMenuCommand(EDITSTATE *es, UINT id)
3174{
3175 switch (id) {
3176 case EM_UNDO:
3177 SendMessageW(es->hwndSelf, WM_UNDO, 0, 0);
3178 break;
3179 case WM_CUT:
3180 SendMessageW(es->hwndSelf, WM_CUT, 0, 0);
3181 break;
3182 case WM_COPY:
3183 SendMessageW(es->hwndSelf, WM_COPY, 0, 0);
3184 break;
3185 case WM_PASTE:
3186 SendMessageW(es->hwndSelf, WM_PASTE, 0, 0);
3187 break;
3188 case WM_CLEAR:
3189 SendMessageW(es->hwndSelf, WM_CLEAR, 0, 0);
3190 break;
3191 case EM_SETSEL:
3192 SendMessageW(es->hwndSelf, EM_SETSEL, 0, -1);
3193 break;
3194 default:
3195 ERR("unknown menu item, please report\n");
3196 break;
3197 }
3198}
3199
3200
3201/*********************************************************************
3202 *
3203 * WM_CONTEXTMENU
3204 *
3205 * Note: the resource files resource/sysres_??.rc cannot define a
3206 * single popup menu. Hence we use a (dummy) menubar
3207 * containing the single popup menu as its first item.
3208 *
3209 * FIXME: the message identifiers have been chosen arbitrarily,
3210 * hence we use MF_BYPOSITION.
3211 * We might as well use the "real" values (anybody knows ?)
3212 * The menu definition is in resources/sysres_??.rc.
3213 * Once these are OK, we better use MF_BYCOMMAND here
3214 * (as we do in EDIT_WM_Command()).
3215 *
3217static void EDIT_WM_ContextMenu(EDITSTATE *es, INT x, INT y)
3218{
3219 HMENU menu = LoadMenuA(GetModuleHandleA("user32.dll"), "EDITMENU");
3220 HMENU popup = GetSubMenu(menu, 0);
3221 UINT start = es->selection_start;
3222 UINT end = es->selection_end;
3223 UINT cmd;
3224 POINT pt;
3225
3227
3228 /* undo */
3230 /* cut */
3231 EnableMenuItem(popup, 2, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
3232 /* copy */
3233 EnableMenuItem(popup, 3, MF_BYPOSITION | ((end - start) && !(es->style & ES_PASSWORD) ? MF_ENABLED : MF_GRAYED));
3234 /* paste */
3236 /* delete */
3237 EnableMenuItem(popup, 5, MF_BYPOSITION | ((end - start) && !(es->style & ES_READONLY) ? MF_ENABLED : MF_GRAYED));
3238 /* select all */
3240
3241 pt.x = x;
3242 pt.y = y;
3243
3244 if (pt.x == -1 && pt.y == -1) /* passed via VK_APPS press/release */
3245 {
3246 RECT rc;
3247
3248 /* Windows places the menu at the edit's center in this case */
3249 GetClientRect(es->hwndSelf, &rc);
3250 pt.x = rc.left + (rc.right - rc.left) / 2;
3251 pt.y = rc.top + (rc.bottom - rc.top) / 2;
3252 ClientToScreen(es->hwndSelf, &pt);
3253 }
3254
3255 if (!(es->flags & EF_FOCUSED))
3256 SetFocus(es->hwndSelf);
3257
3259 pt.x, pt.y, 0, es->hwndSelf, NULL);
3260
3261 if (cmd)
3263
3264 DestroyMenu(menu);
3265}
3266
3267
3268/*********************************************************************
3269 *
3270 * WM_GETTEXT
3271 *
3274{
3275 if (!count)
3276 return 0;
3277
3278 lstrcpynW(dst, es->text, count);
3279 return lstrlenW(dst);
3280}
3281
3282/*********************************************************************
3283 *
3284 * EDIT_CheckCombo
3285 *
3288{
3289 HWND hLBox = es->hwndListBox;
3290 HWND hCombo;
3291 BOOL bDropped;
3292 int nEUI;
3293
3294 if (!hLBox)
3295 return FALSE;
3296
3297 hCombo = GetParent(es->hwndSelf);
3298 bDropped = TRUE;
3299 nEUI = 0;
3300
3301 TRACE("[%p]: handling msg %x (%x)\n", es->hwndSelf, msg, key);
3302
3303 if (key == VK_UP || key == VK_DOWN)
3304 {
3305 if (SendMessageW(hCombo, CB_GETEXTENDEDUI, 0, 0))
3306 nEUI = 1;
3307
3308 if (msg == WM_KEYDOWN || nEUI)
3309 bDropped = (BOOL)SendMessageW(hCombo, CB_GETDROPPEDSTATE, 0, 0);
3310 }
3311
3312 switch (msg)
3313 {
3314 case WM_KEYDOWN:
3315 if (!bDropped && nEUI && (key == VK_UP || key == VK_DOWN))
3316 {
3317 /* make sure ComboLBox pops up */
3318 SendMessageW(hCombo, CB_SETEXTENDEDUI, FALSE, 0);
3319 key = VK_F4;
3320 nEUI = 2;
3321 }
3322
3323 SendMessageW(hLBox, WM_KEYDOWN, key, 0);
3324 break;
3325
3326 case WM_SYSKEYDOWN: /* Handle Alt+up/down arrows */
3327 if (nEUI)
3328 SendMessageW(hCombo, CB_SHOWDROPDOWN, !bDropped, 0);
3329 else
3330 SendMessageW(hLBox, WM_KEYDOWN, VK_F4, 0);
3331 break;
3332 }
3333
3334 if (nEUI == 2)
3335 SendMessageW(hCombo, CB_SETEXTENDEDUI, TRUE, 0);
3336
3337 return TRUE;
3338}
3339
3340
3341/*********************************************************************
3342 *
3343 * WM_KEYDOWN
3344 *
3345 * Handling of special keys that don't produce a WM_CHAR
3346 * (i.e. non-printable keys) & Backspace & Delete
3347 *
3350{
3351 BOOL shift;
3352 BOOL control;
3353
3354 if (GetKeyState(VK_MENU) & 0x8000)
3355 return 0;
3356
3357 shift = GetKeyState(VK_SHIFT) & 0x8000;
3358 control = GetKeyState(VK_CONTROL) & 0x8000;
3359
3360 switch (key) {
3361 case VK_F4:
3362 case VK_UP:
3364 break;
3365
3366 /* fall through */
3367 case VK_LEFT:
3368 if ((es->style & ES_MULTILINE) && (key == VK_UP))
3370 else
3371 if (control)
3373 else
3375 break;
3376 case VK_DOWN:
3378 break;
3379 /* fall through */
3380 case VK_RIGHT:
3381 if ((es->style & ES_MULTILINE) && (key == VK_DOWN))
3383 else if (control)
3385 else
3387 break;
3388 case VK_HOME:
3390 break;
3391 case VK_END:
3393 break;
3394 case VK_PRIOR:
3395 if (es->style & ES_MULTILINE)
3397 else
3399 break;
3400 case VK_NEXT:
3401 if (es->style & ES_MULTILINE)
3403 else
3405 break;
3406 case VK_DELETE:
3407 if (!(es->style & ES_READONLY) && !(shift && control)) {
3408 if (es->selection_start != es->selection_end) {
3409 if (shift)
3410 EDIT_WM_Cut(es);
3411 else
3413 } else {
3414 EDIT_EM_SetSel(es, ~0u, 0, FALSE);
3415 if (shift)
3416 /* delete character left of caret */
3418 else if (control)
3419 /* delete to end of line */
3421 else
3422 /* delete character right of caret */
3425 }
3426 }
3427 break;
3428 case VK_INSERT:
3429 if (shift) {
3430 if (!(es->style & ES_READONLY))
3432 } else if (control)
3434 break;
3435 case VK_RETURN:
3436 /* If the edit doesn't want the return send a message to the default object */
3437 if(!(es->style & ES_MULTILINE) || !(es->style & ES_WANTRETURN))
3438 {
3439 DWORD dw;
3440
3441 if (!EDIT_IsInsideDialog(es)) break;
3442 if (control) break;
3443 dw = SendMessageW(es->hwndParent, DM_GETDEFID, 0, 0);
3444 if (HIWORD(dw) == DC_HASDEFID)
3445 {
3446 HWND hwDefCtrl = GetDlgItem(es->hwndParent, LOWORD(dw));
3447 if (hwDefCtrl)
3448 {
3449 SendMessageW(es->hwndParent, WM_NEXTDLGCTL, (WPARAM)hwDefCtrl, TRUE);
3450 PostMessageW(hwDefCtrl, WM_KEYDOWN, VK_RETURN, 0);
3451 }
3452 }
3453 }
3454 break;
3455 case VK_ESCAPE:
3456 if ((es->style & ES_MULTILINE) && EDIT_IsInsideDialog(es))
3457 PostMessageW(es->hwndParent, WM_CLOSE, 0, 0);
3458 break;
3459 case VK_TAB:
3460 if ((es->style & ES_MULTILINE) && EDIT_IsInsideDialog(es))
3461 SendMessageW(es->hwndParent, WM_NEXTDLGCTL, shift, 0);
3462 break;
3463 case 'A':
3464 if (control)
3465 {
3467 {
3468 if (!notify_parent(es, EN_UPDATE)) break;
3470#ifdef __REACTOS__
3472#endif
3473 }
3474 }
3475 break;
3476 }
3477 return TRUE;
3478}
3479
3480
3481/*********************************************************************
3482 *
3483 * WM_KILLFOCUS
3484 *
3487{
3489 HWND hwndSelf = es->hwndSelf;
3490
3491 es->flags &= ~EF_FOCUSED;
3492 DestroyCaret();
3493 if (!(es->style & ES_NOHIDESEL))
3494 EDIT_InvalidateText(es, es->selection_start, es->selection_end);
3495 if (!notify_parent(es, EN_KILLFOCUS)) return 0;
3496 /* Throw away left over scroll when we lose focus */
3497 es->wheelDeltaRemainder = 0;
3498
3499 if (theme)
3500 flags |= RDW_FRAME;
3501
3502 RedrawWindow(hwndSelf, NULL, NULL, flags);
3503 return 0;
3504}
3505
3506
3507/*********************************************************************
3508 *
3509 * WM_LBUTTONDBLCLK
3510 *
3511 * The caret position has been set on the WM_LBUTTONDOWN message
3512 *
3515{
3516 INT s;
3517 INT e = es->selection_end;
3518 INT l;
3519 INT li;
3520 INT ll;
3521
3522 es->bCaptureState = TRUE;
3523 SetCapture(es->hwndSelf);
3524
3532 es->region_posx = es->region_posy = 0;
3533 SetTimer(es->hwndSelf, 0, 100, NULL);
3534 return 0;
3535}
3536
3537
3538/*********************************************************************
3539 *
3540 * WM_LBUTTONDOWN
3541 *
3544{
3545 INT e;
3546 BOOL after_wrap;
3547
3548 es->bCaptureState = TRUE;
3549 SetCapture(es->hwndSelf);
3550 EDIT_ConfinePoint(es, &x, &y);
3551 e = EDIT_CharFromPos(es, x, y, &after_wrap);
3552 EDIT_EM_SetSel(es, (keys & MK_SHIFT) ? es->selection_start : e, e, after_wrap);
3554 es->region_posx = es->region_posy = 0;
3555 SetTimer(es->hwndSelf, 0, 100, NULL);
3556
3557 if (!(es->flags & EF_FOCUSED))
3558 SetFocus(es->hwndSelf);
3559
3560 return 0;
3561}
3562
3563
3564/*********************************************************************
3565 *
3566 * WM_LBUTTONUP
3567 *
3570{
3571 if (es->bCaptureState) {
3572 KillTimer(es->hwndSelf, 0);
3573 if (GetCapture() == es->hwndSelf) ReleaseCapture();
3574 }
3575 es->bCaptureState = FALSE;
3576 return 0;
3577}
3578
3579
3580/*********************************************************************
3581 *
3582 * WM_MBUTTONDOWN
3583 *
3586{
3587 SendMessageW(es->hwndSelf, WM_PASTE, 0, 0);
3588 return 0;
3589}
3590
3591
3592/*********************************************************************
3593 *
3594 * WM_MOUSEMOVE
3595 *
3598{
3599 INT e;
3600 BOOL after_wrap;
3601 INT prex, prey;
3602
3603 /* If the mouse has been captured by process other than the edit control itself,
3604 * the windows edit controls will not select the strings with mouse move.
3605 */
3606 if (!es->bCaptureState || GetCapture() != es->hwndSelf)
3607 return 0;
3608
3609 /*
3610 * FIXME: gotta do some scrolling if outside client
3611 * area. Maybe reset the timer ?
3612 */
3613 prex = x; prey = y;
3614 EDIT_ConfinePoint(es, &x, &y);
3615 es->region_posx = (prex < x) ? -1 : ((prex > x) ? 1 : 0);
3616 es->region_posy = (prey < y) ? -1 : ((prey > y) ? 1 : 0);
3617 e = EDIT_CharFromPos(es, x, y, &after_wrap);
3618 EDIT_EM_SetSel(es, es->selection_start, e, after_wrap);
3619 EDIT_SetCaretPos(es,es->selection_end,es->flags & EF_AFTER_WRAP);
3620 return 0;
3621}
3622
3623
3624/*********************************************************************
3625 *
3626 * WM_PAINT
3627 *
3629static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc)
3630{
3631 PAINTSTRUCT ps;
3632 INT i;
3633 HDC dc;
3634 HFONT old_font = 0;
3635 RECT rc;
3636 RECT rcClient;
3637 RECT rcLine;
3638 RECT rcRgn;
3639 HBRUSH brush;
3640 HBRUSH old_brush;
3641 INT bw, bh;
3642 BOOL rev = es->bEnableState &&
3643 ((es->flags & EF_FOCUSED) ||
3644 (es->style & ES_NOHIDESEL));
3645 dc = hdc ? hdc : BeginPaint(es->hwndSelf, &ps);
3646
3647 /* The dc we use for calculating may not be the one we paint into.
3648 This is the safest action. */
3650 GetClientRect(es->hwndSelf, &rcClient);
3651
3652 /* get the background brush */
3653 brush = EDIT_NotifyCtlColor(es, dc);
3654
3655 /* paint the border and the background */
3656 IntersectClipRect(dc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
3657
3658 if(es->style & WS_BORDER) {
3661 rc = rcClient;
3662 if(es->style & ES_MULTILINE) {
3663 if(es->style & WS_HSCROLL) rc.bottom+=bh;
3664 if(es->style & WS_VSCROLL) rc.right+=bw;
3665 }
3666
3667 /* Draw the frame. Same code as in nonclient.c */
3669 PatBlt(dc, rc.left, rc.top, rc.right - rc.left, bh, PATCOPY);
3670 PatBlt(dc, rc.left, rc.top, bw, rc.bottom - rc.top, PATCOPY);
3671 PatBlt(dc, rc.left, rc.bottom - 1, rc.right - rc.left, -bw, PATCOPY);
3672 PatBlt(dc, rc.right - 1, rc.top, -bw, rc.bottom - rc.top, PATCOPY);
3673 SelectObject(dc, old_brush);
3674
3675 /* Keep the border clean */
3676 IntersectClipRect(dc, rc.left+bw, rc.top+bh,
3677 max(rc.right-bw, rc.left+bw), max(rc.bottom-bh, rc.top+bh));
3678 }
3679
3680 GetClipBox(dc, &rc);
3681 FillRect(dc, &rc, brush);
3682
3683 IntersectClipRect(dc, es->format_rect.left,
3684 es->format_rect.top,
3685 es->format_rect.right,
3686 es->format_rect.bottom);
3687 if (es->style & ES_MULTILINE) {
3688 rc = rcClient;
3689 IntersectClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);
3690 }
3691 if (es->font)
3692 old_font = SelectObject(dc, es->font);
3693
3694 if (!es->bEnableState)
3696 GetClipBox(dc, &rcRgn);
3697 if (es->style & ES_MULTILINE) {
3699 for (i = es->y_offset ; i <= min(es->y_offset + vlc, es->y_offset + es->line_count - 1) ; i++) {
3701 EDIT_GetLineRect(es, i, 0, -1, &rcLine);
3702 if (IntersectRect(&rc, &rcRgn, &rcLine))
3703 EDIT_PaintLine(es, dc, i, rev);
3704 }
3705 } else {
3707 EDIT_GetLineRect(es, 0, 0, -1, &rcLine);
3708 if (IntersectRect(&rc, &rcRgn, &rcLine))
3709 EDIT_PaintLine(es, dc, 0, rev);
3710 }
3711 if (es->font)
3712 SelectObject(dc, old_font);
3713
3714 if (!hdc)
3715 EndPaint(es->hwndSelf, &ps);
3716}
3718static void EDIT_WM_NCPaint(HWND hwnd, HRGN region)
3719{
3721 HTHEME theme = GetWindowTheme(hwnd);
3722 HRGN cliprgn = region;
3723
3724 if (theme && exStyle & WS_EX_CLIENTEDGE)
3725 {
3726 HDC dc;
3727 RECT r;
3728 int cxEdge = GetSystemMetrics(SM_CXEDGE),
3729 cyEdge = GetSystemMetrics(SM_CYEDGE);
3730 const int part = EP_EDITTEXT;
3731 int state = ETS_NORMAL;
3732 DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3733
3734 if (!IsWindowEnabled(hwnd))
3736 else if (dwStyle & ES_READONLY)
3738 else if (GetFocus() == hwnd)
3740
3741 GetWindowRect(hwnd, &r);
3742
3743 /* New clipping region passed to default proc to exclude border */
3744 cliprgn = CreateRectRgn(r.left + cxEdge, r.top + cyEdge,
3745 r.right - cxEdge, r.bottom - cyEdge);
3746 if (region != (HRGN)1)
3747 CombineRgn(cliprgn, cliprgn, region, RGN_AND);
3748 OffsetRect(&r, -r.left, -r.top);
3749
3750#ifdef __REACTOS__ /* r73789 */
3751 dc = GetWindowDC(hwnd);
3752 /* Exclude client part */
3754 r.left + cxEdge,
3755 r.top + cyEdge,
3756 r.right - cxEdge,
3757 r.bottom -cyEdge);
3758#else
3760 OffsetRect(&r, -r.left, -r.top);
3761#endif
3762
3765 DrawThemeBackground(theme, dc, part, state, &r, 0);
3766 ReleaseDC(hwnd, dc);
3767 }
3768
3769 /* Call default proc to get the scrollbars etc. also painted */
3770 DefWindowProcW (hwnd, WM_NCPAINT, (WPARAM)cliprgn, 0);
3771 if (cliprgn != region)
3772 DeleteObject(cliprgn);
3773}
3774
3775/*********************************************************************
3776 *
3777 * WM_SETFOCUS
3778 *
3780static void EDIT_WM_SetFocus(HTHEME theme, EDITSTATE *es)
3781{
3783
3784 es->flags |= EF_FOCUSED;
3785
3786 if (!(es->style & ES_NOHIDESEL))
3787 EDIT_InvalidateText(es, es->selection_start, es->selection_end);
3788
3789#ifdef __REACTOS__
3790 SystemParametersInfo(SPI_GETCARETWIDTH, 0, &es->dwCaretWidth, 0);
3791 CreateCaret(es->hwndSelf, NULL, es->dwCaretWidth, es->line_height);
3792#else
3793 CreateCaret(es->hwndSelf, 0, 1, es->line_height);
3794#endif
3795 EDIT_SetCaretPos(es, es->selection_end, es->flags & EF_AFTER_WRAP);
3796 ShowCaret(es->hwndSelf);
3797 if (!notify_parent(es, EN_SETFOCUS)) return;
3798
3799 if (theme)
3801
3802 RedrawWindow(es->hwndSelf, NULL, NULL, flags);
3803}
3804
3807{
3808 ABC abc[256];
3809 SHORT left, right;
3810 UINT i;
3811
3812 if (!(tm->tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE)))
3814
3815 if (!is_cjk(hdc))
3817
3818 if (!GetCharABCWidthsW(hdc, 0, 255, abc))
3819 return 0;
3820
3821 left = right = 0;
3822 for (i = 0; i < ARRAY_SIZE(abc); i++) {
3823 if (-abc[i].abcA > right) right = -abc[i].abcA;
3824 if (-abc[i].abcC > left ) left = -abc[i].abcC;
3825 }
3826 return MAKELONG(left, right);
3827}
3828
3829/*********************************************************************
3830 *
3831 * WM_SETFONT
3832 *
3833 * With Win95 look the margins are set to default font value unless
3834 * the system font (font == 0) is being set, in which case they are left
3835 * unchanged.
3836 *
3839{
3841 HDC dc;
3842 HFONT old_font = 0;
3843 RECT clientRect;
3844 DWORD margins;
3845
3846 es->font = font;
3848 dc = GetDC(es->hwndSelf);
3849 if (font)
3850 old_font = SelectObject(dc, font);
3852 es->line_height = tm.tmHeight;
3853 es->char_width = tm.tmAveCharWidth;
3855 if (font)
3856 SelectObject(dc, old_font);
3857 ReleaseDC(es->hwndSelf, dc);
3858
3859 /* Reset the format rect and the margins */
3860 GetClientRect(es->hwndSelf, &clientRect);
3861 EDIT_SetRectNP(es, &clientRect);
3862 if (margins)
3865
3866 if (es->style & ES_MULTILINE)
3868 else
3870
3871 if (redraw)
3873 if (es->flags & EF_FOCUSED) {
3874 DestroyCaret();
3875#ifdef __REACTOS__
3876 CreateCaret(es->hwndSelf, NULL, es->dwCaretWidth, es->line_height);
3877#else
3878 CreateCaret(es->hwndSelf, 0, 1, es->line_height);
3879#endif
3880 EDIT_SetCaretPos(es, es->selection_end,
3881 es->flags & EF_AFTER_WRAP);
3882 ShowCaret(es->hwndSelf);
3883 }
3884#ifdef __REACTOS__
3886 {
3887 LOGFONTW lf;
3888 HIMC hIMC = ImmGetContext(es->hwndSelf);
3889 if (font == NULL)
3891 GetObjectW(font, sizeof(lf), &lf);
3892 ImmSetCompositionFontW(hIMC, &lf);
3893 ImmReleaseContext(es->hwndSelf, hIMC);
3894 }
3895#endif
3896}
3897
3898
3899/*********************************************************************
3900 *
3901 * WM_SETTEXT
3902 *
3903 * NOTES
3904 * For multiline controls (ES_MULTILINE), reception of WM_SETTEXT triggers:
3905 * The modified flag is reset. No notifications are sent.
3906 *
3907 * For single-line controls, reception of WM_SETTEXT triggers:
3908 * The modified flag is reset. EN_UPDATE and EN_CHANGE notifications are sent.
3909 *
3912{
3913 if (es->flags & EF_UPDATE)
3914 /* fixed this bug once; complain if we see it about to happen again. */
3915 ERR("SetSel may generate UPDATE message whose handler may reset "
3916 "selection.\n");
3917
3918 EDIT_EM_SetSel(es, 0, (UINT)-1, FALSE);
3919 if (text)
3920 {
3921 TRACE("%s\n", debugstr_w(text));
3923 }
3924 else
3925 {
3926 TRACE("<NULL>\n");
3928 }
3929 es->x_offset = 0;
3930 es->flags &= ~EF_MODIFIED;
3931 EDIT_EM_SetSel(es, 0, 0, FALSE);
3932
3933 /* Send the notification after the selection start and end have been set
3934 * edit control doesn't send notification on WM_SETTEXT
3935 * if it is multiline, or it is part of combobox
3936 */
3937 if( !((es->style & ES_MULTILINE) || es->hwndListBox))
3938 {
3939 if (!notify_parent(es, EN_UPDATE)) return;
3940 if (!notify_parent(es, EN_CHANGE)) return;
3941 }
3945}
3946
3947
3948/*********************************************************************
3949 *
3950 * WM_SIZE
3951 *
3953static void EDIT_WM_Size(EDITSTATE *es, UINT action)
3954{
3955 if ((action == SIZE_MAXIMIZED) || (action == SIZE_RESTORED)) {
3956 RECT rc;
3957 GetClientRect(es->hwndSelf, &rc);
3958 EDIT_SetRectNP(es, &rc);
3960 }
3961}
3962
3963
3964/*********************************************************************
3965 *
3966 * WM_STYLECHANGED
3967 *
3968 * This message is sent by SetWindowLong on having changed either the Style
3969 * or the extended style.
3970 *
3971 * We ensure that the window's version of the styles and the EDITSTATE's agree.
3972 *
3973 * See also EDIT_WM_NCCreate
3974 *
3975 * It appears that the Windows version of the edit control allows the style
3976 * (as retrieved by GetWindowLong) to be any value and maintains an internal
3977 * style variable which will generally be different. In this function we
3978 * update the internal style based on what changed in the externally visible
3979 * style.
3980 *
3981 * Much of this content as based upon the MSDN, especially:
3982 * Platform SDK Documentation -> User Interface Services ->
3983 * Windows User Interface -> Edit Controls -> Edit Control Reference ->
3984 * Edit Control Styles
3987{
3988 if (GWL_STYLE == which) {
3989 DWORD style_change_mask;
3990 DWORD new_style;
3991 /* Only a subset of changes can be applied after the control
3992 * has been created.
3993 */
3994 style_change_mask = ES_UPPERCASE | ES_LOWERCASE |
3995 ES_NUMBER;
3996 if (es->style & ES_MULTILINE)
3997 style_change_mask |= ES_WANTRETURN;
3998
3999 new_style = style->styleNew & style_change_mask;
4000
4001 /* Number overrides lowercase overrides uppercase (at least it
4002 * does in Win95). However I'll bet that ES_NUMBER would be
4003 * invalid under Win 3.1.
4004 */
4005 if (new_style & ES_NUMBER) {
4006 ; /* do not override the ES_NUMBER */
4007 } else if (new_style & ES_LOWERCASE) {
4008 new_style &= ~ES_UPPERCASE;
4009 }
4010
4011 es->style = (es->style & ~style_change_mask) | new_style;
4012 } else if (GWL_EXSTYLE == which) {
4013 ; /* FIXME - what is needed here */
4014 } else {
4015 WARN ("Invalid style change %ld\n",which);
4016 }
4017
4018 return 0;
4019}
4020
4021/*********************************************************************
4022 *
4023 * WM_SYSKEYDOWN
4024 *
4027{
4028 if ((key == VK_BACK) && (key_data & 0x2000)) {
4029 if (EDIT_EM_CanUndo(es))
4031 return 0;
4032 } else if (key == VK_UP || key == VK_DOWN) {
4034 return 0;
4035 }
4036 return DefWindowProcW(es->hwndSelf, WM_SYSKEYDOWN, key, key_data);
4037}
4038
4039
4040/*********************************************************************
4041 *
4042 * WM_TIMER
4043 *
4045static void EDIT_WM_Timer(EDITSTATE *es)
4046{
4047 if (es->region_posx < 0) {
4049 } else if (es->region_posx > 0) {
4051 }
4052/*
4053 * FIXME: gotta do some vertical scrolling here, like
4054 * EDIT_EM_LineScroll(hwnd, 0, 1);
4055 */
4056}
4057
4058/*********************************************************************
4059 *
4060 * WM_HSCROLL
4061 *
4064{
4065 INT dx;
4066 INT fw;
4067
4068 if (!(es->style & ES_MULTILINE))
4069 return 0;
4070
4071 if (!(es->style & ES_AUTOHSCROLL))
4072 return 0;
4073
4074 dx = 0;
4075 fw = es->format_rect.right - es->format_rect.left;
4076 switch (action) {
4077 case SB_LINELEFT:
4078 TRACE("SB_LINELEFT\n");
4079 if (es->x_offset)
4080 dx = -es->char_width;
4081 break;
4082 case SB_LINERIGHT:
4083 TRACE("SB_LINERIGHT\n");
4084 if (es->x_offset < es->text_width)
4085 dx = es->char_width;
4086 break;
4087 case SB_PAGELEFT:
4088 TRACE("SB_PAGELEFT\n");
4089 if (es->x_offset)
4090 dx = -fw / HSCROLL_FRACTION / es->char_width * es->char_width;
4091 break;
4092 case SB_PAGERIGHT:
4093 TRACE("SB_PAGERIGHT\n");
4094 if (es->x_offset < es->text_width)
4095 dx = fw / HSCROLL_FRACTION / es->char_width * es->char_width;
4096 break;
4097 case SB_LEFT:
4098 TRACE("SB_LEFT\n");
4099 if (es->x_offset)
4100 dx = -es->x_offset;
4101 break;
4102 case SB_RIGHT:
4103 TRACE("SB_RIGHT\n");
4104 if (es->x_offset < es->text_width)
4105 dx = es->text_width - es->x_offset;
4106 break;
4107 case SB_THUMBTRACK:
4108 TRACE("SB_THUMBTRACK %d\n", pos);
4109 es->flags |= EF_HSCROLL_TRACK;
4110 if(es->style & WS_HSCROLL)
4111 dx = pos - es->x_offset;
4112 else
4113 {
4114 INT fw, new_x;
4115 /* Sanity check */
4116 if(pos < 0 || pos > 100) return 0;
4117 /* Assume default scroll range 0-100 */
4118 fw = es->format_rect.right - es->format_rect.left;
4119 new_x = pos * (es->text_width - fw) / 100;
4120 dx = es->text_width ? (new_x - es->x_offset) : 0;
4121 }
4122 break;
4123 case SB_THUMBPOSITION:
4124 TRACE("SB_THUMBPOSITION %d\n", pos);
4125 es->flags &= ~EF_HSCROLL_TRACK;
4126 if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_HSCROLL)
4127 dx = pos - es->x_offset;
4128 else
4129 {
4130 INT fw, new_x;
4131 /* Sanity check */
4132 if(pos < 0 || pos > 100) return 0;
4133 /* Assume default scroll range 0-100 */
4134 fw = es->format_rect.right - es->format_rect.left;
4135 new_x = pos * (es->text_width - fw) / 100;
4136 dx = es->text_width ? (new_x - es->x_offset) : 0;
4137 }
4138 if (!dx) {
4139 /* force scroll info update */
4142 }
4143 break;
4144 case SB_ENDSCROLL:
4145 TRACE("SB_ENDSCROLL\n");
4146 break;
4147 /*
4148 * FIXME : the next two are undocumented !
4149 * Are we doing the right thing ?
4150 * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
4151 * although it's also a regular control message.
4152 */
4153 case EM_GETTHUMB: /* this one is used by NT notepad */
4154 {
4155 LRESULT ret;
4156 if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_HSCROLL)
4157 ret = GetScrollPos(es->hwndSelf, SB_HORZ);
4158 else
4159 {
4160 /* Assume default scroll range 0-100 */
4161 INT fw = es->format_rect.right - es->format_rect.left;
4162 ret = es->text_width ? es->x_offset * 100 / (es->text_width - fw) : 0;
4163 }
4164 TRACE("EM_GETTHUMB: returning %ld\n", ret);
4165 return ret;
4166 }
4167 case EM_LINESCROLL:
4168 TRACE("EM_LINESCROLL16\n");
4169 dx = pos;
4170 break;
4171
4172 default:
4173 ERR("undocumented WM_HSCROLL action %d (0x%04x), please report\n",
4174 action, action);
4175 return 0;
4176 }
4177 if (dx)
4178 {
4179 INT fw = es->format_rect.right - es->format_rect.left;
4180 /* check if we are going to move too far */
4181 if(es->x_offset + dx + fw > es->text_width)
4182 dx = es->text_width - fw - es->x_offset;
4183 if(dx)
4185 }
4186 return 0;
4187}
4188
4189
4190/*********************************************************************
4191 *
4192 * WM_VSCROLL
4193 *
4196{
4197 INT dy;
4198
4199 if (!(es->style & ES_MULTILINE))
4200 return 0;
4201
4202 if (!(es->style & ES_AUTOVSCROLL))
4203 return 0;
4204
4205 dy = 0;
4206 switch (action) {
4207 case SB_LINEUP:
4208 case SB_LINEDOWN:
4209 case SB_PAGEUP:
4210 case SB_PAGEDOWN:
4211 TRACE("action %d (%s)\n", action, (action == SB_LINEUP ? "SB_LINEUP" :
4212 (action == SB_LINEDOWN ? "SB_LINEDOWN" :
4213 (action == SB_PAGEUP ? "SB_PAGEUP" :
4214 "SB_PAGEDOWN"))));
4216 return 0;
4217 case SB_TOP:
4218 TRACE("SB_TOP\n");
4219 dy = -es->y_offset;
4220 break;
4221 case SB_BOTTOM:
4222 TRACE("SB_BOTTOM\n");
4223 dy = es->line_count - 1 - es->y_offset;
4224 break;
4225 case SB_THUMBTRACK:
4226 TRACE("SB_THUMBTRACK %d\n", pos);
4227 es->flags |= EF_VSCROLL_TRACK;
4228 if(es->style & WS_VSCROLL)
4229 dy = pos - es->y_offset;
4230 else
4231 {
4232 /* Assume default scroll range 0-100 */
4233 INT vlc, new_y;
4234 /* Sanity check */
4235 if(pos < 0 || pos > 100) return 0;
4237 new_y = pos * (es->line_count - vlc) / 100;
4238 dy = es->line_count ? (new_y - es->y_offset) : 0;
4239 TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n",
4240 es->line_count, es->y_offset, pos, dy);
4241 }
4242 break;
4243 case SB_THUMBPOSITION:
4244 TRACE("SB_THUMBPOSITION %d\n", pos);
4245 es->flags &= ~EF_VSCROLL_TRACK;
4246 if(es->style & WS_VSCROLL)
4247 dy = pos - es->y_offset;
4248 else
4249 {
4250 /* Assume default scroll range 0-100 */
4251 INT vlc, new_y;
4252 /* Sanity check */
4253 if(pos < 0 || pos > 100) return 0;
4255 new_y = pos * (es->line_count - vlc) / 100;
4256 dy = es->line_count ? (new_y - es->y_offset) : 0;
4257 TRACE("line_count=%d, y_offset=%d, pos=%d, dy = %d\n",
4258 es->line_count, es->y_offset, pos, dy);
4259 }
4260 if (!dy)
4261 {
4262 /* force scroll info update */
4265 }
4266 break;
4267 case SB_ENDSCROLL:
4268 TRACE("SB_ENDSCROLL\n");
4269 break;
4270 /*
4271 * FIXME : the next two are undocumented !
4272 * Are we doing the right thing ?
4273 * At least Win 3.1 Notepad makes use of EM_GETTHUMB this way,
4274 * although it's also a regular control message.
4275 */
4276 case EM_GETTHUMB: /* this one is used by NT notepad */
4277 {
4278 LRESULT ret;
4279 if(GetWindowLongW( es->hwndSelf, GWL_STYLE ) & WS_VSCROLL)
4280 ret = GetScrollPos(es->hwndSelf, SB_VERT);
4281 else
4282 {
4283 /* Assume default scroll range 0-100 */
4285 ret = es->line_count ? es->y_offset * 100 / (es->line_count - vlc) : 0;
4286 }
4287 TRACE("EM_GETTHUMB: returning %ld\n", ret);
4288 return ret;
4289 }
4290 case EM_LINESCROLL:
4291 TRACE("EM_LINESCROLL %d\n", pos);
4292 dy = pos;
4293 break;
4294
4295 default:
4296 ERR("undocumented WM_VSCROLL action %d (0x%04x), please report\n",
4297 action, action);
4298 return 0;
4299 }
4300 if (dy)
4302 return 0;
4303}
4304
4305/*********************************************************************
4306 *
4307 * EM_GETTHUMB
4308 *
4309 * FIXME: is this right ? (or should it be only VSCROLL)
4310 * (and maybe only for edit controls that really have their
4311 * own scrollbars) (and maybe only for multiline controls ?)
4312 * All in all: very poorly documented
4313 *
4316{
4319}
4321static inline WCHAR *heap_strdupW(const WCHAR *str)
4322{
4323 int len = lstrlenW(str) + 1;
4324 WCHAR *ret = heap_alloc(len * sizeof(WCHAR));
4325 lstrcpyW(ret, str);
4326 return ret;
4327}
4328
4329/*********************************************************************
4330 *
4331 * EM_SETCUEBANNER
4332 *
4334static BOOL EDIT_EM_SetCueBanner(EDITSTATE *es, BOOL draw_focused, const WCHAR *cue_text)
4335{
4336 if (es->style & ES_MULTILINE || !cue_text)
4337 return FALSE;
4338
4339 heap_free(es->cue_banner_text);
4340 es->cue_banner_text = heap_strdupW(cue_text);
4341 es->cue_banner_draw_focused = draw_focused;
4342
4343 return TRUE;
4344}
4345
4346/*********************************************************************
4347 *
4348 * EM_GETCUEBANNER
4349 *
4352{
4353 if (es->style & ES_MULTILINE)
4354 return FALSE;
4355
4356 if (!es->cue_banner_text)
4357 {
4358 if (buf && size)
4359 *buf = 0;
4360 return FALSE;
4361 }
4362 else
4363 {
4364 if (buf)
4365 lstrcpynW(buf, es->cue_banner_text, size);
4366 return TRUE;
4367 }
4368}
4369
4370
4371/********************************************************************
4372 *
4373 * The Following code is to handle inline editing from IMEs
4374 */
4376static void EDIT_GetCompositionStr(HIMC hIMC, LPARAM CompFlag, EDITSTATE *es)
4377{
4378 LONG buflen;
4379 LPWSTR lpCompStr;
4380 LPSTR lpCompStrAttr = NULL;
4381 DWORD dwBufLenAttr;
4382
4383 buflen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
4384
4385 if (buflen < 0)
4386 {
4387 return;
4388 }
4389
4390 lpCompStr = heap_alloc(buflen);
4391 if (!lpCompStr)
4392 {
4393 ERR("Unable to allocate IME CompositionString\n");
4394 return;
4395 }
4396
4397 if (buflen)
4398 ImmGetCompositionStringW(hIMC, GCS_COMPSTR, lpCompStr, buflen);
4399
4400 if (CompFlag & GCS_COMPATTR)
4401 {
4402 /*
4403 * We do not use the attributes yet. it would tell us what characters
4404 * are in transition and which are converted or decided upon
4405 */
4406 dwBufLenAttr = ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
4407 if (dwBufLenAttr)
4408 {
4409 dwBufLenAttr ++;
4410 lpCompStrAttr = heap_alloc(dwBufLenAttr + 1);
4411 if (!lpCompStrAttr)
4412 {
4413 ERR("Unable to allocate IME Attribute String\n");
4414 heap_free(lpCompStr);
4415 return;
4416 }
4417 ImmGetCompositionStringW(hIMC,GCS_COMPATTR, lpCompStrAttr,
4418 dwBufLenAttr);
4419 lpCompStrAttr[dwBufLenAttr] = 0;
4420 }
4421 }
4422
4423#ifndef __REACTOS__ /* We don't use internal composition string. Rely on the composition window */
4424 /* check for change in composition start */
4425 if (es->selection_end < es->composition_start)
4426 es->composition_start = es->selection_end;
4427
4428 /* replace existing selection string */
4429 es->selection_start = es->composition_start;
4430
4431 if (es->composition_len > 0)
4432 es->selection_end = es->composition_start + es->composition_len;
4433 else
4434 es->selection_end = es->selection_start;
4435
4436 EDIT_EM_ReplaceSel(es, FALSE, lpCompStr, buflen / sizeof(WCHAR), TRUE, TRUE);
4437 es->composition_len = abs(es->composition_start - es->selection_end);
4438
4439 es->selection_start = es->composition_start;
4440 es->selection_end = es->selection_start + es->composition_len;
4441#endif
4442
4443 heap_free(lpCompStrAttr);
4444 heap_free(lpCompStr);
4445}
4447static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es)
4448{
4449 LONG buflen;
4450 LPWSTR lpResultStr;
4451
4452 buflen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
4453 if (buflen <= 0)
4454 {
4455 return;
4456 }
4457
4458 lpResultStr = heap_alloc(buflen);
4459 if (!lpResultStr)
4460 {
4461 ERR("Unable to alloc buffer for IME string\n");
4462 return;
4463 }
4464
4465 ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpResultStr, buflen);
4466
4467#ifndef __REACTOS__
4468 /* check for change in composition start */
4469 if (es->selection_end < es->composition_start)
4470 es->composition_start = es->selection_end;
4471
4472 es->selection_start = es->composition_start;
4473 es->selection_end = es->composition_start + es->composition_len;
4474 EDIT_EM_ReplaceSel(es, TRUE, lpResultStr, buflen / sizeof(WCHAR), TRUE, TRUE);
4475 es->composition_start = es->selection_end;
4476 es->composition_len = 0;
4477#endif
4478
4479 heap_free(lpResultStr);
4480}
4482static void EDIT_ImeComposition(HWND hwnd, LPARAM CompFlag, EDITSTATE *es)
4483{
4484 HIMC hIMC;
4485 int cursor;
4486
4487#ifdef __REACTOS__
4488 if (es->selection_start != es->selection_end)
4490#else
4491 if (es->composition_len == 0 && es->selection_start != es->selection_end)
4492 {
4494 es->composition_start = es->selection_end;
4495 }
4496#endif
4497
4498 hIMC = ImmGetContext(hwnd);
4499 if (!hIMC)
4500 return;
4501
4502 if (CompFlag & GCS_RESULTSTR)
4503 {
4504 EDIT_GetResultStr(hIMC, es);
4505 cursor = 0;
4506 }
4507 else
4508 {
4509 if (CompFlag & GCS_COMPSTR)
4510 EDIT_GetCompositionStr(hIMC, CompFlag, es);
4511#ifdef __REACTOS__
4512 cursor = 0;
4513#else
4515#endif
4516 }
4517 ImmReleaseContext(hwnd, hIMC);
4518 EDIT_SetCaretPos(es, es->selection_start + cursor, es->flags & EF_AFTER_WRAP);
4519}
4520
4521
4522/*********************************************************************
4523 *
4524 * WM_NCCREATE
4525 *
4526 * See also EDIT_WM_StyleChanged
4529{
4530 EDITSTATE *es;
4531 UINT alloc_size;
4532
4533 TRACE("Creating edit control, style = %08x\n", lpcs->style);
4534
4535 if (!(es = heap_alloc_zero(sizeof(*es))))
4536 return FALSE;
4538
4539 /*
4540 * Note: since the EDITSTATE has not been fully initialized yet,
4541 * we can't use any API calls that may send
4542 * WM_XXX messages before WM_NCCREATE is completed.
4543 */
4544
4545 es->style = lpcs->style;
4546
4547 es->bEnableState = !(es->style & WS_DISABLED);
4548
4549 es->hwndSelf = hwnd;
4550 /* Save parent, which will be notified by EN_* messages */
4551 es->hwndParent = lpcs->hwndParent;
4552
4553 if (es->style & ES_COMBO)
4554 es->hwndListBox = GetDlgItem(es->hwndParent, ID_CB_LISTBOX);
4555
4556 /* FIXME: should we handle changes to WS_EX_RIGHT style after creation? */
4557 if (lpcs->dwExStyle & WS_EX_RIGHT) es->style |= ES_RIGHT;
4558
4559 /* Number overrides lowercase overrides uppercase (at least it
4560 * does in Win95). However I'll bet that ES_NUMBER would be
4561 * invalid under Win 3.1.
4562 */
4563 if (es->style & ES_NUMBER) {
4564 ; /* do not override the ES_NUMBER */
4565 } else if (es->style & ES_LOWERCASE) {
4566 es->style &= ~ES_UPPERCASE;
4567 }
4568 if (es->style & ES_MULTILINE) {
4569 es->buffer_limit = BUFLIMIT_INITIAL;
4570 if (es->style & WS_VSCROLL)
4571 es->style |= ES_AUTOVSCROLL;
4572 if (es->style & WS_HSCROLL)
4573 es->style |= ES_AUTOHSCROLL;
4574 es->style &= ~ES_PASSWORD;
4575 if ((es->style & ES_CENTER) || (es->style & ES_RIGHT)) {
4576 /* Confirmed - RIGHT overrides CENTER */
4577 if (es->style & ES_RIGHT)
4578 es->style &= ~ES_CENTER;
4579 es->style &= ~WS_HSCROLL;
4580 es->style &= ~ES_AUTOHSCROLL;
4581 }
4582 } else {
4583 es->buffer_limit = BUFLIMIT_INITIAL;
4584 if ((es->style & ES_RIGHT) && (es->style & ES_CENTER))
4585 es->style &= ~ES_CENTER;
4586 es->style &= ~WS_HSCROLL;
4587 es->style &= ~WS_VSCROLL;
4588 if (es->style & ES_PASSWORD)
4589 es->password_char = '*';
4590 }
4591
4592 alloc_size = ROUND_TO_GROW((es->buffer_size + 1) * sizeof(WCHAR));
4593 if(!(es->hloc32W = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size)))
4594 goto cleanup;
4595 es->buffer_size = LocalSize(es->hloc32W)/sizeof(WCHAR) - 1;
4596
4597 if (!(es->undo_text = heap_alloc_zero((es->buffer_size + 1) * sizeof(WCHAR))))
4598 goto cleanup;
4599 es->undo_buffer_size = es->buffer_size;
4600
4601 if (es->style & ES_MULTILINE)
4602 if (!(es->first_line_def = heap_alloc_zero(sizeof(LINEDEF))))
4603 goto cleanup;
4604 es->line_count = 1;
4605
4606 /*
4607 * In Win95 look and feel, the WS_BORDER style is replaced by the
4608 * WS_EX_CLIENTEDGE style for the edit control. This gives the edit
4609 * control a nonclient area so we don't need to draw the border.
4610 * If WS_BORDER without WS_EX_CLIENTEDGE is specified we shouldn't have
4611 * a nonclient area and we should handle painting the border ourselves.
4612 *
4613 * When making modifications please ensure that the code still works
4614 * for edit controls created directly with style 0x50800000, exStyle 0
4615 * (which should have a single pixel border)
4616 */
4617 if (lpcs->dwExStyle & WS_EX_CLIENTEDGE)
4618 es->style &= ~WS_BORDER;
4619 else if (es->style & WS_BORDER)
4621
4622 return TRUE;
4623
4624cleanup:
4625 SetWindowLongPtrW(es->hwndSelf, 0, 0);
4627 heap_free(es->first_line_def);
4628 heap_free(es->undo_text);
4629 if (es->hloc32W) LocalFree(es->hloc32W);
4630 heap_free(es->logAttr);
4631 heap_free(es);
4632 return FALSE;
4633}
4634
4635
4636/*********************************************************************
4637 *
4638 * WM_CREATE
4639 *
4642{
4643 RECT clientRect;
4644
4645 TRACE("%s\n", debugstr_w(name));
4646
4647 /*
4648 * To initialize some final structure members, we call some helper
4649 * functions. However, since the EDITSTATE is not consistent (i.e.
4650 * not fully initialized), we should be very careful which
4651 * functions can be called, and in what order.
4652 */
4655
4656 /* We need to calculate the format rect
4657 (applications may send EM_SETMARGINS before the control gets visible) */
4658 GetClientRect(es->hwndSelf, &clientRect);
4659 EDIT_SetRectNP(es, &clientRect);
4660
4661 if (name && *name)
4662 {
4664 /* if we insert text to the editline, the text scrolls out
4665 * of the window, as the caret is placed after the insert
4666 * pos normally; thus we reset es->selection... to 0 and
4667 * update caret
4668 */
4669 es->selection_start = es->selection_end = 0;
4670 /* Adobe Photoshop does NOT like this. and MSDN says that EN_CHANGE
4671 * Messages are only to be sent when the USER does something to
4672 * change the contents. So I am removing this EN_CHANGE
4673 *
4674 * EDIT_NOTIFY_PARENT(es, EN_CHANGE);
4675 */
4677 }
4678
4679 /* force scroll info update */
4681 OpenThemeData(es->hwndSelf, WC_EDITW);
4682
4683 /* The rule seems to return 1 here for success */
4684 /* Power Builder masked edit controls will crash */
4685 /* if not. */
4686 /* FIXME: is that in all cases so ? */
4687 return 1;
4688}
4689
4690
4691/*********************************************************************
4692 *
4693 * WM_NCDESTROY
4694 *
4697{
4698 LINEDEF *pc, *pp;
4699 HTHEME theme;
4700
4701 theme = GetWindowTheme(es->hwndSelf);
4702 CloseThemeData(theme);
4703
4704 /* The app can own the text buffer handle */
4705 if (es->hloc32W && (es->hloc32W != es->hlocapp))
4706 LocalFree(es->hloc32W);
4707
4709
4710 pc = es->first_line_def;
4711 while (pc)
4712 {
4713 pp = pc->next;
4714 heap_free(pc);
4715 pc = pp;
4716 }
4717
4718 SetWindowLongPtrW( es->hwndSelf, 0, 0 );
4719 heap_free(es->undo_text);
4720 heap_free(es->cue_banner_text);
4721 heap_free(es);
4722
4723 return 0;
4724}
4727{
4729 HTHEME theme = GetWindowTheme(hwnd);
4730 LRESULT result = 0;
4731 RECT *rect;
4732
4733 TRACE("hwnd=%p msg=%#x wparam=%lx lparam=%lx\n", hwnd, msg, wParam, lParam);
4734
4735 if (!es && msg != WM_NCCREATE)
4736 return DefWindowProcW(hwnd, msg, wParam, lParam);
4737
4738 if (es && (msg != WM_NCDESTROY))
4740
4741 switch (msg)
4742 {
4743 case EM_GETSEL:
4745 break;
4746
4747 case EM_SETSEL:
4750 result = 1;
4751 break;
4752
4753 case EM_GETRECT:
4754 rect = (RECT *)lParam;
4755 if (rect)
4756 *rect = es->format_rect;
4757 break;
4758
4759 case EM_SETRECT:
4760 if ((es->style & ES_MULTILINE) && lParam)
4761 {
4764 }
4765 break;
4766
4767 case EM_SETRECTNP:
4768 if ((es->style & ES_MULTILINE) && lParam)
4770 break;
4771
4772 case EM_SCROLL:
4774 break;
4775
4776 case EM_LINESCROLL:
4778 break;
4779
4780 case EM_SCROLLCARET:
4782 result = 1;
4783 break;
4784
4785 case EM_GETMODIFY:
4786 result = ((es->flags & EF_MODIFIED) != 0);
4787 break;
4788
4789 case EM_SETMODIFY:
4790 if (wParam)
4791 es->flags |= EF_MODIFIED;
4792 else
4793 es->flags &= ~(EF_MODIFIED | EF_UPDATE); /* reset pending updates */
4794 break;
4795
4796 case EM_GETLINECOUNT:
4797 result = (es->style & ES_MULTILINE) ? es->line_count : 1;
4798 break;
4799
4800 case EM_LINEINDEX:
4802 break;
4803
4804 case EM_SETHANDLE:
4806 break;
4807
4808 case EM_GETHANDLE:
4810 break;
4811
4812 case EM_GETTHUMB:
4814 break;
4815
4816 /* these messages missing from specs */
4817 case 0x00bf:
4818 case 0x00c0:
4819 case 0x00c3:
4820 case 0x00ca:
4821 FIXME("undocumented message 0x%x, please report\n", msg);
4823 break;
4824
4825 case EM_LINELENGTH:
4827 break;
4828
4829 case EM_REPLACESEL:
4830 {
4831 const WCHAR *textW = (const WCHAR *)lParam;
4832
4834 result = 1;
4835 break;
4836 }
4837
4838 case EM_GETLINE:
4840 break;
4841
4842 case EM_SETLIMITTEXT:
4844 break;
4845
4846 case EM_CANUNDO:
4848 break;
4849
4850 case EM_UNDO:
4851 case WM_UNDO:
4853 break;
4854
4855 case EM_FMTLINES:
4857 break;
4858
4859 case EM_LINEFROMCHAR:
4861 break;
4862
4863 case EM_SETTABSTOPS:
4865 break;
4866
4867 case EM_SETPASSWORDCHAR:
4869 break;
4870
4871 case EM_EMPTYUNDOBUFFER:
4873 break;
4874
4876 result = (es->style & ES_MULTILINE) ? es->y_offset : es->x_offset;
4877 break;
4878
4879 case EM_SETREADONLY:
4880 {
4881 DWORD old_style = es->style;
4882
4883 if (wParam)
4884 {
4886 es->style |= ES_READONLY;
4887 }
4888 else
4889 {
4891 es->style &= ~ES_READONLY;
4892 }
4893
4894 if (old_style ^ es->style)
4895 InvalidateRect(es->hwndSelf, NULL, TRUE);
4896
4897 result = 1;
4898 break;
4899 }
4900
4903 result = 1;
4904 break;
4905
4907 result = (LRESULT)es->word_break_proc;
4908 break;
4909
4910 case EM_GETPASSWORDCHAR:
4911 result = es->password_char;
4912 break;
4913
4914 case EM_SETMARGINS:
4916 break;
4917
4918 case EM_GETMARGINS:
4919 result = MAKELONG(es->left_margin, es->right_margin);
4920 break;
4921
4922 case EM_GETLIMITTEXT:
4923 result = es->buffer_limit;
4924 break;
4925
4926 case EM_POSFROMCHAR:
4927 if ((INT)wParam >= get_text_length(es)) result = -1;
4929 break;
4930
4931 case EM_CHARFROMPOS:
4932 result = EDIT_EM_CharFromPos(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
4933 break;
4934
4935 case EM_SETCUEBANNER:
4937 break;
4938
4939 case EM_GETCUEBANNER:
4941 break;
4942
4943 /* End of the EM_ messages which were in numerical order; what order
4944 * are these in? vaguely alphabetical?
4945 */
4946
4947 case WM_NCCREATE:
4949 break;
4950
4951 case WM_NCDESTROY:
4953 es = NULL;
4954 break;
4955
4956 case WM_GETDLGCODE:
4958
4959 if (es->style & ES_MULTILINE)
4961
4962 if (lParam)
4963 {
4964 MSG *msg = (MSG *)lParam;
4965 es->flags |= EF_DIALOGMODE;
4966
4967 if (msg->message == WM_KEYDOWN)
4968 {
4969 int vk = (int)msg->wParam;
4970
4971 if (es->hwndListBox)
4972 {
4973 if (vk == VK_RETURN || vk == VK_ESCAPE)
4976 }
4977 }
4978 }
4979 break;
4980
4981 case WM_IME_CHAR:
4982#ifdef __REACTOS__
4984 break;
4985#endif
4986 case WM_CHAR:
4987 {
4988 WCHAR charW = wParam;
4989
4990 if (es->hwndListBox)
4991 {
4992 if (charW == VK_RETURN || charW == VK_ESCAPE)
4993 {
4996 break;
4997 }
4998 }
4999 result = EDIT_WM_Char(es, charW);
5000 break;
5001 }
5002
5003 case WM_UNICHAR:
5004 if (wParam == UNICODE_NOCHAR) return TRUE;
5005 if (wParam <= 0x000fffff)
5006 {
5007 if (wParam > 0xffff) /* convert to surrogates */
5008 {
5009 wParam -= 0x10000;
5010 EDIT_WM_Char(es, (wParam >> 10) + 0xd800);
5011 EDIT_WM_Char(es, (wParam & 0x03ff) + 0xdc00);
5012 }
5013 else
5015 }
5016 return 0;
5017
5018 case WM_CLEAR:
5020 break;
5021
5022 case WM_CONTEXTMENU:
5023 EDIT_WM_ContextMenu(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
5024 break;
5025
5026 case WM_COPY:
5028 break;
5029
5030 case WM_CREATE:
5032 break;
5033
5034 case WM_CUT:
5035 EDIT_WM_Cut(es);
5036 break;
5037
5038 case WM_ENABLE:
5039 es->bEnableState = (BOOL) wParam;
5041 if (theme)
5043 break;
5044
5045 case WM_ERASEBKGND:
5046 /* we do the proper erase in EDIT_WM_Paint */
5047 result = 1;
5048 break;
5049
5050 case WM_GETFONT:
5051 result = (LRESULT)es->font;
5052 break;
5053
5054 case WM_GETTEXT:
5056 break;
5057
5058 case WM_GETTEXTLENGTH:
5060 break;
5061
5062 case WM_HSCROLL:
5064 break;
5065
5066 case WM_KEYDOWN:
5068 break;
5069
5070 case WM_KILLFOCUS:
5071 result = EDIT_WM_KillFocus(theme, es);
5072 break;
5073
5074 case WM_LBUTTONDBLCLK:
5076 break;
5077
5078 case WM_LBUTTONDOWN:
5080 break;
5081
5082 case WM_LBUTTONUP:
5084 break;
5085
5086 case WM_MBUTTONDOWN:
5088 break;
5089
5090 case WM_MOUSEMOVE:
5091 result = EDIT_WM_MouseMove(es, (short)LOWORD(lParam), (short)HIWORD(lParam));
5092 break;
5093
5094 case WM_PRINTCLIENT:
5095 case WM_PAINT:
5097 break;
5098
5099 case WM_NCPAINT:
5100 EDIT_WM_NCPaint(hwnd, (HRGN)wParam);
5101 break;
5102
5103 case WM_PASTE:
5105 break;
5106
5107 case WM_SETFOCUS:
5108 EDIT_WM_SetFocus(theme, es);
5109 break;
5110
5111 case WM_SETFONT:
5113 break;
5114
5115 case WM_SETREDRAW:
5116 /* FIXME: actually set an internal flag and behave accordingly */
5117 break;
5118
5119 case WM_SETTEXT:
5120 EDIT_WM_SetText(es, (const WCHAR *)lParam);
5121 result = TRUE;
5122 break;
5123
5124 case WM_SIZE:
5126 break;
5127
5128 case WM_STYLECHANGED:
5130 break;
5131
5132 case WM_STYLECHANGING:
5133 result = 0; /* See EDIT_WM_StyleChanged */
5134 break;
5135
5136 case WM_SYSKEYDOWN:
5138 break;
5139
5140 case WM_TIMER:
5142 break;
5143
5144 case WM_VSCROLL:
5146 break;
5147
5148 case WM_MOUSEWHEEL:
5149 {
5150 int wheelDelta;
5151 INT pulScrollLines = 3;
5152 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
5153
5154 if (wParam & (MK_SHIFT | MK_CONTROL))
5155 {
5157 break;
5158 }
5159
5160 wheelDelta = GET_WHEEL_DELTA_WPARAM(wParam);
5161 /* if scrolling changes direction, ignore left overs */
5162 if ((wheelDelta < 0 && es->wheelDeltaRemainder < 0) ||
5163 (wheelDelta > 0 && es->wheelDeltaRemainder > 0))
5164 es->wheelDeltaRemainder += wheelDelta;
5165 else
5166 es->wheelDeltaRemainder = wheelDelta;
5167
5168 if (es->wheelDeltaRemainder && pulScrollLines)
5169 {
5170 int cLineScroll;
5171 pulScrollLines = min(es->line_count, pulScrollLines);
5172 cLineScroll = pulScrollLines * es->wheelDeltaRemainder / WHEEL_DELTA;
5173 es->wheelDeltaRemainder -= WHEEL_DELTA * cLineScroll / pulScrollLines;
5174 result = EDIT_EM_LineScroll(es, 0, -cLineScroll);
5175 }
5176 break;
5177 }
5178
5179 /* IME messages to make the edit control IME aware */
5180 case WM_IME_SETCONTEXT:
5181#ifdef __REACTOS__
5182 {
5183 HKL hKL = GetKeyboardLayout(0);
5184
5185 /* Korean doesn't want composition window */
5186 if (PRIMARYLANGID(LOWORD(hKL)) == LANG_KOREAN)
5187 lParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
5188
5189 if (wParam)
5190 {
5191 HIMC hIMC = ImmGetContext(hwnd);
5193 if (pIC)
5194 {
5195 pIC->dwUIFlags &= ~0x40000;
5196 ImmUnlockIMC(hIMC);
5197 }
5198 if (FALSE) /* FIXME: Condition */
5200 ImmReleaseContext(hwnd, hIMC);
5201 }
5202
5204 }
5205#endif
5206 break;
5207
5208 case WM_IME_STARTCOMPOSITION:
5209#ifdef __REACTOS__
5210 {
5211 HKL hKL = GetKeyboardLayout(0);
5212
5213 /* Korean doesn't want composition window */
5214 if (PRIMARYLANGID(LOWORD(hKL)) == LANG_KOREAN)
5215 return TRUE;
5216
5218 }
5219#else
5220 es->composition_start = es->selection_end;
5221 es->composition_len = 0;
5222#endif
5223 break;
5224
5225 case WM_IME_COMPOSITION:
5227#ifdef __REACTOS__
5229#endif
5230 break;
5231
5232 case WM_IME_ENDCOMPOSITION:
5233#ifdef __REACTOS__
5235#else
5236 if (es->composition_len > 0)
5237 {
5239 es->selection_end = es->selection_start;
5240 es->composition_len= 0;
5241 }
5242#endif
5243 break;
5244
5246 break;
5247
5248 case WM_IME_SELECT:
5249#ifdef __REACTOS__
5251#endif
5252 break;
5253
5254 case WM_IME_CONTROL:
5255#ifdef __REACTOS__
5257#endif
5258 break;
5259
5260 case WM_IME_REQUEST:
5261 switch (wParam)
5262 {
5263 case IMR_QUERYCHARPOSITION:
5264 {
5265 IMECHARPOSITION *chpos = (IMECHARPOSITION *)lParam;
5266 LRESULT pos;
5267
5268 pos = EDIT_EM_PosFromChar(es, es->selection_start + chpos->dwCharPos, FALSE);
5269 chpos->pt.x = LOWORD(pos);
5270 chpos->pt.y = HIWORD(pos);
5271 chpos->cLineHeight = es->line_height;
5272 chpos->rcDocument = es->format_rect;
5273 MapWindowPoints(hwnd, 0, &chpos->pt, 1);
5274 MapWindowPoints(hwnd, 0, (POINT*)&chpos->rcDocument, 2);
5275 result = 1;
5276 break;
5277 }
5278 }
5279 break;
5280
5281 case WM_THEMECHANGED:
5282 CloseThemeData (theme);
5284 break;
5285
5286 default:
5288 break;
5289 }
5290
5291 if (IsWindow(hwnd) && es && msg != EM_GETHANDLE)
5293
5294 TRACE("hwnd=%p msg=%x -- 0x%08lx\n", hwnd, msg, result);
5295
5296 return result;
5297}
5299void EDIT_Register(void)
5300{
5301 WNDCLASSW wndClass;
5302
5303 memset(&wndClass, 0, sizeof(wndClass));
5305 wndClass.lpfnWndProc = EDIT_WindowProc;
5306 wndClass.cbClsExtra = 0;
5307#ifdef __i386__
5308 wndClass.cbWndExtra = sizeof(EDITSTATE *) + sizeof(WORD);
5309#else
5310 wndClass.cbWndExtra = sizeof(EDITSTATE *);
5311#endif
5312 wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_IBEAM);
5313 wndClass.hbrBackground = NULL;
5314 wndClass.lpszClassName = WC_EDITW;
5315 RegisterClassW(&wndClass);
5316}
5317
5318#ifdef __REACTOS__
5319void EDIT_Unregister(void)
5320{
5322}
5323#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:73
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
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:4725
static void EDIT_WM_Paint(EDITSTATE *es, HDC hdc)
Definition: edit.c:3628
static void EDIT_MoveEnd(EDITSTATE *es, BOOL extend, BOOL ctrl)
Definition: edit.c:1896
static void EDIT_PaintLine(EDITSTATE *es, HDC dc, INT line, BOOL rev)
Definition: edit.c:2179
static void EDIT_GetResultStr(HIMC hIMC, EDITSTATE *es)
Definition: edit.c:4446
static BOOL EDIT_IsInsideDialog(EDITSTATE *es)
Definition: edit.c:2982
#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:3513
static void EDIT_MoveBackward(EDITSTATE *es, BOOL extend)
Definition: edit.c:1847
static LRESULT EDIT_WM_Char(EDITSTATE *es, WCHAR c)
Definition: edit.c:3085
BOOL WINAPI GetCharWidthInfo(HDC, struct char_width_info *)
static void EDIT_WM_SetFont(EDITSTATE *es, HFONT font, BOOL redraw)
Definition: edit.c:3837
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:2490
#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:3584
static void EDIT_EM_ScrollCaret(EDITSTATE *es)
Definition: edit.c:1778
#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:3286
static void EDIT_SetRectNP(EDITSTATE *es, const RECT *rc)
Definition: edit.c:2317
static BOOL EDIT_EM_FmtLines(EDITSTATE *es, BOOL add_eol)
Definition: edit.c:2389
static void EDIT_WM_Copy(EDITSTATE *es)
Definition: edit.c:3029
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:4375
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:2022
static BOOL EDIT_EM_GetCueBanner(EDITSTATE *es, WCHAR *buf, DWORD size)
Definition: edit.c:4350
static INT EDIT_PaintText(EDITSTATE *es, HDC dc, INT x, INT y, INT line, INT col, INT count, BOOL rev)
Definition: edit.c:2105
static LRESULT EDIT_EM_CharFromPos(EDITSTATE *es, INT x, INT y)
Definition: edit.c:2361
static void EDIT_MoveHome(EDITSTATE *es, BOOL extend, BOOL ctrl)
Definition: edit.c:1942
static LRESULT EDIT_WM_HScroll(EDITSTATE *es, INT action, INT pos)
Definition: edit.c:4062
static void EDIT_WM_Cut(EDITSTATE *es)
Definition: edit.c:3073
static void EDIT_EM_SetPasswordChar(EDITSTATE *es, WCHAR c)
Definition: edit.c:2871
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:3717
struct tagLINEDEF LINEDEF
static void EDIT_AdjustFormatRect(EDITSTATE *es)
Definition: edit.c:2266
static INT EDIT_WM_GetText(const EDITSTATE *es, INT count, LPWSTR dst)
Definition: edit.c:3272
static void EDIT_WM_ContextMenu(EDITSTATE *es, INT x, INT y)
Definition: edit.c:3216
static LRESULT EDIT_WM_MouseMove(EDITSTATE *es, INT x, INT y)
Definition: edit.c:3596
static void EDIT_MovePageUp_ML(EDITSTATE *es, BOOL extend)
Definition: edit.c:1994
void EDIT_Register(void)
Definition: edit.c:5298
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:4695
static LRESULT EDIT_WM_LButtonDown(EDITSTATE *es, DWORD keys, INT x, INT y)
Definition: edit.c:3542
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:2411
static INT EDIT_EM_GetLine(EDITSTATE *es, INT line, LPWSTR dst)
Definition: edit.c:2431
#define EF_UPDATE
Definition: edit.c:67
static BOOL EDIT_EM_Undo(EDITSTATE *es)
Definition: edit.c:2941
static UINT get_text_length(EDITSTATE *es)
Definition: edit.c:216
static WCHAR * heap_strdupW(const WCHAR *str)
Definition: edit.c:4320
static void EDIT_InvalidateUniscribeData(EDITSTATE *es)
Definition: edit.c:315
static void EDIT_WM_Paste(EDITSTATE *es)
Definition: edit.c:2993
#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:1966
static LRESULT EDIT_WM_KillFocus(HTHEME theme, EDITSTATE *es)
Definition: edit.c:3485
static void EDIT_MoveWordForward(EDITSTATE *es, BOOL extend)
Definition: edit.c:2075
static int get_cjk_fontinfo_margin(int width, int side_bearing)
Definition: edit.c:2770
static LRESULT EDIT_WM_SysKeyDown(EDITSTATE *es, INT key, DWORD key_data)
Definition: edit.c:4025
static LRESULT EDIT_EM_GetThumb(EDITSTATE *es)
Definition: edit.c:4314
static LRESULT EDIT_WM_NCCreate(HWND hwnd, LPCREATESTRUCTW lpcs)
Definition: edit.c:4527
static LRESULT EDIT_WM_LButtonUp(EDITSTATE *es)
Definition: edit.c:3568
static void EDIT_WM_Clear(EDITSTATE *es)
Definition: edit.c:3058
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:2799
static void EDIT_MoveWordBackward(EDITSTATE *es, BOOL extend)
Definition: edit.c:2044
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:3779
#define HSCROLL_FRACTION
Definition: edit.c:60
static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc)
Definition: edit.c:2707
static LRESULT EDIT_WM_Create(EDITSTATE *es, const WCHAR *name)
Definition: edit.c:4640
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:3348
static void EDIT_EM_SetLimitText(EDITSTATE *es, UINT limit)
Definition: edit.c:2749
static void EDIT_WM_Timer(EDITSTATE *es)
Definition: edit.c:4044
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:4333
static void EDIT_MoveForward(EDITSTATE *es, BOOL extend)
Definition: edit.c:1917
#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:2469
static void EDIT_EM_SetWordBreakProc(EDITSTATE *es, EDITWORDBREAKPROCW wbp)
Definition: edit.c:2922
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:1874
#define EF_VSCROLL_TRACK
Definition: edit.c:68
static LRESULT EDIT_WM_StyleChanged(EDITSTATE *es, WPARAM which, const STYLESTRUCT *style)
Definition: edit.c:3985
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:3172
#define ORDER_UINT(x, y)
Definition: edit.c:164
static LRESULT EDIT_WM_VScroll(EDITSTATE *es, INT action, INT pos)
Definition: edit.c:4194
static BOOL EDIT_MakeFit(EDITSTATE *es, UINT size)
Definition: edit.c:1276
static void EDIT_WM_SetText(EDITSTATE *es, LPCWSTR text)
Definition: edit.c:3910
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:2900
static DWORD get_font_margins(HDC hdc, const TEXTMETRICW *tm)
Definition: edit.c:3805
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:4481
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:3952
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
static void cleanup(void)
Definition: main.c:1335
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
const UINT * keys
Definition: locale.c:416
DWORD WINAPI CharLowerBuffW(WCHAR *str, DWORD len)
Definition: string.c:1086
DWORD WINAPI CharUpperBuffW(WCHAR *str, DWORD len)
Definition: string.c:1199
const WCHAR * text
Definition: package.c:1794
HRESULT WINAPI ScriptStringFree(SCRIPT_STRING_ANALYSIS *pssa)
Definition: usp10.c:2577
HRESULT WINAPI ScriptStringGetLogicalWidths(SCRIPT_STRING_ANALYSIS ssa, int *piDx)
Definition: usp10.c:3825
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:2387
const SIZE *WINAPI ScriptString_pSize(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3897
const int *WINAPI ScriptString_pcOutChars(SCRIPT_STRING_ANALYSIS ssa)
Definition: usp10.c:3959
HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int *piCh, int *piTrailing)
Definition: usp10.c:2495
HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrailing, int *pX)
Definition: usp10.c:2432
HRESULT WINAPI ScriptBreak(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la)
Definition: usp10.c:3068
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 GetWindowTheme(HWND hwnd)
Definition: system.c:911
HRESULT WINAPI CloseThemeData(HTHEME hTheme)
Definition: system.c:1027
HTHEME WINAPI OpenThemeData(HWND hwnd, LPCWSTR pszClassList)
Definition: system.c:881
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
return ret
Definition: mutex.c:146
action
Definition: namespace.c:707
#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
BOOL WINAPI ImmSetCompositionFontW(_In_ HIMC hIMC, _In_ LPLOGFONTW lplf)
Definition: ime.c:1322
struct INPUTCONTEXTDX * LPINPUTCONTEXTDX
#define IS_IME_HKL(hKL)
Definition: imm32_undoc.h:21
#define CFS_RECT
Definition: imm.h:324
#define CPS_CANCEL
Definition: imm.h:181
#define GCS_COMPATTR
Definition: imm.h:228
BOOL WINAPI ImmSetCompositionWindow(_In_ HIMC hIMC, _In_ LPCOMPOSITIONFORM lpCompForm)
Definition: ime.c:1149
#define GCS_RESULTSTR
Definition: imm.h:234
HIMC WINAPI ImmGetContext(_In_ HWND hWnd)
Definition: imm.c:1065
#define CFS_POINT
Definition: imm.h:325
BOOL WINAPI ImmReleaseContext(_In_ HWND hWnd, _In_ HIMC hIMC)
Definition: imm.c:1109
#define GCS_COMPSTR
Definition: imm.h:227
#define GCS_CURSORPOS
Definition: imm.h:230
LONG WINAPI ImmGetCompositionStringW(_In_ HIMC hIMC, _In_ DWORD dwIndex, _Out_writes_bytes_opt_(dwBufLen) LPVOID lpBuf, _In_ DWORD dwBufLen)
Definition: compstr.c:908
BOOL WINAPI ImmNotifyIME(_In_ HIMC hIMC, _In_ DWORD dwAction, _In_ DWORD dwIndex, _In_ DWORD_PTR dwValue)
Definition: ime.c:458
LPINPUTCONTEXT WINAPI ImmLockIMC(_In_ HIMC hIMC)
Definition: imm.c:1079
#define NI_COMPOSITIONSTR
Definition: immdev.h:381
BOOL WINAPI ImmUnlockIMC(_In_ HIMC hIMC)
Definition: imm.c:1089
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:125
__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 PRIMARYLANGID(l)
Definition: nls.h:16
#define LANG_KOREAN
Definition: nls.h:84
#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:3261
HBRUSH hbrBackground
Definition: winuser.h:3259
int cbClsExtra
Definition: winuser.h:3254
UINT style
Definition: winuser.h:3252
WNDPROC lpfnWndProc
Definition: winuser.h:3253
int cbWndExtra
Definition: winuser.h:3255
HCURSOR hCursor
Definition: winuser.h:3258
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
static GLenum which
Definition: wgl_font.c:159
LINE_END
Definition: edit.c:84
#define LMEM_MOVEABLE
Definition: winbase.h:402
#define LMEM_ZEROINIT
Definition: winbase.h:408
#define GMEM_MOVEABLE
Definition: winbase.h:327
#define GMEM_DDESHARE
Definition: winbase.h:331
_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:860
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:917
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:1639
HWND WINAPI GetFocus(void)
Definition: window.c:1863
HWND WINAPI SetCapture(_In_ HWND hWnd)
#define EM_SETREADONLY
Definition: winuser.h:2034
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define WM_ERASEBKGND
Definition: winuser.h:1644
DWORD WINAPI GetSysColor(_In_ int)
#define MAKEWPARAM(l, h)
Definition: winuser.h:4085
BOOL WINAPI CopyRect(_Out_ LPRECT, _In_ LPCRECT)
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define WM_CTLCOLORSTATIC
Definition: winuser.h:1791
#define MK_SHIFT
Definition: winuser.h:2388
#define WM_GETTEXTLENGTH
Definition: winuser.h:1638
#define EM_GETRECT
Definition: winuser.h:2015
HKL WINAPI GetKeyboardLayout(_In_ DWORD)
#define WM_IME_REQUEST
Definition: winuser.h:1855
#define WM_CLOSE
Definition: winuser.h:1640
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:4905
BOOL WINAPI ShowCaret(_In_opt_ HWND)
#define EM_LINEFROMCHAR
Definition: winuser.h:2020
#define VK_TAB
Definition: winuser.h:2218
HDC WINAPI GetWindowDC(_In_opt_ HWND)
#define WM_ENABLE
Definition: winuser.h:1634
#define SM_CYEDGE
Definition: winuser.h:1020
#define SB_LINEUP
Definition: winuser.h:564
#define WM_HSCROLL
Definition: winuser.h:1762
#define WM_PASTE
Definition: winuser.h:1882
#define EN_KILLFOCUS
Definition: winuser.h:2044
#define COLOR_GRAYTEXT
Definition: winuser.h:943
#define EM_GETWORDBREAKPROC
Definition: winuser.h:2018
#define EM_FMTLINES
Definition: winuser.h:2005
BOOL WINAPI ReleaseCapture(void)
Definition: message.c:2890
#define EM_GETPASSWORDCHAR
Definition: winuser.h:2014
#define COLOR_WINDOWFRAME
Definition: winuser.h:930
#define DCX_WINDOW
Definition: winuser.h:2132
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define EC_RIGHTMARGIN
Definition: winuser.h:2626
#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:1763
#define TPM_RIGHTBUTTON
Definition: winuser.h:2399
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
#define SIF_RANGE
Definition: winuser.h:1246
#define WM_CREATE
Definition: winuser.h:1627
#define DLGC_WANTCHARS
Definition: winuser.h:2637
#define CB_SHOWDROPDOWN
Definition: winuser.h:1989
#define EM_GETSEL
Definition: winuser.h:2016
#define EN_SETFOCUS
Definition: winuser.h:2046
#define EM_SETPASSWORDCHAR
Definition: winuser.h:2033
#define EN_UPDATE
Definition: winuser.h:2047
#define EM_GETMODIFY
Definition: winuser.h:2013
#define SB_PAGERIGHT
Definition: winuser.h:571
#define WB_ISDELIMITER
Definition: winuser.h:549
#define WM_SIZE
Definition: winuser.h:1630
#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:2004
#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:2631
#define WM_LBUTTONDBLCLK
Definition: winuser.h:1797
#define WM_COMMAND
Definition: winuser.h:1759
#define SW_INVALIDATE
Definition: winuser.h:2598
#define EM_REPLACESEL
Definition: winuser.h:2025
#define EC_USEFONTINFO
Definition: winuser.h:2627
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
BOOL WINAPI CloseClipboard(void)
Definition: ntwrapper.h:178
#define VK_CONTROL
Definition: winuser.h:2222
#define EM_SETRECT
Definition: winuser.h:2035
#define DC_HASDEFID
Definition: winuser.h:2628
#define VK_UP
Definition: winuser.h:2244
BOOL WINAPI IsRectEmpty(_In_ LPCRECT)
#define WM_SETFOCUS
Definition: winuser.h:1632
#define SIF_PAGE
Definition: winuser.h:1244
#define WM_MOUSEMOVE
Definition: winuser.h:1794
#define WM_GETTEXT
Definition: winuser.h:1637
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:2405
BOOL WINAPI OpenClipboard(_In_opt_ HWND)
#define WM_CUT
Definition: winuser.h:1880
#define SB_LINERIGHT
Definition: winuser.h:567
#define CS_DBLCLKS
Definition: winuser.h:659
#define EN_MAXTEXT
Definition: winuser.h:2045
#define WM_LBUTTONDOWN
Definition: winuser.h:1795
#define EM_LINEINDEX
Definition: winuser.h:2021
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2442
#define EN_HSCROLL
Definition: winuser.h:2043
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:1670
#define EM_LINESCROLL
Definition: winuser.h:2023
#define EM_GETFIRSTVISIBLELINE
Definition: winuser.h:2007
#define EM_GETHANDLE
Definition: winuser.h:2008
BOOL WINAPI ClientToScreen(_In_ HWND, _Inout_ LPPOINT)
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
#define WM_NEXTDLGCTL
Definition: winuser.h:1662
#define WM_UNDO
Definition: winuser.h:1884
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
#define VK_NEXT
Definition: winuser.h:2240
#define WM_NCCREATE
Definition: winuser.h:1702
#define WM_IME_SETCONTEXT
Definition: winuser.h:1848
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
#define WM_SETTEXT
Definition: winuser.h:1636
#define EM_CANUNDO
Definition: winuser.h:2002
#define EM_LINELENGTH
Definition: winuser.h:2022
#define SM_CYBORDER
Definition: winuser.h:976
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define DCX_INTERSECTRGN
Definition: winuser.h:2141
#define WM_IME_CHAR
Definition: winuser.h:1853
#define EM_SETHANDLE
Definition: winuser.h:2028
#define VK_RETURN
Definition: winuser.h:2220
#define EM_GETLINE
Definition: winuser.h:2010
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
#define EM_SETRECTNP
Definition: winuser.h:2036
#define SB_LINELEFT
Definition: winuser.h:566
HWND WINAPI SetFocus(_In_opt_ HWND)
#define SIZE_MAXIMIZED
Definition: winuser.h:2526
#define MF_ENABLED
Definition: winuser.h:128
#define MK_CONTROL
Definition: winuser.h:2389
#define EM_SETLIMITTEXT
Definition: winuser.h:2030
#define WB_LEFT
Definition: winuser.h:550
#define WM_SETFONT
Definition: winuser.h:1669
#define WM_TIMER
Definition: winuser.h:1761
#define VK_END
Definition: winuser.h:2241
#define TPM_LEFTALIGN
Definition: winuser.h:2396
#define VK_HOME
Definition: winuser.h:2242
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define MF_BYPOSITION
Definition: winuser.h:203
#define EM_UNDO
Definition: winuser.h:2040
#define SM_CXBORDER
Definition: winuser.h:975
#define DLGC_WANTARROWS
Definition: winuser.h:2629
#define SIF_DISABLENOSCROLL
Definition: winuser.h:1247
#define EM_SCROLL
Definition: winuser.h:2026
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:2039
#define IDC_IBEAM
Definition: winuser.h:696
#define VK_BACK
Definition: winuser.h:2217
#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:2037
#define VK_F4
Definition: winuser.h:2277
int(CALLBACK * EDITWORDBREAKPROCW)(LPWSTR, int, int, int)
Definition: winuser.h:2981
#define CB_GETDROPPEDSTATE
Definition: winuser.h:1964
#define ES_NUMBER
Definition: winuser.h:301
#define WM_LBUTTONUP
Definition: winuser.h:1796
#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:1851
#define WM_CHAR
Definition: winuser.h:1736
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:2243
#define WM_NCDESTROY
Definition: winuser.h:1703
#define VK_RIGHT
Definition: winuser.h:2245
#define SIZE_RESTORED
Definition: winuser.h:2524
#define SB_TOP
Definition: winuser.h:578
#define EN_VSCROLL
Definition: winuser.h:2048
#define CB_GETEXTENDEDUI
Definition: winuser.h:1967
#define SIF_POS
Definition: winuser.h:1245
#define VK_DOWN
Definition: winuser.h:2246
#define GWLP_ID
Definition: winuser.h:871
#define WM_COPY
Definition: winuser.h:1881
#define EM_GETTHUMB
Definition: winuser.h:2017
#define SB_ENDSCROLL
Definition: winuser.h:574
#define EM_GETMARGINS
Definition: winuser.h:2012
#define WM_IME_CONTROL
Definition: winuser.h:1850
BOOL WINAPI OffsetRect(_Inout_ LPRECT, _In_ int, _In_ int)
#define VK_SHIFT
Definition: winuser.h:2221
#define EM_SETTABSTOPS
Definition: winuser.h:2038
#define DLGC_WANTMESSAGE
Definition: winuser.h:2632
BOOL WINAPI TrackPopupMenu(_In_ HMENU, _In_ UINT, _In_ int, _In_ int, _Reserved_ int, _In_ HWND, _Reserved_ LPCRECT)
#define VK_PRIOR
Definition: winuser.h:2239
int WINAPI SetScrollInfo(_In_ HWND, _In_ int, _In_ LPCSCROLLINFO, _In_ BOOL)
#define VK_DELETE
Definition: winuser.h:2252
#define WM_IME_SELECT
Definition: winuser.h:1852
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
#define WS_EX_CLIENTEDGE
Definition: winuser.h:384
#define WM_CLEAR
Definition: winuser.h:1883
#define WM_KEYDOWN
Definition: winuser.h:1734
#define CB_SETEXTENDEDUI
Definition: winuser.h:1983
#define EM_GETLINECOUNT
Definition: winuser.h:2011
#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:2625
#define DM_GETDEFID
Definition: winuser.h:2117
#define TPM_RETURNCMD
Definition: winuser.h:2406
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
BOOL WINAPI KillTimer(_In_opt_ HWND, _In_ UINT_PTR)
#define SystemParametersInfo
Definition: winuser.h:5943
#define SetWindowLongPtrW
Definition: winuser.h:5431
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
#define EN_ERRSPACE
Definition: winuser.h:2042
#define GWL_STYLE
Definition: winuser.h:863
#define CS_PARENTDC
Definition: winuser.h:664
#define EM_SETMARGINS
Definition: winuser.h:2031
#define WM_CTLCOLOREDIT
Definition: winuser.h:1786
#define VK_ESCAPE
Definition: winuser.h:2233
#define DLGC_HASSETSEL
Definition: winuser.h:2633
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:1633
int WINAPI GetSystemMetrics(_In_ int)
#define SB_PAGEUP
Definition: winuser.h:568
#define WM_SYSKEYDOWN
Definition: winuser.h:1738
BOOL WINAPI IsClipboardFormatAvailable(_In_ UINT)
#define VK_INSERT
Definition: winuser.h:2251
#define RDW_INVALIDATE
Definition: winuser.h:1225
#define WM_GETDLGCODE
Definition: winuser.h:1708
#define WM_MBUTTONDOWN
Definition: winuser.h:1801
#define EM_SETMODIFY
Definition: winuser.h:2032
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:2223
#define WM_NCPAINT
Definition: winuser.h:1706
#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:2041
#define WM_SETREDRAW
Definition: winuser.h:1635
#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