ReactOS 0.4.16-dev-250-g3ecd236
caret.c
Go to the documentation of this file.
1/*
2 * RichEdit - Caret and selection functions.
3 *
4 * Copyright 2004 by Krzysztof Foltman
5 * Copyright 2005 by Phil Krylov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22
23#include "editor.h"
24
26
28{
29 cursor->pPara = editor->pBuffer->pFirst->member.para.next_para;
30 cursor->pRun = ME_FindItemFwd(cursor->pPara, diRun);
31 cursor->nOffset = 0;
32}
33
34static void ME_SetCursorToEnd(ME_TextEditor *editor, ME_Cursor *cursor, BOOL final_eop)
35{
36 cursor->pPara = editor->pBuffer->pLast->member.para.prev_para;
37 cursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
38 cursor->nOffset = final_eop ? cursor->pRun->member.run.len : 0;
39}
40
41
42int ME_GetSelectionOfs(ME_TextEditor *editor, int *from, int *to)
43{
44 *from = ME_GetCursorOfs(&editor->pCursors[0]);
45 *to = ME_GetCursorOfs(&editor->pCursors[1]);
46
47 if (*from > *to)
48 {
49 int tmp = *from;
50 *from = *to;
51 *to = tmp;
52 return 1;
53 }
54 return 0;
55}
56
58{
59 int from_ofs = ME_GetCursorOfs( &editor->pCursors[0] );
60 int to_ofs = ME_GetCursorOfs( &editor->pCursors[1] );
61 BOOL swap = (from_ofs > to_ofs);
62
63 if (from_ofs == to_ofs)
64 {
65 /* If cursor[0] is at the beginning of a run and cursor[1] at the end
66 of the prev run then we need to swap. */
67 if (editor->pCursors[0].nOffset < editor->pCursors[1].nOffset)
68 swap = TRUE;
69 }
70
71 if (!swap)
72 {
73 *from = &editor->pCursors[0];
74 *to = &editor->pCursors[1];
75 return 0;
76 } else {
77 *from = &editor->pCursors[1];
78 *to = &editor->pCursors[0];
79 return 1;
80 }
81}
82
84{
87 return ME_GetCursorOfs(&cursor);
88}
89
90
92{
93 int length;
94
95 if (how->flags & GTL_PRECISE && how->flags & GTL_CLOSE)
96 return E_INVALIDARG;
97 if (how->flags & GTL_NUMCHARS && how->flags & GTL_NUMBYTES)
98 return E_INVALIDARG;
99
100 length = ME_GetTextLength(editor);
101
102 if ((editor->styleFlags & ES_MULTILINE)
103 && (how->flags & GTL_USECRLF)
104 && !editor->bEmulateVersion10) /* Ignore GTL_USECRLF flag in 1.0 emulation */
105 length += editor->nParagraphs - 1;
106
107 if (how->flags & GTL_NUMBYTES ||
108 (how->flags & GTL_PRECISE && /* GTL_PRECISE seems to imply GTL_NUMBYTES */
109 !(how->flags & GTL_NUMCHARS))) /* unless GTL_NUMCHARS is given */
110 {
111 CPINFO cpinfo;
112
113 if (how->codepage == 1200)
114 return length * 2;
115 if (how->flags & GTL_PRECISE)
116 FIXME("GTL_PRECISE flag unsupported. Using GTL_CLOSE\n");
117 if (GetCPInfo(how->codepage, &cpinfo))
118 return length * cpinfo.MaxCharSize;
119 ERR("Invalid codepage %u\n", how->codepage);
120 return E_INVALIDARG;
121 }
122 return length;
123}
124
125/******************************************************************
126 * set_selection_cursors
127 *
128 * Updates the selection cursors.
129 *
130 * Note that this does not invalidate either the old or the new selections.
131 */
132int set_selection_cursors(ME_TextEditor *editor, int from, int to)
133{
134 int selectionEnd = 0;
135 const int len = ME_GetTextLength(editor);
136
137 /* all negative values are effectively the same */
138 if (from < 0)
139 from = -1;
140 if (to < 0)
141 to = -1;
142
143 /* select all */
144 if (from == 0 && to == -1)
145 {
146 ME_SetCursorToStart(editor, &editor->pCursors[1]);
147 ME_SetCursorToEnd(editor, &editor->pCursors[0], TRUE);
148 return len + 1;
149 }
150
151 /* if both values are equal and also out of bound, that means to */
152 /* put the selection at the end of the text */
153 if ((from == to) && (to < 0 || to > len))
154 {
155 selectionEnd = 1;
156 }
157 else
158 {
159 /* if from is negative and to is positive then selection is */
160 /* deselected and caret moved to end of the current selection */
161 if (from < 0)
162 {
163 int start, end;
164 ME_GetSelectionOfs(editor, &start, &end);
165 if (start != end)
166 {
167 if (end > len)
168 {
169 editor->pCursors[0].nOffset = 0;
170 end --;
171 }
172 editor->pCursors[1] = editor->pCursors[0];
173 }
174 return end;
175 }
176
177 /* adjust to if it's a negative value */
178 if (to < 0)
179 to = len + 1;
180
181 /* flip from and to if they are reversed */
182 if (from>to)
183 {
184 int tmp = from;
185 from = to;
186 to = tmp;
187 }
188
189 /* after fiddling with the values, we find from > len && to > len */
190 if (from > len)
191 selectionEnd = 1;
192 /* special case with to too big */
193 else if (to > len)
194 to = len + 1;
195 }
196
197 if (selectionEnd)
198 {
199 ME_SetCursorToEnd(editor, &editor->pCursors[0], FALSE);
200 editor->pCursors[1] = editor->pCursors[0];
201 return len;
202 }
203
204 ME_CursorFromCharOfs(editor, from, &editor->pCursors[1]);
205 editor->pCursors[0] = editor->pCursors[1];
206 ME_MoveCursorChars(editor, &editor->pCursors[0], to - from, FALSE);
207 /* Selection is not allowed in the middle of an end paragraph run. */
208 if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA)
209 editor->pCursors[1].nOffset = 0;
210 if (editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA)
211 {
212 if (to > len)
213 editor->pCursors[0].nOffset = editor->pCursors[0].pRun->member.run.len;
214 else
215 editor->pCursors[0].nOffset = 0;
216 }
217 return to;
218}
219
220
222 int *x, int *y, int *height)
223{
225 ME_DisplayItem *run = pCursor->pRun;
226 ME_DisplayItem *para = pCursor->pPara;
227 ME_DisplayItem *pSizeRun = run;
229 int run_x;
230
231 assert(height && x && y);
233 assert(run && run->type == diRun);
234 assert(para && para->type == diParagraph);
235
237 assert(row && row->type == diStartRow);
238
239 ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
240
241 if (!pCursor->nOffset)
242 {
244 assert(prev);
245 if (prev->type == diRun)
246 pSizeRun = prev;
247 }
248 if (editor->bCaretAtEnd && !pCursor->nOffset &&
249 run == ME_FindItemFwd(row, diRun))
250 {
252 assert(tmp);
253 if (tmp->type == diRun)
254 {
256 pSizeRun = run = tmp;
257 assert(run);
258 assert(run->type == diRun);
259 }
260 }
261 run_x = ME_PointFromCharContext( &c, &run->member.run, pCursor->nOffset, TRUE );
262
263 *height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent;
264 *x = c.rcView.left + run->member.run.pt.x + run_x - editor->horz_si.nPos;
265 *y = c.rcView.top + para->member.para.pt.y + row->member.row.nBaseline
266 + run->member.run.pt.y - pSizeRun->member.run.nAscent
267 - editor->vert_si.nPos;
269 return;
270}
271
273{
274 int x, y, height;
275
276 ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height);
278 editor->caret_height = height;
279 editor->caret_hidden = TRUE;
280}
281
283{
285 editor->caret_hidden = FALSE;
286}
287
289{
290 /* calls to HideCaret are cumulative; do so only once */
291 if (!editor->caret_hidden)
292 {
294 editor->caret_hidden = TRUE;
295 }
296}
297
299{
300 int x, y, height;
301
302 if (!editor->bHaveFocus) return;
303 if (!ME_IsSelection(editor))
304 {
305 ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height);
306 if (height != editor->caret_height) create_caret(editor);
307 x = min(x, editor->rcFormat.right-1);
309 show_caret(editor);
310 }
311 else
312 hide_caret(editor);
313#ifdef __REACTOS__
315 {
316 HIMC hIMC = ImmGetContext(editor->hWnd);
317 if (hIMC)
318 {
320 LOGFONTW lf;
321 COMPOSITIONFORM CompForm;
322 POINT pt = { x, y };
323
324 CompForm.ptCurrentPos = pt;
325 if (editor->styleFlags & ES_MULTILINE)
326 {
327 CompForm.dwStyle = CFS_RECT;
328 CompForm.rcArea = editor->rcFormat;
329 }
330 else
331 {
332 CompForm.dwStyle = CFS_POINT;
333 SetRectEmpty(&CompForm.rcArea);
334 }
335 ImmSetCompositionWindow(hIMC, &CompForm);
336
337 fmt.cbSize = sizeof(fmt);
339
340 ZeroMemory(&lf, sizeof(lf));
342 if (fmt.dwMask & CFM_SIZE)
343 {
345 lf.lfHeight = -MulDiv(fmt.yHeight, GetDeviceCaps(hdc, LOGPIXELSY), 1440);
346 DeleteDC(hdc);
347 }
348 if (fmt.dwMask & CFM_CHARSET)
349 lf.lfCharSet = fmt.bCharSet;
350 if (fmt.dwMask & CFM_FACE)
351 lstrcpynW(lf.lfFaceName, fmt.szFaceName, ARRAY_SIZE(lf.lfFaceName));
352 ImmSetCompositionFontW(hIMC, &lf);
353
354 ImmReleaseContext(editor->hWnd, hIMC);
355 }
356 }
357#endif
358}
359
361 int nChars, BOOL bForce)
362{
363 ME_Cursor c = *start;
364 int nOfs = ME_GetCursorOfs(start), text_len = ME_GetTextLength( editor );
365 int shift = 0;
366 int totalChars = nChars;
367 ME_DisplayItem *start_para;
368 BOOL delete_all = FALSE;
369
370 /* Prevent deletion past last end of paragraph run. */
371 nChars = min(nChars, text_len - nOfs);
372 if (nChars == text_len) delete_all = TRUE;
373 start_para = c.pPara;
374
375 if (!bForce)
376 {
377 ME_ProtectPartialTableDeletion(editor, &c, &nChars);
378 if (nChars == 0)
379 return FALSE;
380 }
381
382 while(nChars > 0)
383 {
384 ME_Run *run;
385 ME_CursorFromCharOfs(editor, nOfs+nChars, &c);
386 if (!c.nOffset &&
387 nOfs+nChars == (c.pRun->member.run.nCharOfs
388 + c.pPara->member.para.nCharOfs))
389 {
390 /* We aren't deleting anything in this run, so we will go back to the
391 * last run we are deleting text in. */
392 ME_PrevRun(&c.pPara, &c.pRun, TRUE);
393 c.nOffset = c.pRun->member.run.len;
394 }
395 run = &c.pRun->member.run;
396 if (run->nFlags & MERF_ENDPARA) {
397 int eollen = c.pRun->member.run.len;
398 BOOL keepFirstParaFormat;
399
400 if (!ME_FindItemFwd(c.pRun, diParagraph))
401 {
402 return TRUE;
403 }
404 keepFirstParaFormat = (totalChars == nChars && nChars <= eollen &&
405 run->nCharOfs);
406 if (!editor->bEmulateVersion10) /* v4.1 */
407 {
409 ME_DisplayItem *this_para = next_para->member.para.prev_para;
410
411 /* The end of paragraph before a table row is only deleted if there
412 * is nothing else on the line before it. */
413 if (this_para == start_para &&
414 next_para->member.para.nFlags & MEPF_ROWSTART)
415 {
416 /* If the paragraph will be empty, then it should be deleted, however
417 * it still might have text right now which would inherit the
418 * MEPF_STARTROW property if we joined it right now.
419 * Instead we will delete it after the preceding text is deleted. */
420 if (nOfs > this_para->member.para.nCharOfs) {
421 /* Skip this end of line. */
422 nChars -= (eollen < nChars) ? eollen : nChars;
423 continue;
424 }
425 keepFirstParaFormat = TRUE;
426 }
427 }
428 ME_JoinParagraphs(editor, c.pPara, keepFirstParaFormat);
429 /* ME_SkipAndPropagateCharOffset(p->pRun, shift); */
430 ME_CheckCharOffsets(editor);
431 nChars -= (eollen < nChars) ? eollen : nChars;
432 continue;
433 }
434 else
435 {
437 int nCharsToDelete = min(nChars, c.nOffset);
438 int i;
439
440 c.nOffset -= nCharsToDelete;
441
443
444 cursor = c;
445 /* nChars is the number of characters that should be deleted from the
446 PRECEDING runs (these BEFORE cursor.pRun)
447 nCharsToDelete is a number of chars to delete from THIS run */
448 nChars -= nCharsToDelete;
449 shift -= nCharsToDelete;
450 TRACE("Deleting %d (remaining %d) chars at %d in %s (%d)\n",
451 nCharsToDelete, nChars, c.nOffset,
452 debugstr_run( run ), run->len);
453
454 /* nOfs is a character offset (from the start of the document
455 to the current (deleted) run */
456 add_undo_insert_run( editor, nOfs + nChars, get_text( run, c.nOffset ), nCharsToDelete, run->nFlags, run->style );
457
458 ME_StrDeleteV(run->para->text, run->nCharOfs + c.nOffset, nCharsToDelete);
459 run->len -= nCharsToDelete;
460 TRACE("Post deletion string: %s (%d)\n", debugstr_run( run ), run->len);
461 TRACE("Shift value: %d\n", shift);
462
463 /* update cursors (including c) */
464 for (i=-1; i<editor->nCursors; i++) {
465 ME_Cursor *pThisCur = editor->pCursors + i;
466 if (i == -1) pThisCur = &c;
467 if (pThisCur->pRun == cursor.pRun) {
468 if (pThisCur->nOffset > cursor.nOffset) {
469 if (pThisCur->nOffset-cursor.nOffset < nCharsToDelete)
470 pThisCur->nOffset = cursor.nOffset;
471 else
472 pThisCur->nOffset -= nCharsToDelete;
473 assert(pThisCur->nOffset >= 0);
474 assert(pThisCur->nOffset <= run->len);
475 }
476 if (pThisCur->nOffset == run->len)
477 {
478 pThisCur->pRun = ME_FindItemFwd(pThisCur->pRun, diRunOrParagraphOrEnd);
479 assert(pThisCur->pRun->type == diRun);
480 pThisCur->nOffset = 0;
481 }
482 }
483 }
484
485 /* c = updated data now */
486
487 if (c.pRun == cursor.pRun)
489 else
491
492 if (!cursor.pRun->member.run.len)
493 {
494 TRACE("Removing empty run\n");
495 ME_Remove(cursor.pRun);
497 }
498
499 shift = 0;
500 /*
501 ME_CheckCharOffsets(editor);
502 */
503 continue;
504 }
505 }
506 if (delete_all) ME_SetDefaultParaFormat( editor, &start_para->member.para.fmt );
507 return TRUE;
508}
509
510BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars)
511{
512 assert(nCursor>=0 && nCursor<editor->nCursors);
513 /* text operations set modified state */
514 editor->nModifyStep = 1;
515 return ME_InternalDeleteText(editor, &editor->pCursors[nCursor],
516 nChars, FALSE);
517}
518
519static ME_DisplayItem *
521 const WCHAR *str, int len, ME_Style *style,
522 int flags)
523{
524 ME_Cursor *p = &editor->pCursors[nCursor];
525
526 editor->bCaretAtEnd = FALSE;
527
528 assert(p->pRun->type == diRun);
529
530 return ME_InsertRunAtCursor(editor, p, style, str, len, flags);
531}
532
533static struct re_object* create_re_object(const REOBJECT *reo)
534{
535 struct re_object *reobj = heap_alloc(sizeof(*reobj));
536
537 if (!reobj)
538 {
539 WARN("Fail to allocate re_object.\n");
540 return NULL;
541 }
542 ME_CopyReObject(&reobj->obj, reo, REO_GETOBJ_ALL_INTERFACES);
543 return reobj;
544}
545
546void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor)
547{
548 ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
549 ME_DisplayItem *di;
550 WCHAR space = ' ';
551 ME_DisplayItem *di_prev = NULL;
552 struct re_object *reobj_prev = NULL;
553
554 /* FIXME no no no */
555 if (ME_IsSelection(editor))
556 ME_DeleteSelection(editor);
557
558 di = ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle,
560 di->member.run.reobj = create_re_object(reo);
561
562 di_prev = di;
563 while (ME_PrevRun(NULL, &di_prev, TRUE))
564 {
565 if (di_prev->member.run.reobj)
566 {
567 reobj_prev = di_prev->member.run.reobj;
568 break;
569 }
570 }
571 if (reobj_prev)
572 list_add_after(&reobj_prev->entry, &di->member.run.reobj->entry);
573 else
574 list_add_head(&editor->reobj_list, &di->member.run.reobj->entry);
575
576 ME_ReleaseStyle(pStyle);
577}
578
579
580void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor)
581{
582 ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
583 WCHAR space = ' ';
584
585 /* FIXME no no no */
586 if (ME_IsSelection(editor))
587 ME_DeleteSelection(editor);
588
589 ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle,
591 ME_ReleaseStyle(pStyle);
592}
593
594
595void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
596 const WCHAR *str, int len, ME_Style *style)
597{
598 const WCHAR *pos;
599 ME_Cursor *p = NULL;
600 int oldLen;
601
602 /* FIXME really HERE ? */
603 if (ME_IsSelection(editor))
604 ME_DeleteSelection(editor);
605
606 /* FIXME: is this too slow? */
607 /* Didn't affect performance for WM_SETTEXT (around 50sec/30K) */
608 oldLen = ME_GetTextLength(editor);
609
610 /* text operations set modified state */
611 editor->nModifyStep = 1;
612
613 assert(style);
614
615 assert(nCursor>=0 && nCursor<editor->nCursors);
616 if (len == -1)
617 len = lstrlenW(str);
618
619 /* grow the text limit to fit our text */
620 if(editor->nTextLimit < oldLen +len)
621 editor->nTextLimit = oldLen + len;
622
623 pos = str;
624
625 while (len)
626 {
627 /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
628 while(pos - str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
629 pos++;
630
631 if (pos != str) { /* handle text */
632 ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
633 } else if (*pos == '\t') { /* handle tabs */
634 WCHAR tab = '\t';
635 ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
636 pos++;
637 } else { /* handle EOLs */
638 ME_DisplayItem *tp, *end_run, *run, *prev;
639 int eol_len = 0;
640
641 /* Check if new line is allowed for this control */
642 if (!(editor->styleFlags & ES_MULTILINE))
643 break;
644
645 /* Find number of CR and LF in end of paragraph run */
646 if (*pos =='\r')
647 {
648 if (len > 1 && pos[1] == '\n')
649 eol_len = 2;
650 else if (len > 2 && pos[1] == '\r' && pos[2] == '\n')
651 eol_len = 3;
652 else
653 eol_len = 1;
654 } else {
655 assert(*pos == '\n');
656 eol_len = 1;
657 }
658 pos += eol_len;
659
660 if (!editor->bEmulateVersion10 && eol_len == 3)
661 {
662 /* handle special \r\r\n sequence (richedit 2.x and higher only) */
663 WCHAR space = ' ';
664 ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);
665 } else {
666 const WCHAR cr = '\r', *eol_str = str;
667
668 if (!editor->bEmulateVersion10)
669 {
670 eol_str = &cr;
671 eol_len = 1;
672 }
673
674 p = &editor->pCursors[nCursor];
675
676 if (p->nOffset == p->pRun->member.run.len)
677 {
678 run = ME_FindItemFwd( p->pRun, diRun );
679 if (!run) run = p->pRun;
680 }
681 else
682 {
683 if (p->nOffset) ME_SplitRunSimple(editor, p);
684 run = p->pRun;
685 }
686
687 tp = ME_SplitParagraph(editor, run, style, eol_str, eol_len, 0);
688
689 end_run = ME_FindItemBack(tp, diRun);
690
691 /* Move any cursors that were at the end of the previous run to the beginning of the new para */
692 prev = ME_FindItemBack( end_run, diRun );
693 if (prev)
694 {
695 int i;
696 for (i = 0; i < editor->nCursors; i++)
697 {
698 if (editor->pCursors[i].pRun == prev &&
699 editor->pCursors[i].nOffset == prev->member.run.len)
700 {
701 editor->pCursors[i].pPara = tp;
702 editor->pCursors[i].pRun = run;
703 editor->pCursors[i].nOffset = 0;
704 }
705 }
706 }
707
708 }
709 }
710 len -= pos - str;
711 str = pos;
712 }
713}
714
715/* Move the cursor nRelOfs characters (either forwards or backwards)
716 * If final_eop is TRUE, allow moving the cursor to the end of the final eop.
717 *
718 * returns the actual number of characters moved.
719 **/
720int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BOOL final_eop)
721{
722 cursor->nOffset += nRelOfs;
723 if (cursor->nOffset < 0)
724 {
725 cursor->nOffset += cursor->pRun->member.run.nCharOfs;
726 if (cursor->nOffset >= 0)
727 {
728 /* new offset in the same paragraph */
729 do {
730 cursor->pRun = ME_FindItemBack(cursor->pRun, diRun);
731 } while (cursor->nOffset < cursor->pRun->member.run.nCharOfs);
732 cursor->nOffset -= cursor->pRun->member.run.nCharOfs;
733 return nRelOfs;
734 }
735
736 cursor->nOffset += cursor->pPara->member.para.nCharOfs;
737 if (cursor->nOffset <= 0)
738 {
739 /* moved to the start of the text */
740 nRelOfs -= cursor->nOffset;
742 return nRelOfs;
743 }
744
745 /* new offset in a previous paragraph */
746 do {
747 cursor->pPara = cursor->pPara->member.para.prev_para;
748 } while (cursor->nOffset < cursor->pPara->member.para.nCharOfs);
749 cursor->nOffset -= cursor->pPara->member.para.nCharOfs;
750
751 cursor->pRun = ME_FindItemBack(cursor->pPara->member.para.next_para, diRun);
752 while (cursor->nOffset < cursor->pRun->member.run.nCharOfs) {
753 cursor->pRun = ME_FindItemBack(cursor->pRun, diRun);
754 }
755 cursor->nOffset -= cursor->pRun->member.run.nCharOfs;
756 } else if (cursor->nOffset >= cursor->pRun->member.run.len) {
757 ME_DisplayItem *next_para;
758 int new_offset;
759
760 new_offset = ME_GetCursorOfs(cursor);
761 next_para = cursor->pPara->member.para.next_para;
762 if (new_offset < next_para->member.para.nCharOfs)
763 {
764 /* new offset in the same paragraph */
765 do {
766 cursor->nOffset -= cursor->pRun->member.run.len;
767 cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun);
768 } while (cursor->nOffset >= cursor->pRun->member.run.len);
769 return nRelOfs;
770 }
771
772 if (new_offset >= ME_GetTextLength(editor) + (final_eop ? 1 : 0))
773 {
774 /* new offset at the end of the text */
775 ME_SetCursorToEnd(editor, cursor, final_eop);
776 nRelOfs -= new_offset - (ME_GetTextLength(editor) + (final_eop ? 1 : 0));
777 return nRelOfs;
778 }
779
780 /* new offset in a following paragraph */
781 do {
782 cursor->pPara = next_para;
783 next_para = next_para->member.para.next_para;
784 } while (new_offset >= next_para->member.para.nCharOfs);
785
786 cursor->nOffset = new_offset - cursor->pPara->member.para.nCharOfs;
787 cursor->pRun = ME_FindItemFwd(cursor->pPara, diRun);
788 while (cursor->nOffset >= cursor->pRun->member.run.len)
789 {
790 cursor->nOffset -= cursor->pRun->member.run.len;
791 cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun);
792 }
793 } /* else new offset is in the same run */
794 return nRelOfs;
795}
796
797
798BOOL
800{
801 ME_DisplayItem *pRun = cursor->pRun, *pOtherRun;
802 ME_DisplayItem *pPara = cursor->pPara;
803 int nOffset = cursor->nOffset;
804
805 if (nRelOfs == -1)
806 {
807 /* Backward movement */
808 while (TRUE)
809 {
810 nOffset = ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
811 pRun->member.run.len, nOffset, WB_MOVEWORDLEFT);
812 if (nOffset)
813 break;
814 pOtherRun = ME_FindItemBack(pRun, diRunOrParagraph);
815 if (pOtherRun->type == diRun)
816 {
817 if (ME_CallWordBreakProc(editor, get_text( &pOtherRun->member.run, 0 ),
818 pOtherRun->member.run.len,
819 pOtherRun->member.run.len - 1,
821 && !(pRun->member.run.nFlags & MERF_ENDPARA)
822 && !(cursor->pRun == pRun && cursor->nOffset == 0)
823 && !ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
824 pRun->member.run.len, 0,
826 break;
827 pRun = pOtherRun;
828 nOffset = pOtherRun->member.run.len;
829 }
830 else if (pOtherRun->type == diParagraph)
831 {
832 if (cursor->pRun == pRun && cursor->nOffset == 0)
833 {
834 pPara = pOtherRun;
835 /* Skip empty start of table row paragraph */
836 if (pPara->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART)
837 pPara = pPara->member.para.prev_para;
838 /* Paragraph breaks are treated as separate words */
839 if (pPara->member.para.prev_para->type == diTextStart)
840 return FALSE;
841
842 pRun = ME_FindItemBack(pPara, diRun);
843 pPara = pPara->member.para.prev_para;
844 }
845 break;
846 }
847 }
848 }
849 else
850 {
851 /* Forward movement */
852 BOOL last_delim = FALSE;
853
854 while (TRUE)
855 {
856 if (last_delim && !ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
857 pRun->member.run.len, nOffset, WB_ISDELIMITER))
858 break;
859 nOffset = ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
860 pRun->member.run.len, nOffset, WB_MOVEWORDRIGHT);
861 if (nOffset < pRun->member.run.len)
862 break;
863 pOtherRun = ME_FindItemFwd(pRun, diRunOrParagraphOrEnd);
864 if (pOtherRun->type == diRun)
865 {
866 last_delim = ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
867 pRun->member.run.len, nOffset - 1, WB_ISDELIMITER);
868 pRun = pOtherRun;
869 nOffset = 0;
870 }
871 else if (pOtherRun->type == diParagraph)
872 {
873 if (pOtherRun->member.para.nFlags & MEPF_ROWSTART)
874 pOtherRun = pOtherRun->member.para.next_para;
875 if (cursor->pRun == pRun) {
876 pPara = pOtherRun;
877 pRun = ME_FindItemFwd(pPara, diRun);
878 }
879 nOffset = 0;
880 break;
881 }
882 else /* diTextEnd */
883 {
884 if (cursor->pRun == pRun)
885 return FALSE;
886 nOffset = 0;
887 break;
888 }
889 }
890 }
891 cursor->pPara = pPara;
892 cursor->pRun = pRun;
893 cursor->nOffset = nOffset;
894 return TRUE;
895}
896
897
898static void
900{
901 /* pCursor[0] is the end of the selection
902 * pCursor[1] is the start of the selection (or the position selection anchor)
903 * pCursor[2] and [3] are the selection anchors that are backed up
904 * so they are kept when the selection changes for drag selection.
905 */
906
907 editor->nSelectionType = selectionType;
908 switch(selectionType)
909 {
910 case stPosition:
911 break;
912 case stWord:
913 ME_MoveCursorWords(editor, &editor->pCursors[0], +1);
914 editor->pCursors[1] = editor->pCursors[0];
915 ME_MoveCursorWords(editor, &editor->pCursors[1], -1);
916 break;
917 case stLine:
918 case stParagraph:
919 {
920 ME_DisplayItem *pItem;
921 ME_DIType fwdSearchType, backSearchType;
922 if (selectionType == stParagraph) {
923 backSearchType = diParagraph;
924 fwdSearchType = diParagraphOrEnd;
925 } else {
926 backSearchType = diStartRow;
927 fwdSearchType = diStartRowOrParagraphOrEnd;
928 }
929 pItem = ME_FindItemFwd(editor->pCursors[0].pRun, fwdSearchType);
930 assert(pItem);
931 if (pItem->type == diTextEnd)
932 editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun);
933 else
934 editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun);
935 editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun);
936 editor->pCursors[0].nOffset = 0;
937
938 pItem = ME_FindItemBack(pItem, backSearchType);
939 editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun);
940 editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun);
941 editor->pCursors[1].nOffset = 0;
942 break;
943 }
944 case stDocument:
945 /* Select everything with cursor anchored from the start of the text */
946 editor->nSelectionType = stDocument;
947 ME_SetCursorToStart(editor, &editor->pCursors[1]);
948 ME_SetCursorToEnd(editor, &editor->pCursors[0], FALSE);
949 break;
950 default: assert(0);
951 }
952 /* Store the anchor positions for extending the selection. */
953 editor->pCursors[2] = editor->pCursors[0];
954 editor->pCursors[3] = editor->pCursors[1];
955}
956
958{
959 return cursor->pPara->member.para.nCharOfs
960 + cursor->pRun->member.run.nCharOfs + cursor->nOffset;
961}
962
963/* Helper function for ME_FindPixelPos to find paragraph within tables */
965 ME_DisplayItem *para)
966{
967 ME_DisplayItem *cell, *next_cell;
969 cell = para->member.para.next_para->member.para.pCell;
970 assert(cell);
971
972 /* find the cell we are in */
973 while ((next_cell = cell->member.cell.next_cell) != NULL) {
974 if (x < next_cell->member.cell.pt.x)
975 {
976 para = ME_FindItemFwd(cell, diParagraph);
977 /* Found the cell, but there might be multiple paragraphs in
978 * the cell, so need to search down the cell for the paragraph. */
979 while (cell == para->member.para.pCell) {
980 if (y < para->member.para.pt.y + para->member.para.nHeight)
981 {
982 if (para->member.para.nFlags & MEPF_ROWSTART)
983 return ME_FindPixelPosInTableRow(x, y, para);
984 else
985 return para;
986 }
987 para = para->member.para.next_para;
988 }
989 /* Past the end of the cell, so go back to the last cell paragraph */
990 return para->member.para.prev_para;
991 }
992 cell = next_cell;
993 }
994 /* Return table row delimiter */
995 para = ME_FindItemFwd(cell, diParagraph);
999 return para;
1000}
1001
1003 int x, ME_Cursor *cursor, BOOL *pbCaretAtEnd)
1004{
1005 ME_DisplayItem *pNext, *pLastRun;
1006 ME_Row *row = &pRow->member.row;
1007 BOOL exact = TRUE;
1008
1009 if (x < row->pt.x)
1010 {
1011 x = row->pt.x;
1012 exact = FALSE;
1013 }
1014 pNext = ME_FindItemFwd(pRow, diRunOrStartRow);
1015 assert(pNext->type == diRun);
1016 if (pbCaretAtEnd) *pbCaretAtEnd = FALSE;
1017 cursor->nOffset = 0;
1018 do {
1019 int run_x = pNext->member.run.pt.x;
1020 int width = pNext->member.run.nWidth;
1021
1022 if (x >= run_x && x < run_x+width)
1023 {
1024 cursor->nOffset = ME_CharFromPoint(editor, x-run_x, &pNext->member.run, TRUE, TRUE);
1025 cursor->pRun = pNext;
1026 cursor->pPara = ME_GetParagraph( cursor->pRun );
1027 return exact;
1028 }
1029 pLastRun = pNext;
1030 pNext = ME_FindItemFwd(pNext, diRunOrStartRow);
1031 } while(pNext && pNext->type == diRun);
1032
1033 if ((pLastRun->member.run.nFlags & MERF_ENDPARA) == 0)
1034 {
1035 cursor->pRun = ME_FindItemFwd(pNext, diRun);
1036 if (pbCaretAtEnd) *pbCaretAtEnd = TRUE;
1037 }
1038 else
1039 cursor->pRun = pLastRun;
1040
1041 cursor->pPara = ME_GetParagraph( cursor->pRun );
1042 return FALSE;
1043}
1044
1045/* Finds the run and offset from the pixel position.
1046 *
1047 * x & y are pixel positions in virtual coordinates into the rich edit control,
1048 * so client coordinates must first be adjusted by the scroll position.
1049 *
1050 * If final_eop is TRUE consider the final end-of-paragraph.
1051 *
1052 * returns TRUE if the result was exactly under the cursor, otherwise returns
1053 * FALSE, and result is set to the closest position to the coordinates.
1054 */
1055static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
1056 ME_Cursor *result, BOOL *is_eol, BOOL final_eop)
1057{
1059 BOOL isExact = TRUE;
1060
1061 x -= editor->rcFormat.left;
1062 y -= editor->rcFormat.top;
1063
1064 if (is_eol)
1065 *is_eol = FALSE;
1066
1067 /* find paragraph */
1068 for (; p != editor->pBuffer->pLast; p = p->member.para.next_para)
1069 {
1070 assert(p->type == diParagraph);
1071 if (y < p->member.para.pt.y + p->member.para.nHeight)
1072 {
1073 if (p->member.para.nFlags & MEPF_ROWSTART)
1075 y -= p->member.para.pt.y;
1077 break;
1078 } else if (p->member.para.nFlags & MEPF_ROWSTART) {
1080 }
1081 }
1082 /* find row */
1083 for (; p != editor->pBuffer->pLast; )
1084 {
1085 ME_DisplayItem *pp;
1086 assert(p->type == diStartRow);
1087 if (y < p->member.row.pt.y + p->member.row.nHeight) break;
1089 if (!pp) break;
1090 p = pp;
1091 }
1092 if (p == editor->pBuffer->pLast && !final_eop)
1093 {
1094 /* The position is below the last paragraph, so the last row will be used
1095 * rather than the end of the text, so the x position will be used to
1096 * determine the offset closest to the pixel position. */
1097 isExact = FALSE;
1099 if (!p) p = editor->pBuffer->pLast;
1100 }
1101
1102 assert( p->type == diStartRow || p == editor->pBuffer->pLast );
1103
1104 if( p->type == diStartRow )
1105 return ME_FindRunInRow( editor, p, x, result, is_eol ) && isExact;
1106
1107 ME_SetCursorToEnd(editor, result, TRUE);
1108 return FALSE;
1109}
1110
1111
1112/* Sets the cursor to the position closest to the pixel position
1113 *
1114 * x & y are pixel positions in client coordinates.
1115 *
1116 * isExact will be set to TRUE if the run is directly under the pixel
1117 * position, FALSE if it not, unless isExact is set to NULL.
1118 *
1119 * return FALSE if outside client area and the cursor is not set,
1120 * otherwise TRUE is returned.
1121 */
1123 ME_Cursor *cursor, BOOL *isExact)
1124{
1125 RECT rc;
1126 BOOL bResult;
1127
1128 ITextHost_TxGetClientRect(editor->texthost, &rc);
1129 if (x < 0 || y < 0 || x >= rc.right || y >= rc.bottom) {
1130 if (isExact) *isExact = FALSE;
1131 return FALSE;
1132 }
1133 x += editor->horz_si.nPos;
1134 y += editor->vert_si.nPos;
1135 bResult = ME_FindPixelPos(editor, x, y, cursor, NULL, FALSE);
1136 if (isExact) *isExact = bResult;
1137 return TRUE;
1138}
1139
1140
1141
1142/* Extends the selection with a word, line, or paragraph selection type.
1143 *
1144 * The selection is anchored by editor->pCursors[2-3] such that the text
1145 * between the anchors will remain selected, and one end will be extended.
1146 *
1147 * editor->pCursors[0] should have the position to extend the selection to
1148 * before this function is called.
1149 *
1150 * Nothing will be done if editor->nSelectionType equals stPosition.
1151 */
1153{
1154 ME_Cursor tmp_cursor;
1155 int curOfs, anchorStartOfs, anchorEndOfs;
1156 if (editor->nSelectionType == stPosition || editor->nSelectionType == stDocument)
1157 return;
1158 curOfs = ME_GetCursorOfs(&editor->pCursors[0]);
1159 anchorStartOfs = ME_GetCursorOfs(&editor->pCursors[3]);
1160 anchorEndOfs = ME_GetCursorOfs(&editor->pCursors[2]);
1161
1162 tmp_cursor = editor->pCursors[0];
1163 editor->pCursors[0] = editor->pCursors[2];
1164 editor->pCursors[1] = editor->pCursors[3];
1165 if (curOfs < anchorStartOfs)
1166 {
1167 /* Extend the left side of selection */
1168 editor->pCursors[1] = tmp_cursor;
1169 if (editor->nSelectionType == stWord)
1170 ME_MoveCursorWords(editor, &editor->pCursors[1], -1);
1171 else
1172 {
1173 ME_DisplayItem *pItem;
1174 ME_DIType searchType = ((editor->nSelectionType == stLine) ?
1176 pItem = ME_FindItemBack(editor->pCursors[1].pRun, searchType);
1177 editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun);
1178 editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun);
1179 editor->pCursors[1].nOffset = 0;
1180 }
1181 }
1182 else if (curOfs >= anchorEndOfs)
1183 {
1184 /* Extend the right side of selection */
1185 editor->pCursors[0] = tmp_cursor;
1186 if (editor->nSelectionType == stWord)
1187 ME_MoveCursorWords(editor, &editor->pCursors[0], +1);
1188 else
1189 {
1190 ME_DisplayItem *pItem;
1191 ME_DIType searchType = ((editor->nSelectionType == stLine) ?
1193 pItem = ME_FindItemFwd(editor->pCursors[0].pRun, searchType);
1194 if (pItem->type == diTextEnd)
1195 editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun);
1196 else
1197 editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun);
1198 editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun);
1199 editor->pCursors[0].nOffset = 0;
1200 }
1201 }
1202}
1203
1204void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
1205{
1206 ME_Cursor tmp_cursor;
1207 BOOL is_selection = FALSE, is_shift;
1208
1209 editor->nUDArrowX = -1;
1210
1211 x += editor->horz_si.nPos;
1212 y += editor->vert_si.nPos;
1213
1214 tmp_cursor = editor->pCursors[0];
1215 is_selection = ME_IsSelection(editor);
1216 is_shift = GetKeyState(VK_SHIFT) < 0;
1217
1218 ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd, FALSE);
1219
1220 if (x >= editor->rcFormat.left || is_shift)
1221 {
1222 if (clickNum > 1)
1223 {
1224 editor->pCursors[1] = editor->pCursors[0];
1225 if (is_shift) {
1226 if (x >= editor->rcFormat.left)
1227 ME_SelectByType(editor, stWord);
1228 else
1230 } else if (clickNum % 2 == 0) {
1231 ME_SelectByType(editor, stWord);
1232 } else {
1234 }
1235 }
1236 else if (!is_shift)
1237 {
1238 editor->nSelectionType = stPosition;
1239 editor->pCursors[1] = editor->pCursors[0];
1240 }
1241 else if (!is_selection)
1242 {
1243 editor->nSelectionType = stPosition;
1244 editor->pCursors[1] = tmp_cursor;
1245 }
1246 else if (editor->nSelectionType != stPosition)
1247 {
1249 }
1250 }
1251 else
1252 {
1253 if (clickNum < 2) {
1254 ME_SelectByType(editor, stLine);
1255 } else if (clickNum % 2 == 0 || is_shift) {
1257 } else {
1258 ME_SelectByType(editor, stDocument);
1259 }
1260 }
1261 ME_InvalidateSelection(editor);
1262 update_caret(editor);
1263 ME_SendSelChange(editor);
1264}
1265
1266void ME_MouseMove(ME_TextEditor *editor, int x, int y)
1267{
1268 ME_Cursor tmp_cursor;
1269
1270 if (editor->nSelectionType == stDocument)
1271 return;
1272 x += editor->horz_si.nPos;
1273 y += editor->vert_si.nPos;
1274
1275 tmp_cursor = editor->pCursors[0];
1276 /* FIXME: do something with the return value of ME_FindPixelPos */
1277 ME_FindPixelPos(editor, x, y, &tmp_cursor, &editor->bCaretAtEnd, TRUE);
1278
1279 ME_InvalidateSelection(editor);
1280 editor->pCursors[0] = tmp_cursor;
1282
1283 if (editor->nSelectionType != stPosition &&
1284 memcmp(&editor->pCursors[1], &editor->pCursors[3], sizeof(ME_Cursor)))
1285 {
1286 /* The scroll the cursor towards the other end, since it was the one
1287 * extended by ME_ExtendAnchorSelection */
1288 ME_EnsureVisible(editor, &editor->pCursors[1]);
1289 } else {
1290 ME_EnsureVisible(editor, &editor->pCursors[0]);
1291 }
1292
1293 ME_InvalidateSelection(editor);
1294 update_caret(editor);
1295 ME_SendSelChange(editor);
1296}
1297
1298static int ME_GetXForArrow(ME_TextEditor *editor, ME_Cursor *pCursor)
1299{
1300 ME_DisplayItem *pRun = pCursor->pRun;
1301 int x;
1302
1303 if (editor->nUDArrowX != -1)
1304 x = editor->nUDArrowX;
1305 else {
1306 if (editor->bCaretAtEnd)
1307 {
1308 pRun = ME_FindItemBack(pRun, diRun);
1309 assert(pRun);
1310 x = pRun->member.run.pt.x + pRun->member.run.nWidth;
1311 }
1312 else {
1313 x = pRun->member.run.pt.x;
1314 x += ME_PointFromChar(editor, &pRun->member.run, pCursor->nOffset, TRUE);
1315 }
1316 editor->nUDArrowX = x;
1317 }
1318 return x;
1319}
1320
1321
1322static void
1323ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs, BOOL extend)
1324{
1325 ME_DisplayItem *pRun = pCursor->pRun;
1326 ME_DisplayItem *pOldPara = pCursor->pPara;
1327 ME_DisplayItem *pItem, *pNewPara;
1328 int x = ME_GetXForArrow(editor, pCursor);
1329
1330 if (editor->bCaretAtEnd && !pCursor->nOffset)
1331 if (!ME_PrevRun(&pOldPara, &pRun, TRUE))
1332 return;
1333
1334 if (nRelOfs == -1)
1335 {
1336 /* start of this row */
1337 pItem = ME_FindItemBack(pRun, diStartRow);
1338 assert(pItem);
1339 /* start of the previous row */
1340 pItem = ME_FindItemBack(pItem, diStartRow);
1341 if (!pItem) /* row not found */
1342 {
1343 if (extend)
1344 ME_SetCursorToStart(editor, pCursor);
1345 return;
1346 }
1347 pNewPara = ME_GetParagraph(pItem);
1348 if (pOldPara->member.para.nFlags & MEPF_ROWEND ||
1349 (pOldPara->member.para.pCell &&
1350 pOldPara->member.para.pCell != pNewPara->member.para.pCell))
1351 {
1352 /* Brought out of a cell */
1353 pNewPara = ME_GetTableRowStart(pOldPara)->member.para.prev_para;
1354 if (pNewPara->type == diTextStart)
1355 return; /* At the top, so don't go anywhere. */
1356 pItem = ME_FindItemFwd(pNewPara, diStartRow);
1357 }
1358 if (pNewPara->member.para.nFlags & MEPF_ROWEND)
1359 {
1360 /* Brought into a table row */
1361 ME_Cell *cell = &ME_FindItemBack(pNewPara, diCell)->member.cell;
1362 while (x < cell->pt.x && cell->prev_cell)
1363 cell = &cell->prev_cell->member.cell;
1364 if (cell->next_cell) /* else - we are still at the end of the row */
1365 pItem = ME_FindItemBack(cell->next_cell, diStartRow);
1366 }
1367 }
1368 else
1369 {
1370 /* start of the next row */
1371 pItem = ME_FindItemFwd(pRun, diStartRow);
1372 if (!pItem) /* row not found */
1373 {
1374 if (extend)
1375 ME_SetCursorToEnd(editor, pCursor, TRUE);
1376 return;
1377 }
1378 pNewPara = ME_GetParagraph(pItem);
1379 if (pOldPara->member.para.nFlags & MEPF_ROWSTART ||
1380 (pOldPara->member.para.pCell &&
1381 pOldPara->member.para.pCell != pNewPara->member.para.pCell))
1382 {
1383 /* Brought out of a cell */
1384 pNewPara = ME_GetTableRowEnd(pOldPara)->member.para.next_para;
1385 if (pNewPara->type == diTextEnd)
1386 return; /* At the bottom, so don't go anywhere. */
1387 pItem = ME_FindItemFwd(pNewPara, diStartRow);
1388 }
1389 if (pNewPara->member.para.nFlags & MEPF_ROWSTART)
1390 {
1391 /* Brought into a table row */
1392 ME_DisplayItem *cell = ME_FindItemFwd(pNewPara, diCell);
1393 while (cell->member.cell.next_cell &&
1394 x >= cell->member.cell.next_cell->member.cell.pt.x)
1395 cell = cell->member.cell.next_cell;
1396 pItem = ME_FindItemFwd(cell, diStartRow);
1397 }
1398 }
1399 if (!pItem)
1400 {
1401 /* row not found - ignore */
1402 return;
1403 }
1404 ME_FindRunInRow(editor, pItem, x, pCursor, &editor->bCaretAtEnd);
1405 assert(pCursor->pRun);
1406 assert(pCursor->pRun->type == diRun);
1407}
1408
1409static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
1410{
1412
1413 if (editor->vert_si.nPos < p->member.row.nHeight)
1414 {
1415 ME_SetCursorToStart(editor, pCursor);
1416 editor->bCaretAtEnd = FALSE;
1417 /* Native clears seems to clear this x value on page up at the top
1418 * of the text, but not on page down at the end of the text.
1419 * Doesn't make sense, but we try to be bug for bug compatible. */
1420 editor->nUDArrowX = -1;
1421 } else {
1422 ME_DisplayItem *pRun = pCursor->pRun;
1423 ME_DisplayItem *pLast;
1424 int x, y, yd, yp;
1425 int yOldScrollPos = editor->vert_si.nPos;
1426
1427 x = ME_GetXForArrow(editor, pCursor);
1428 if (!pCursor->nOffset && editor->bCaretAtEnd)
1429 pRun = ME_FindItemBack(pRun, diRun);
1430
1432 assert(p->type == diStartRow);
1434 y = yp + p->member.row.pt.y;
1435
1436 ME_ScrollUp(editor, editor->sizeWindow.cy);
1437 /* Only move the cursor by the amount scrolled. */
1438 yd = y + editor->vert_si.nPos - yOldScrollPos;
1439 pLast = p;
1440
1441 do {
1443 if (!p)
1444 break;
1445 if (p->type == diParagraph) { /* crossing paragraphs */
1446 if (p->member.para.prev_para == NULL)
1447 break;
1448 yp = p->member.para.prev_para->member.para.pt.y;
1449 continue;
1450 }
1451 y = yp + p->member.row.pt.y;
1452 if (y < yd)
1453 break;
1454 pLast = p;
1455 } while(1);
1456
1457 ME_FindRunInRow(editor, pLast, x, pCursor, &editor->bCaretAtEnd);
1458 }
1459 assert(pCursor->pRun);
1460 assert(pCursor->pRun->type == diRun);
1461}
1462
1463static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
1464{
1465 ME_DisplayItem *pLast;
1466 int x, y;
1467
1468 /* Find y position of the last row */
1469 pLast = editor->pBuffer->pLast;
1470 y = pLast->member.para.prev_para->member.para.pt.y
1472
1473 x = ME_GetXForArrow(editor, pCursor);
1474
1475 if (editor->vert_si.nPos >= y - editor->sizeWindow.cy)
1476 {
1477 ME_SetCursorToEnd(editor, pCursor, FALSE);
1478 editor->bCaretAtEnd = FALSE;
1479 } else {
1480 ME_DisplayItem *pRun = pCursor->pRun;
1482 int yd, yp;
1483 int yOldScrollPos = editor->vert_si.nPos;
1484
1485 if (!pCursor->nOffset && editor->bCaretAtEnd)
1486 pRun = ME_FindItemBack(pRun, diRun);
1487
1489 assert(p->type == diStartRow);
1491 y = yp + p->member.row.pt.y;
1492
1493 /* For native richedit controls:
1494 * v1.0 - v3.1 can only scroll down as far as the scrollbar lets us
1495 * v4.1 can scroll past this position here. */
1496 ME_ScrollDown(editor, editor->sizeWindow.cy);
1497 /* Only move the cursor by the amount scrolled. */
1498 yd = y + editor->vert_si.nPos - yOldScrollPos;
1499 pLast = p;
1500
1501 do {
1503 if (!p)
1504 break;
1505 if (p->type == diParagraph) {
1506 yp = p->member.para.pt.y;
1507 continue;
1508 }
1509 y = yp + p->member.row.pt.y;
1510 if (y >= yd)
1511 break;
1512 pLast = p;
1513 } while(1);
1514
1515 ME_FindRunInRow(editor, pLast, x, pCursor, &editor->bCaretAtEnd);
1516 }
1517 assert(pCursor->pRun);
1518 assert(pCursor->pRun->type == diRun);
1519}
1520
1521static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
1522{
1523 ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow);
1524 if (pRow) {
1525 ME_DisplayItem *pRun;
1526 if (editor->bCaretAtEnd && !pCursor->nOffset) {
1527 pRow = ME_FindItemBack(pRow, diStartRow);
1528 if (!pRow)
1529 return;
1530 }
1531 pRun = ME_FindItemFwd(pRow, diRun);
1532 if (pRun) {
1533 pCursor->pRun = pRun;
1534 assert(pCursor->pPara == ME_GetParagraph(pRun));
1535 pCursor->nOffset = 0;
1536 }
1537 }
1538 editor->bCaretAtEnd = FALSE;
1539}
1540
1541static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor)
1542{
1543 ME_SetCursorToStart(editor, pCursor);
1544 editor->bCaretAtEnd = FALSE;
1545}
1546
1547static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
1548{
1549 ME_DisplayItem *pRow;
1550
1551 if (editor->bCaretAtEnd && !pCursor->nOffset)
1552 return;
1553
1555 assert(pRow);
1556 if (pRow->type == diStartRow) {
1557 ME_DisplayItem *pRun = ME_FindItemFwd(pRow, diRun);
1558 assert(pRun);
1559 pCursor->pRun = pRun;
1560 assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun));
1561 pCursor->nOffset = 0;
1562 editor->bCaretAtEnd = TRUE;
1563 return;
1564 }
1565 pCursor->pRun = ME_FindItemBack(pRow, diRun);
1566 assert(pCursor->pRun && pCursor->pRun->member.run.nFlags & MERF_ENDPARA);
1567 assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun));
1568 pCursor->nOffset = 0;
1569 editor->bCaretAtEnd = FALSE;
1570}
1571
1572static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
1573{
1574 ME_SetCursorToEnd(editor, pCursor, FALSE);
1575 editor->bCaretAtEnd = FALSE;
1576}
1577
1579{
1580 return editor->pCursors[0].pRun != editor->pCursors[1].pRun ||
1581 editor->pCursors[0].nOffset != editor->pCursors[1].nOffset;
1582}
1583
1585{
1586 int from, to;
1587 int nStartCursor = ME_GetSelectionOfs(editor, &from, &to);
1588 int nEndCursor = nStartCursor ^ 1;
1589 ME_DeleteTextAtCursor(editor, nStartCursor, to - from);
1590 editor->pCursors[nEndCursor] = editor->pCursors[nStartCursor];
1591}
1592
1594{
1595 return ME_GetInsertStyle(editor, 0);
1596}
1597
1599{
1600 SELCHANGE sc;
1601
1602 sc.nmhdr.hwndFrom = NULL;
1603 sc.nmhdr.idFrom = 0;
1604 sc.nmhdr.code = EN_SELCHANGE;
1605 ME_GetSelectionOfs(editor, &sc.chrg.cpMin, &sc.chrg.cpMax);
1606 sc.seltyp = SEL_EMPTY;
1607 if (sc.chrg.cpMin != sc.chrg.cpMax)
1608 sc.seltyp |= SEL_TEXT;
1609 if (sc.chrg.cpMin < sc.chrg.cpMax+1) /* what were RICHEDIT authors thinking ? */
1610 sc.seltyp |= SEL_MULTICHAR;
1611
1612 if (sc.chrg.cpMin != editor->notified_cr.cpMin || sc.chrg.cpMax != editor->notified_cr.cpMax)
1613 {
1614 ME_ClearTempStyle(editor);
1615
1616 editor->notified_cr = sc.chrg;
1617
1618 if (editor->nEventMask & ENM_SELCHANGE)
1619 {
1620 TRACE("cpMin=%d cpMax=%d seltyp=%d (%s %s)\n",
1621 sc.chrg.cpMin, sc.chrg.cpMax, sc.seltyp,
1622 (sc.seltyp & SEL_TEXT) ? "SEL_TEXT" : "",
1623 (sc.seltyp & SEL_MULTICHAR) ? "SEL_MULTICHAR" : "");
1624 ITextHost_TxNotify(editor->texthost, sc.nmhdr.code, &sc);
1625 }
1626 }
1627}
1628
1629BOOL
1630ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
1631{
1632 int nCursor = 0;
1633 ME_Cursor *p = &editor->pCursors[nCursor];
1634 ME_Cursor tmp_curs = *p;
1635 BOOL success = FALSE;
1636
1637 ME_CheckCharOffsets(editor);
1638 switch(nVKey) {
1639 case VK_LEFT:
1640 editor->bCaretAtEnd = FALSE;
1641 if (ctrl)
1642 success = ME_MoveCursorWords(editor, &tmp_curs, -1);
1643 else
1644 success = ME_MoveCursorChars(editor, &tmp_curs, -1, extend);
1645 break;
1646 case VK_RIGHT:
1647 editor->bCaretAtEnd = FALSE;
1648 if (ctrl)
1649 success = ME_MoveCursorWords(editor, &tmp_curs, +1);
1650 else
1651 success = ME_MoveCursorChars(editor, &tmp_curs, +1, extend);
1652 break;
1653 case VK_UP:
1654 ME_MoveCursorLines(editor, &tmp_curs, -1, extend);
1655 break;
1656 case VK_DOWN:
1657 ME_MoveCursorLines(editor, &tmp_curs, +1, extend);
1658 break;
1659 case VK_PRIOR:
1660 ME_ArrowPageUp(editor, &tmp_curs);
1661 break;
1662 case VK_NEXT:
1663 ME_ArrowPageDown(editor, &tmp_curs);
1664 break;
1665 case VK_HOME: {
1666 if (ctrl)
1667 ME_ArrowCtrlHome(editor, &tmp_curs);
1668 else
1669 ME_ArrowHome(editor, &tmp_curs);
1670 editor->bCaretAtEnd = FALSE;
1671 break;
1672 }
1673 case VK_END:
1674 if (ctrl)
1675 ME_ArrowCtrlEnd(editor, &tmp_curs);
1676 else
1677 ME_ArrowEnd(editor, &tmp_curs);
1678 break;
1679 }
1680
1681 if (!extend)
1682 editor->pCursors[1] = tmp_curs;
1683 *p = tmp_curs;
1684
1685 ME_InvalidateSelection(editor);
1686 ME_Repaint(editor);
1687 hide_caret(editor);
1688 ME_EnsureVisible(editor, &tmp_curs);
1689 update_caret(editor);
1690 ME_SendSelChange(editor);
1691 return success;
1692}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
Arabic default style
Definition: afstyles.h:94
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:20
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define E_INVALIDARG
Definition: ddrawi.h:101
DWORD HIMC
Definition: dimm.idl:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
Definition: ime.c:1744
BOOL WINAPI ImmIsIME(HKL hKL)
Definition: ime.c:880
BOOL WINAPI ImmSetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
Definition: ime.c:1583
HIMC WINAPI ImmGetContext(HWND hWnd)
Definition: imm.c:1045
BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
Definition: imm.c:1086
BOOL WINAPI GetCPInfo(UINT codepage, LPCPINFO cpinfo)
Definition: locale.c:2144
void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor)
Definition: caret.c:580
void ME_SetCursorToStart(ME_TextEditor *editor, ME_Cursor *cursor)
Definition: caret.c:27
BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars)
Definition: caret.c:510
BOOL ME_IsSelection(ME_TextEditor *editor)
Definition: caret.c:1578
void ME_DeleteSelection(ME_TextEditor *editor)
Definition: caret.c:1584
static int ME_GetXForArrow(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1298
static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1521
static void ME_ExtendAnchorSelection(ME_TextEditor *editor)
Definition: caret.c:1152
int ME_GetCursorOfs(const ME_Cursor *cursor)
Definition: caret.c:957
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, const WCHAR *str, int len, ME_Style *style)
Definition: caret.c:595
int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BOOL final_eop)
Definition: caret.c:720
BOOL ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
Definition: caret.c:799
void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT *reo, int nCursor)
Definition: caret.c:546
void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
Definition: caret.c:1204
int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how)
Definition: caret.c:91
static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1409
static void ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs, BOOL extend)
Definition: caret.c:1323
int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to)
Definition: caret.c:57
BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nChars, BOOL bForce)
Definition: caret.c:360
static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *result, BOOL *is_eol, BOOL final_eop)
Definition: caret.c:1055
void hide_caret(ME_TextEditor *editor)
Definition: caret.c:288
static void ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType)
Definition: caret.c:899
static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1572
void ME_MouseMove(ME_TextEditor *editor, int x, int y)
Definition: caret.c:1266
BOOL ME_CharFromPos(ME_TextEditor *editor, int x, int y, ME_Cursor *cursor, BOOL *isExact)
Definition: caret.c:1122
static ME_DisplayItem * ME_FindPixelPosInTableRow(int x, int y, ME_DisplayItem *para)
Definition: caret.c:964
void ME_SendSelChange(ME_TextEditor *editor)
Definition: caret.c:1598
int set_selection_cursors(ME_TextEditor *editor, int from, int to)
Definition: caret.c:132
int ME_GetSelectionOfs(ME_TextEditor *editor, int *from, int *to)
Definition: caret.c:42
BOOL ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
Definition: caret.c:1630
static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1463
static void ME_SetCursorToEnd(ME_TextEditor *editor, ME_Cursor *cursor, BOOL final_eop)
Definition: caret.c:34
void create_caret(ME_TextEditor *editor)
Definition: caret.c:272
static BOOL ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow, int x, ME_Cursor *cursor, BOOL *pbCaretAtEnd)
Definition: caret.c:1002
int ME_GetTextLength(ME_TextEditor *editor)
Definition: caret.c:83
void ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, int *x, int *y, int *height)
Definition: caret.c:221
void show_caret(ME_TextEditor *editor)
Definition: caret.c:282
static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1547
static ME_DisplayItem * ME_InternalInsertTextFromCursor(ME_TextEditor *editor, int nCursor, const WCHAR *str, int len, ME_Style *style, int flags)
Definition: caret.c:520
void update_caret(ME_TextEditor *editor)
Definition: caret.c:298
static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1541
ME_Style * ME_GetSelectionInsertStyle(ME_TextEditor *editor)
Definition: caret.c:1593
static struct re_object * create_re_object(const REOBJECT *reo)
Definition: caret.c:533
void ME_DestroyContext(ME_Context *c)
Definition: context.c:44
void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC)
Definition: context.c:23
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
#define assert(x)
Definition: debug.h:53
#define pt(x, y)
Definition: drawing.c:79
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
void ME_ReleaseStyle(ME_Style *item) DECLSPEC_HIDDEN
Definition: style.c:462
ME_Style * ME_GetInsertStyle(ME_TextEditor *editor, int nCursor) DECLSPEC_HIDDEN
Definition: style.c:476
int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN
Definition: run.c:557
BOOL add_undo_insert_run(ME_TextEditor *, int pos, const WCHAR *str, int len, int flags, ME_Style *style) DECLSPEC_HIDDEN
Definition: undo.c:131
ME_DisplayItem * ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, const WCHAR *str, int len, int flags) DECLSPEC_HIDDEN
Definition: run.c:325
void mark_para_rewrap(ME_TextEditor *editor, ME_DisplayItem *para) DECLSPEC_HIDDEN
Definition: para.c:26
void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor) DECLSPEC_HIDDEN
Definition: run.c:171
void ME_CheckCharOffsets(ME_TextEditor *editor) DECLSPEC_HIDDEN
Definition: run.c:101
#define ITextHost_TxCreateCaret(This, a, b, c)
Definition: editor.h:295
void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN
Definition: list.c:160
ME_DisplayItem * ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN
Definition: list.c:111
void ME_PropagateCharOffset(ME_DisplayItem *p, int shift) DECLSPEC_HIDDEN
Definition: run.c:59
void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nChars) DECLSPEC_HIDDEN
Definition: table.c:287
ME_DisplayItem * ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN
Definition: run.c:258
#define ITextHost_TxNotify(This, a, b)
Definition: editor.h:322
#define ITextHost_TxSetCaretPos(This, a, b)
Definition: editor.h:297
void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor) DECLSPEC_HIDDEN
Definition: paint.c:1275
ME_DisplayItem * ME_GetParagraph(ME_DisplayItem *run) DECLSPEC_HIDDEN
Definition: para.c:815
void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN
Definition: para.c:992
int ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start, INT code) DECLSPEC_HIDDEN
Definition: string.c:204
ME_DisplayItem * ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, BOOL keepFirstParaFormat) DECLSPEC_HIDDEN
Definition: para.c:687
#define ITextHost_TxGetClientRect(This, a)
Definition: editor.h:308
#define ITextHost_TxGetDC(This)
Definition: editor.h:287
void ME_ScrollUp(ME_TextEditor *editor, int cy) DECLSPEC_HIDDEN
Definition: paint.c:1116
void ME_InvalidateSelection(ME_TextEditor *editor) DECLSPEC_HIDDEN
Definition: paint.c:1322
ME_DisplayItem * ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, const WCHAR *eol_str, int eol_len, int paraFlags) DECLSPEC_HIDDEN
Definition: para.c:545
void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN
Definition: run.c:801
void ME_CopyReObject(REOBJECT *dst, const REOBJECT *src, DWORD flags) DECLSPEC_HIDDEN
Definition: richole.c:5907
void ME_Remove(ME_DisplayItem *diWhere) DECLSPEC_HIDDEN
Definition: list.c:35
void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift) DECLSPEC_HIDDEN
Definition: run.c:46
ME_DisplayItem * ME_GetTableRowStart(ME_DisplayItem *para) DECLSPEC_HIDDEN
Definition: table.c:154
void ME_ClearTempStyle(ME_TextEditor *editor) DECLSPEC_HIDDEN
Definition: style.c:523
void ME_StrDeleteV(ME_String *s, int nVChar, int nChars) DECLSPEC_HIDDEN
Definition: string.c:147
void ME_Repaint(ME_TextEditor *editor) DECLSPEC_HIDDEN
Definition: paint.c:106
static WCHAR * get_text(const ME_Run *run, int offset)
Definition: editor.h:41
void ME_ScrollDown(ME_TextEditor *editor, int cy) DECLSPEC_HIDDEN
Definition: paint.c:1121
ME_DisplayItem * ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN
Definition: list.c:134
int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN
Definition: run.c:598
#define ITextHost_TxShowCaret(This, a)
Definition: editor.h:296
BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para) DECLSPEC_HIDDEN
Definition: list.c:93
static const char * debugstr_run(const ME_Run *run)
Definition: editor.h:46
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, BOOL visual_order) DECLSPEC_HIDDEN
Definition: run.c:521
ME_DisplayItem * ME_GetTableRowEnd(ME_DisplayItem *para) DECLSPEC_HIDDEN
Definition: table.c:136
#define MERF_TAB
Definition: editstr.h:107
#define MERF_ENDPARA
Definition: editstr.h:122
#define MERF_GRAPHICS
Definition: editstr.h:105
#define MEPF_ROWSTART
Definition: editstr.h:144
#define MEPF_ROWEND
Definition: editstr.h:145
ME_DIType
Definition: editstr.h:82
@ diStartRow
Definition: editstr.h:88
@ diTextEnd
Definition: editstr.h:89
@ diRunOrParagraphOrEnd
Definition: editstr.h:97
@ diCell
Definition: editstr.h:86
@ diParagraphOrEnd
Definition: editstr.h:96
@ diRun
Definition: editstr.h:87
@ diStartRowOrParagraphOrEnd
Definition: editstr.h:93
@ diRunOrParagraph
Definition: editstr.h:94
@ diTextStart
Definition: editstr.h:84
@ diRunOrStartRow
Definition: editstr.h:95
@ diStartRowOrParagraph
Definition: editstr.h:92
@ diParagraph
Definition: editstr.h:85
#define MEPF_REWRAP
Definition: editstr.h:141
ME_SelectionType
Definition: editstr.h:356
@ stWord
Definition: editstr.h:358
@ stParagraph
Definition: editstr.h:360
@ stPosition
Definition: editstr.h:357
@ stLine
Definition: editstr.h:359
@ stDocument
Definition: editstr.h:361
#define MERF_ENDROW
Definition: editstr.h:124
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
const GLubyte * c
Definition: glext.h:8905
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const char cursor[]
Definition: icontest.c:13
#define CFS_RECT
Definition: imm.h:324
#define CFS_POINT
Definition: imm.h:325
static __inline int is_eol(struct parser *parser, const CHAR *ptr)
Definition: inffile.c:422
#define c
Definition: ke_i.h:80
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:88
#define shift
Definition: input.c:1755
#define ctrl
Definition: input.c:1756
#define min(a, b)
Definition: monoChain.cc:55
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
#define ES_MULTILINE
Definition: pedump.c:667
#define swap(a, b)
Definition: qsort.c:63
#define WB_MOVEWORDRIGHT
Definition: richedit.h:1002
#define SEL_EMPTY
Definition: richedit.h:822
#define GTL_CLOSE
Definition: richedit.h:1057
#define SEL_MULTICHAR
Definition: richedit.h:825
#define EN_SELCHANGE
Definition: richedit.h:193
#define GTL_NUMCHARS
Definition: richedit.h:1058
#define SEL_TEXT
Definition: richedit.h:823
#define ENM_SELCHANGE
Definition: richedit.h:478
#define CFM_CHARSET
Definition: richedit.h:358
#define CFM_SIZE
Definition: richedit.h:362
#define GTL_PRECISE
Definition: richedit.h:1056
#define PFM_TABLEROWDELIMITER
Definition: richedit.h:868
#define CFM_FACE
Definition: richedit.h:360
#define GTL_NUMBYTES
Definition: richedit.h:1059
#define WB_MOVEWORDLEFT
Definition: richedit.h:1000
#define PFE_TABLEROWDELIMITER
Definition: richedit.h:942
#define GTL_USECRLF
Definition: richedit.h:1055
const WCHAR * str
__WINE_SERVER_LIST_INLINE void list_add_after(struct list *elem, struct list *to_add)
Definition: list.h:78
#define TRACE(s)
Definition: solgame.cpp:4
CardRegion * from
Definition: spigame.cpp:19
RECT rcArea
Definition: dimm.idl:88
DWORD dwStyle
Definition: dimm.idl:86
POINT ptCurrentPos
Definition: dimm.idl:87
LONG lfHeight
Definition: dimm.idl:59
WCHAR lfFaceName[LF_FACESIZE]
Definition: dimm.idl:72
BYTE lfCharSet
Definition: dimm.idl:67
LONG cy
Definition: kdterminal.h:28
LONG cpMax
Definition: richedit.h:501
LONG cpMin
Definition: richedit.h:500
UINT MaxCharSize
Definition: winnls.h:583
DWORD dwMask
Definition: richedit.h:667
WORD wEffects
Definition: richedit.h:669
NMHDR nmhdr
Definition: richedit.h:685
WORD seltyp
Definition: richedit.h:687
CHARRANGE chrg
Definition: richedit.h:686
Definition: dsound.c:943
struct list entry
Definition: editstr.h:154
REOBJECT obj
Definition: editstr.h:155
struct tagME_DisplayItem * prev_cell
Definition: editstr.h:229
struct tagME_DisplayItem * next_cell
Definition: editstr.h:229
ME_DisplayItem * pPara
Definition: editstr.h:275
int nOffset
Definition: editstr.h:277
ME_DisplayItem * pRun
Definition: editstr.h:276
union tagME_DisplayItem::@535 member
ME_DIType type
Definition: editstr.h:256
ME_Cell cell
Definition: editstr.h:261
ME_Paragraph para
Definition: editstr.h:262
struct tagME_DisplayItem * next_para
Definition: editstr.h:217
struct tagME_DisplayItem * prev_para
Definition: editstr.h:217
PARAFORMAT2 fmt
Definition: editstr.h:204
struct tagME_DisplayItem * pCell
Definition: editstr.h:207
POINT pt
Definition: editstr.h:239
int nAscent
Definition: editstr.h:166
POINT pt
Definition: editstr.h:167
int nCharOfs
Definition: editstr.h:162
int nDescent
Definition: editstr.h:166
struct tagME_Paragraph * para
Definition: editstr.h:161
ME_Style * style
Definition: editstr.h:160
int nWidth
Definition: editstr.h:164
struct re_object * reobj
Definition: editstr.h:168
int nFlags
Definition: editstr.h:165
int len
Definition: editstr.h:163
ME_DisplayItem * pFirst
Definition: editstr.h:268
ME_DisplayItem * pLast
Definition: editstr.h:268
DWORD styleFlags
Definition: editstr.h:388
SCROLLINFO vert_si
Definition: editstr.h:441
ITextHost * texthost
Definition: editstr.h:383
struct list reobj_list
Definition: editstr.h:448
ME_SelectionType nSelectionType
Definition: editstr.h:434
ME_Cursor * pCursors
Definition: editstr.h:387
SCROLLINFO horz_si
Definition: editstr.h:441
ME_TextBuffer * pBuffer
Definition: editstr.h:386
CHARRANGE notified_cr
Definition: editstr.h:438
BOOL bEmulateVersion10
Definition: editstr.h:385
BOOL caret_hidden
Definition: editstr.h:444
BOOL bCaretAtEnd
Definition: editstr.h:399
UINT_PTR idFrom
Definition: winuser.h:3161
UINT code
Definition: winuser.h:3162
HWND hwndFrom
Definition: winuser.h:3160
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
#define success(from, fromstr, to, tostr)
#define ZeroMemory
Definition: winbase.h:1737
int WINAPI GetDeviceCaps(_In_opt_ HDC, _In_ int)
#define LOGPIXELSY
Definition: wingdi.h:719
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define DEFAULT_CHARSET
Definition: wingdi.h:384
BOOL WINAPI DeleteDC(_In_ HDC)
HKL WINAPI GetKeyboardLayout(_In_ DWORD)
#define WB_ISDELIMITER
Definition: winuser.h:549
#define VK_UP
Definition: winuser.h:2228
#define VK_NEXT
Definition: winuser.h:2224
#define VK_END
Definition: winuser.h:2225
#define VK_HOME
Definition: winuser.h:2226
BOOL WINAPI SetRectEmpty(_Out_ LPRECT)
#define VK_LEFT
Definition: winuser.h:2227
#define VK_RIGHT
Definition: winuser.h:2229
#define VK_DOWN
Definition: winuser.h:2230
#define VK_SHIFT
Definition: winuser.h:2205
#define VK_PRIOR
Definition: winuser.h:2223
SHORT WINAPI GetKeyState(_In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180