ReactOS 0.4.15-dev-5863-g1fe3ab7
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}
314
316 int nChars, BOOL bForce)
317{
318 ME_Cursor c = *start;
319 int nOfs = ME_GetCursorOfs(start), text_len = ME_GetTextLength( editor );
320 int shift = 0;
321 int totalChars = nChars;
322 ME_DisplayItem *start_para;
323 BOOL delete_all = FALSE;
324
325 /* Prevent deletion past last end of paragraph run. */
326 nChars = min(nChars, text_len - nOfs);
327 if (nChars == text_len) delete_all = TRUE;
328 start_para = c.pPara;
329
330 if (!bForce)
331 {
332 ME_ProtectPartialTableDeletion(editor, &c, &nChars);
333 if (nChars == 0)
334 return FALSE;
335 }
336
337 while(nChars > 0)
338 {
339 ME_Run *run;
340 ME_CursorFromCharOfs(editor, nOfs+nChars, &c);
341 if (!c.nOffset &&
342 nOfs+nChars == (c.pRun->member.run.nCharOfs
343 + c.pPara->member.para.nCharOfs))
344 {
345 /* We aren't deleting anything in this run, so we will go back to the
346 * last run we are deleting text in. */
347 ME_PrevRun(&c.pPara, &c.pRun, TRUE);
348 c.nOffset = c.pRun->member.run.len;
349 }
350 run = &c.pRun->member.run;
351 if (run->nFlags & MERF_ENDPARA) {
352 int eollen = c.pRun->member.run.len;
353 BOOL keepFirstParaFormat;
354
355 if (!ME_FindItemFwd(c.pRun, diParagraph))
356 {
357 return TRUE;
358 }
359 keepFirstParaFormat = (totalChars == nChars && nChars <= eollen &&
360 run->nCharOfs);
361 if (!editor->bEmulateVersion10) /* v4.1 */
362 {
364 ME_DisplayItem *this_para = next_para->member.para.prev_para;
365
366 /* The end of paragraph before a table row is only deleted if there
367 * is nothing else on the line before it. */
368 if (this_para == start_para &&
369 next_para->member.para.nFlags & MEPF_ROWSTART)
370 {
371 /* If the paragraph will be empty, then it should be deleted, however
372 * it still might have text right now which would inherit the
373 * MEPF_STARTROW property if we joined it right now.
374 * Instead we will delete it after the preceding text is deleted. */
375 if (nOfs > this_para->member.para.nCharOfs) {
376 /* Skip this end of line. */
377 nChars -= (eollen < nChars) ? eollen : nChars;
378 continue;
379 }
380 keepFirstParaFormat = TRUE;
381 }
382 }
383 ME_JoinParagraphs(editor, c.pPara, keepFirstParaFormat);
384 /* ME_SkipAndPropagateCharOffset(p->pRun, shift); */
385 ME_CheckCharOffsets(editor);
386 nChars -= (eollen < nChars) ? eollen : nChars;
387 continue;
388 }
389 else
390 {
392 int nCharsToDelete = min(nChars, c.nOffset);
393 int i;
394
395 c.nOffset -= nCharsToDelete;
396
398
399 cursor = c;
400 /* nChars is the number of characters that should be deleted from the
401 PRECEDING runs (these BEFORE cursor.pRun)
402 nCharsToDelete is a number of chars to delete from THIS run */
403 nChars -= nCharsToDelete;
404 shift -= nCharsToDelete;
405 TRACE("Deleting %d (remaining %d) chars at %d in %s (%d)\n",
406 nCharsToDelete, nChars, c.nOffset,
407 debugstr_run( run ), run->len);
408
409 /* nOfs is a character offset (from the start of the document
410 to the current (deleted) run */
411 add_undo_insert_run( editor, nOfs + nChars, get_text( run, c.nOffset ), nCharsToDelete, run->nFlags, run->style );
412
413 ME_StrDeleteV(run->para->text, run->nCharOfs + c.nOffset, nCharsToDelete);
414 run->len -= nCharsToDelete;
415 TRACE("Post deletion string: %s (%d)\n", debugstr_run( run ), run->len);
416 TRACE("Shift value: %d\n", shift);
417
418 /* update cursors (including c) */
419 for (i=-1; i<editor->nCursors; i++) {
420 ME_Cursor *pThisCur = editor->pCursors + i;
421 if (i == -1) pThisCur = &c;
422 if (pThisCur->pRun == cursor.pRun) {
423 if (pThisCur->nOffset > cursor.nOffset) {
424 if (pThisCur->nOffset-cursor.nOffset < nCharsToDelete)
425 pThisCur->nOffset = cursor.nOffset;
426 else
427 pThisCur->nOffset -= nCharsToDelete;
428 assert(pThisCur->nOffset >= 0);
429 assert(pThisCur->nOffset <= run->len);
430 }
431 if (pThisCur->nOffset == run->len)
432 {
433 pThisCur->pRun = ME_FindItemFwd(pThisCur->pRun, diRunOrParagraphOrEnd);
434 assert(pThisCur->pRun->type == diRun);
435 pThisCur->nOffset = 0;
436 }
437 }
438 }
439
440 /* c = updated data now */
441
442 if (c.pRun == cursor.pRun)
444 else
446
447 if (!cursor.pRun->member.run.len)
448 {
449 TRACE("Removing empty run\n");
450 ME_Remove(cursor.pRun);
452 }
453
454 shift = 0;
455 /*
456 ME_CheckCharOffsets(editor);
457 */
458 continue;
459 }
460 }
461 if (delete_all) ME_SetDefaultParaFormat( editor, &start_para->member.para.fmt );
462 return TRUE;
463}
464
465BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars)
466{
467 assert(nCursor>=0 && nCursor<editor->nCursors);
468 /* text operations set modified state */
469 editor->nModifyStep = 1;
470 return ME_InternalDeleteText(editor, &editor->pCursors[nCursor],
471 nChars, FALSE);
472}
473
474static ME_DisplayItem *
476 const WCHAR *str, int len, ME_Style *style,
477 int flags)
478{
479 ME_Cursor *p = &editor->pCursors[nCursor];
480
481 editor->bCaretAtEnd = FALSE;
482
483 assert(p->pRun->type == diRun);
484
485 return ME_InsertRunAtCursor(editor, p, style, str, len, flags);
486}
487
488static struct re_object* create_re_object(const REOBJECT *reo)
489{
490 struct re_object *reobj = heap_alloc(sizeof(*reobj));
491
492 if (!reobj)
493 {
494 WARN("Fail to allocate re_object.\n");
495 return NULL;
496 }
497 ME_CopyReObject(&reobj->obj, reo, REO_GETOBJ_ALL_INTERFACES);
498 return reobj;
499}
500
501void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor)
502{
503 ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
504 ME_DisplayItem *di;
505 WCHAR space = ' ';
506 ME_DisplayItem *di_prev = NULL;
507 struct re_object *reobj_prev = NULL;
508
509 /* FIXME no no no */
510 if (ME_IsSelection(editor))
511 ME_DeleteSelection(editor);
512
513 di = ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle,
515 di->member.run.reobj = create_re_object(reo);
516
517 di_prev = di;
518 while (ME_PrevRun(NULL, &di_prev, TRUE))
519 {
520 if (di_prev->member.run.reobj)
521 {
522 reobj_prev = di_prev->member.run.reobj;
523 break;
524 }
525 }
526 if (reobj_prev)
527 list_add_after(&reobj_prev->entry, &di->member.run.reobj->entry);
528 else
529 list_add_head(&editor->reobj_list, &di->member.run.reobj->entry);
530
531 ME_ReleaseStyle(pStyle);
532}
533
534
535void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor)
536{
537 ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
538 WCHAR space = ' ';
539
540 /* FIXME no no no */
541 if (ME_IsSelection(editor))
542 ME_DeleteSelection(editor);
543
544 ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle,
546 ME_ReleaseStyle(pStyle);
547}
548
549
550void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
551 const WCHAR *str, int len, ME_Style *style)
552{
553 const WCHAR *pos;
554 ME_Cursor *p = NULL;
555 int oldLen;
556
557 /* FIXME really HERE ? */
558 if (ME_IsSelection(editor))
559 ME_DeleteSelection(editor);
560
561 /* FIXME: is this too slow? */
562 /* Didn't affect performance for WM_SETTEXT (around 50sec/30K) */
563 oldLen = ME_GetTextLength(editor);
564
565 /* text operations set modified state */
566 editor->nModifyStep = 1;
567
568 assert(style);
569
570 assert(nCursor>=0 && nCursor<editor->nCursors);
571 if (len == -1)
572 len = lstrlenW(str);
573
574 /* grow the text limit to fit our text */
575 if(editor->nTextLimit < oldLen +len)
576 editor->nTextLimit = oldLen + len;
577
578 pos = str;
579
580 while (len)
581 {
582 /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
583 while(pos - str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
584 pos++;
585
586 if (pos != str) { /* handle text */
587 ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
588 } else if (*pos == '\t') { /* handle tabs */
589 WCHAR tab = '\t';
590 ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
591 pos++;
592 } else { /* handle EOLs */
593 ME_DisplayItem *tp, *end_run, *run, *prev;
594 int eol_len = 0;
595
596 /* Check if new line is allowed for this control */
597 if (!(editor->styleFlags & ES_MULTILINE))
598 break;
599
600 /* Find number of CR and LF in end of paragraph run */
601 if (*pos =='\r')
602 {
603 if (len > 1 && pos[1] == '\n')
604 eol_len = 2;
605 else if (len > 2 && pos[1] == '\r' && pos[2] == '\n')
606 eol_len = 3;
607 else
608 eol_len = 1;
609 } else {
610 assert(*pos == '\n');
611 eol_len = 1;
612 }
613 pos += eol_len;
614
615 if (!editor->bEmulateVersion10 && eol_len == 3)
616 {
617 /* handle special \r\r\n sequence (richedit 2.x and higher only) */
618 WCHAR space = ' ';
619 ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);
620 } else {
621 const WCHAR cr = '\r', *eol_str = str;
622
623 if (!editor->bEmulateVersion10)
624 {
625 eol_str = &cr;
626 eol_len = 1;
627 }
628
629 p = &editor->pCursors[nCursor];
630
631 if (p->nOffset == p->pRun->member.run.len)
632 {
633 run = ME_FindItemFwd( p->pRun, diRun );
634 if (!run) run = p->pRun;
635 }
636 else
637 {
638 if (p->nOffset) ME_SplitRunSimple(editor, p);
639 run = p->pRun;
640 }
641
642 tp = ME_SplitParagraph(editor, run, style, eol_str, eol_len, 0);
643
644 end_run = ME_FindItemBack(tp, diRun);
645
646 /* Move any cursors that were at the end of the previous run to the beginning of the new para */
647 prev = ME_FindItemBack( end_run, diRun );
648 if (prev)
649 {
650 int i;
651 for (i = 0; i < editor->nCursors; i++)
652 {
653 if (editor->pCursors[i].pRun == prev &&
654 editor->pCursors[i].nOffset == prev->member.run.len)
655 {
656 editor->pCursors[i].pPara = tp;
657 editor->pCursors[i].pRun = run;
658 editor->pCursors[i].nOffset = 0;
659 }
660 }
661 }
662
663 }
664 }
665 len -= pos - str;
666 str = pos;
667 }
668}
669
670/* Move the cursor nRelOfs characters (either forwards or backwards)
671 * If final_eop is TRUE, allow moving the cursor to the end of the final eop.
672 *
673 * returns the actual number of characters moved.
674 **/
675int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BOOL final_eop)
676{
677 cursor->nOffset += nRelOfs;
678 if (cursor->nOffset < 0)
679 {
680 cursor->nOffset += cursor->pRun->member.run.nCharOfs;
681 if (cursor->nOffset >= 0)
682 {
683 /* new offset in the same paragraph */
684 do {
685 cursor->pRun = ME_FindItemBack(cursor->pRun, diRun);
686 } while (cursor->nOffset < cursor->pRun->member.run.nCharOfs);
687 cursor->nOffset -= cursor->pRun->member.run.nCharOfs;
688 return nRelOfs;
689 }
690
691 cursor->nOffset += cursor->pPara->member.para.nCharOfs;
692 if (cursor->nOffset <= 0)
693 {
694 /* moved to the start of the text */
695 nRelOfs -= cursor->nOffset;
697 return nRelOfs;
698 }
699
700 /* new offset in a previous paragraph */
701 do {
702 cursor->pPara = cursor->pPara->member.para.prev_para;
703 } while (cursor->nOffset < cursor->pPara->member.para.nCharOfs);
704 cursor->nOffset -= cursor->pPara->member.para.nCharOfs;
705
706 cursor->pRun = ME_FindItemBack(cursor->pPara->member.para.next_para, diRun);
707 while (cursor->nOffset < cursor->pRun->member.run.nCharOfs) {
708 cursor->pRun = ME_FindItemBack(cursor->pRun, diRun);
709 }
710 cursor->nOffset -= cursor->pRun->member.run.nCharOfs;
711 } else if (cursor->nOffset >= cursor->pRun->member.run.len) {
712 ME_DisplayItem *next_para;
713 int new_offset;
714
715 new_offset = ME_GetCursorOfs(cursor);
716 next_para = cursor->pPara->member.para.next_para;
717 if (new_offset < next_para->member.para.nCharOfs)
718 {
719 /* new offset in the same paragraph */
720 do {
721 cursor->nOffset -= cursor->pRun->member.run.len;
722 cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun);
723 } while (cursor->nOffset >= cursor->pRun->member.run.len);
724 return nRelOfs;
725 }
726
727 if (new_offset >= ME_GetTextLength(editor) + (final_eop ? 1 : 0))
728 {
729 /* new offset at the end of the text */
730 ME_SetCursorToEnd(editor, cursor, final_eop);
731 nRelOfs -= new_offset - (ME_GetTextLength(editor) + (final_eop ? 1 : 0));
732 return nRelOfs;
733 }
734
735 /* new offset in a following paragraph */
736 do {
737 cursor->pPara = next_para;
738 next_para = next_para->member.para.next_para;
739 } while (new_offset >= next_para->member.para.nCharOfs);
740
741 cursor->nOffset = new_offset - cursor->pPara->member.para.nCharOfs;
742 cursor->pRun = ME_FindItemFwd(cursor->pPara, diRun);
743 while (cursor->nOffset >= cursor->pRun->member.run.len)
744 {
745 cursor->nOffset -= cursor->pRun->member.run.len;
746 cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun);
747 }
748 } /* else new offset is in the same run */
749 return nRelOfs;
750}
751
752
753BOOL
755{
756 ME_DisplayItem *pRun = cursor->pRun, *pOtherRun;
757 ME_DisplayItem *pPara = cursor->pPara;
758 int nOffset = cursor->nOffset;
759
760 if (nRelOfs == -1)
761 {
762 /* Backward movement */
763 while (TRUE)
764 {
765 nOffset = ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
766 pRun->member.run.len, nOffset, WB_MOVEWORDLEFT);
767 if (nOffset)
768 break;
769 pOtherRun = ME_FindItemBack(pRun, diRunOrParagraph);
770 if (pOtherRun->type == diRun)
771 {
772 if (ME_CallWordBreakProc(editor, get_text( &pOtherRun->member.run, 0 ),
773 pOtherRun->member.run.len,
774 pOtherRun->member.run.len - 1,
776 && !(pRun->member.run.nFlags & MERF_ENDPARA)
777 && !(cursor->pRun == pRun && cursor->nOffset == 0)
778 && !ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
779 pRun->member.run.len, 0,
781 break;
782 pRun = pOtherRun;
783 nOffset = pOtherRun->member.run.len;
784 }
785 else if (pOtherRun->type == diParagraph)
786 {
787 if (cursor->pRun == pRun && cursor->nOffset == 0)
788 {
789 pPara = pOtherRun;
790 /* Skip empty start of table row paragraph */
791 if (pPara->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART)
792 pPara = pPara->member.para.prev_para;
793 /* Paragraph breaks are treated as separate words */
794 if (pPara->member.para.prev_para->type == diTextStart)
795 return FALSE;
796
797 pRun = ME_FindItemBack(pPara, diRun);
798 pPara = pPara->member.para.prev_para;
799 }
800 break;
801 }
802 }
803 }
804 else
805 {
806 /* Forward movement */
807 BOOL last_delim = FALSE;
808
809 while (TRUE)
810 {
811 if (last_delim && !ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
812 pRun->member.run.len, nOffset, WB_ISDELIMITER))
813 break;
814 nOffset = ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
815 pRun->member.run.len, nOffset, WB_MOVEWORDRIGHT);
816 if (nOffset < pRun->member.run.len)
817 break;
818 pOtherRun = ME_FindItemFwd(pRun, diRunOrParagraphOrEnd);
819 if (pOtherRun->type == diRun)
820 {
821 last_delim = ME_CallWordBreakProc(editor, get_text( &pRun->member.run, 0 ),
822 pRun->member.run.len, nOffset - 1, WB_ISDELIMITER);
823 pRun = pOtherRun;
824 nOffset = 0;
825 }
826 else if (pOtherRun->type == diParagraph)
827 {
828 if (pOtherRun->member.para.nFlags & MEPF_ROWSTART)
829 pOtherRun = pOtherRun->member.para.next_para;
830 if (cursor->pRun == pRun) {
831 pPara = pOtherRun;
832 pRun = ME_FindItemFwd(pPara, diRun);
833 }
834 nOffset = 0;
835 break;
836 }
837 else /* diTextEnd */
838 {
839 if (cursor->pRun == pRun)
840 return FALSE;
841 nOffset = 0;
842 break;
843 }
844 }
845 }
846 cursor->pPara = pPara;
847 cursor->pRun = pRun;
848 cursor->nOffset = nOffset;
849 return TRUE;
850}
851
852
853static void
855{
856 /* pCursor[0] is the end of the selection
857 * pCursor[1] is the start of the selection (or the position selection anchor)
858 * pCursor[2] and [3] are the selection anchors that are backed up
859 * so they are kept when the selection changes for drag selection.
860 */
861
862 editor->nSelectionType = selectionType;
863 switch(selectionType)
864 {
865 case stPosition:
866 break;
867 case stWord:
868 ME_MoveCursorWords(editor, &editor->pCursors[0], +1);
869 editor->pCursors[1] = editor->pCursors[0];
870 ME_MoveCursorWords(editor, &editor->pCursors[1], -1);
871 break;
872 case stLine:
873 case stParagraph:
874 {
875 ME_DisplayItem *pItem;
876 ME_DIType fwdSearchType, backSearchType;
877 if (selectionType == stParagraph) {
878 backSearchType = diParagraph;
879 fwdSearchType = diParagraphOrEnd;
880 } else {
881 backSearchType = diStartRow;
882 fwdSearchType = diStartRowOrParagraphOrEnd;
883 }
884 pItem = ME_FindItemFwd(editor->pCursors[0].pRun, fwdSearchType);
885 assert(pItem);
886 if (pItem->type == diTextEnd)
887 editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun);
888 else
889 editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun);
890 editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun);
891 editor->pCursors[0].nOffset = 0;
892
893 pItem = ME_FindItemBack(pItem, backSearchType);
894 editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun);
895 editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun);
896 editor->pCursors[1].nOffset = 0;
897 break;
898 }
899 case stDocument:
900 /* Select everything with cursor anchored from the start of the text */
901 editor->nSelectionType = stDocument;
902 ME_SetCursorToStart(editor, &editor->pCursors[1]);
903 ME_SetCursorToEnd(editor, &editor->pCursors[0], FALSE);
904 break;
905 default: assert(0);
906 }
907 /* Store the anchor positions for extending the selection. */
908 editor->pCursors[2] = editor->pCursors[0];
909 editor->pCursors[3] = editor->pCursors[1];
910}
911
913{
914 return cursor->pPara->member.para.nCharOfs
915 + cursor->pRun->member.run.nCharOfs + cursor->nOffset;
916}
917
918/* Helper function for ME_FindPixelPos to find paragraph within tables */
920 ME_DisplayItem *para)
921{
922 ME_DisplayItem *cell, *next_cell;
924 cell = para->member.para.next_para->member.para.pCell;
925 assert(cell);
926
927 /* find the cell we are in */
928 while ((next_cell = cell->member.cell.next_cell) != NULL) {
929 if (x < next_cell->member.cell.pt.x)
930 {
931 para = ME_FindItemFwd(cell, diParagraph);
932 /* Found the cell, but there might be multiple paragraphs in
933 * the cell, so need to search down the cell for the paragraph. */
934 while (cell == para->member.para.pCell) {
935 if (y < para->member.para.pt.y + para->member.para.nHeight)
936 {
937 if (para->member.para.nFlags & MEPF_ROWSTART)
938 return ME_FindPixelPosInTableRow(x, y, para);
939 else
940 return para;
941 }
942 para = para->member.para.next_para;
943 }
944 /* Past the end of the cell, so go back to the last cell paragraph */
945 return para->member.para.prev_para;
946 }
947 cell = next_cell;
948 }
949 /* Return table row delimiter */
950 para = ME_FindItemFwd(cell, diParagraph);
954 return para;
955}
956
958 int x, ME_Cursor *cursor, BOOL *pbCaretAtEnd)
959{
960 ME_DisplayItem *pNext, *pLastRun;
961 ME_Row *row = &pRow->member.row;
962 BOOL exact = TRUE;
963
964 if (x < row->pt.x)
965 {
966 x = row->pt.x;
967 exact = FALSE;
968 }
969 pNext = ME_FindItemFwd(pRow, diRunOrStartRow);
970 assert(pNext->type == diRun);
971 if (pbCaretAtEnd) *pbCaretAtEnd = FALSE;
972 cursor->nOffset = 0;
973 do {
974 int run_x = pNext->member.run.pt.x;
975 int width = pNext->member.run.nWidth;
976
977 if (x >= run_x && x < run_x+width)
978 {
979 cursor->nOffset = ME_CharFromPoint(editor, x-run_x, &pNext->member.run, TRUE, TRUE);
980 cursor->pRun = pNext;
981 cursor->pPara = ME_GetParagraph( cursor->pRun );
982 return exact;
983 }
984 pLastRun = pNext;
985 pNext = ME_FindItemFwd(pNext, diRunOrStartRow);
986 } while(pNext && pNext->type == diRun);
987
988 if ((pLastRun->member.run.nFlags & MERF_ENDPARA) == 0)
989 {
990 cursor->pRun = ME_FindItemFwd(pNext, diRun);
991 if (pbCaretAtEnd) *pbCaretAtEnd = TRUE;
992 }
993 else
994 cursor->pRun = pLastRun;
995
996 cursor->pPara = ME_GetParagraph( cursor->pRun );
997 return FALSE;
998}
999
1000/* Finds the run and offset from the pixel position.
1001 *
1002 * x & y are pixel positions in virtual coordinates into the rich edit control,
1003 * so client coordinates must first be adjusted by the scroll position.
1004 *
1005 * If final_eop is TRUE consider the final end-of-paragraph.
1006 *
1007 * returns TRUE if the result was exactly under the cursor, otherwise returns
1008 * FALSE, and result is set to the closest position to the coordinates.
1009 */
1010static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
1011 ME_Cursor *result, BOOL *is_eol, BOOL final_eop)
1012{
1014 BOOL isExact = TRUE;
1015
1016 x -= editor->rcFormat.left;
1017 y -= editor->rcFormat.top;
1018
1019 if (is_eol)
1020 *is_eol = FALSE;
1021
1022 /* find paragraph */
1023 for (; p != editor->pBuffer->pLast; p = p->member.para.next_para)
1024 {
1025 assert(p->type == diParagraph);
1026 if (y < p->member.para.pt.y + p->member.para.nHeight)
1027 {
1028 if (p->member.para.nFlags & MEPF_ROWSTART)
1030 y -= p->member.para.pt.y;
1032 break;
1033 } else if (p->member.para.nFlags & MEPF_ROWSTART) {
1035 }
1036 }
1037 /* find row */
1038 for (; p != editor->pBuffer->pLast; )
1039 {
1040 ME_DisplayItem *pp;
1041 assert(p->type == diStartRow);
1042 if (y < p->member.row.pt.y + p->member.row.nHeight) break;
1044 if (!pp) break;
1045 p = pp;
1046 }
1047 if (p == editor->pBuffer->pLast && !final_eop)
1048 {
1049 /* The position is below the last paragraph, so the last row will be used
1050 * rather than the end of the text, so the x position will be used to
1051 * determine the offset closest to the pixel position. */
1052 isExact = FALSE;
1054 if (!p) p = editor->pBuffer->pLast;
1055 }
1056
1057 assert( p->type == diStartRow || p == editor->pBuffer->pLast );
1058
1059 if( p->type == diStartRow )
1060 return ME_FindRunInRow( editor, p, x, result, is_eol ) && isExact;
1061
1062 ME_SetCursorToEnd(editor, result, TRUE);
1063 return FALSE;
1064}
1065
1066
1067/* Sets the cursor to the position closest to the pixel position
1068 *
1069 * x & y are pixel positions in client coordinates.
1070 *
1071 * isExact will be set to TRUE if the run is directly under the pixel
1072 * position, FALSE if it not, unless isExact is set to NULL.
1073 *
1074 * return FALSE if outside client area and the cursor is not set,
1075 * otherwise TRUE is returned.
1076 */
1078 ME_Cursor *cursor, BOOL *isExact)
1079{
1080 RECT rc;
1081 BOOL bResult;
1082
1083 ITextHost_TxGetClientRect(editor->texthost, &rc);
1084 if (x < 0 || y < 0 || x >= rc.right || y >= rc.bottom) {
1085 if (isExact) *isExact = FALSE;
1086 return FALSE;
1087 }
1088 x += editor->horz_si.nPos;
1089 y += editor->vert_si.nPos;
1090 bResult = ME_FindPixelPos(editor, x, y, cursor, NULL, FALSE);
1091 if (isExact) *isExact = bResult;
1092 return TRUE;
1093}
1094
1095
1096
1097/* Extends the selection with a word, line, or paragraph selection type.
1098 *
1099 * The selection is anchored by editor->pCursors[2-3] such that the text
1100 * between the anchors will remain selected, and one end will be extended.
1101 *
1102 * editor->pCursors[0] should have the position to extend the selection to
1103 * before this function is called.
1104 *
1105 * Nothing will be done if editor->nSelectionType equals stPosition.
1106 */
1108{
1109 ME_Cursor tmp_cursor;
1110 int curOfs, anchorStartOfs, anchorEndOfs;
1111 if (editor->nSelectionType == stPosition || editor->nSelectionType == stDocument)
1112 return;
1113 curOfs = ME_GetCursorOfs(&editor->pCursors[0]);
1114 anchorStartOfs = ME_GetCursorOfs(&editor->pCursors[3]);
1115 anchorEndOfs = ME_GetCursorOfs(&editor->pCursors[2]);
1116
1117 tmp_cursor = editor->pCursors[0];
1118 editor->pCursors[0] = editor->pCursors[2];
1119 editor->pCursors[1] = editor->pCursors[3];
1120 if (curOfs < anchorStartOfs)
1121 {
1122 /* Extend the left side of selection */
1123 editor->pCursors[1] = tmp_cursor;
1124 if (editor->nSelectionType == stWord)
1125 ME_MoveCursorWords(editor, &editor->pCursors[1], -1);
1126 else
1127 {
1128 ME_DisplayItem *pItem;
1129 ME_DIType searchType = ((editor->nSelectionType == stLine) ?
1131 pItem = ME_FindItemBack(editor->pCursors[1].pRun, searchType);
1132 editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun);
1133 editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun);
1134 editor->pCursors[1].nOffset = 0;
1135 }
1136 }
1137 else if (curOfs >= anchorEndOfs)
1138 {
1139 /* Extend the right side of selection */
1140 editor->pCursors[0] = tmp_cursor;
1141 if (editor->nSelectionType == stWord)
1142 ME_MoveCursorWords(editor, &editor->pCursors[0], +1);
1143 else
1144 {
1145 ME_DisplayItem *pItem;
1146 ME_DIType searchType = ((editor->nSelectionType == stLine) ?
1148 pItem = ME_FindItemFwd(editor->pCursors[0].pRun, searchType);
1149 if (pItem->type == diTextEnd)
1150 editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun);
1151 else
1152 editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun);
1153 editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun);
1154 editor->pCursors[0].nOffset = 0;
1155 }
1156 }
1157}
1158
1159void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
1160{
1161 ME_Cursor tmp_cursor;
1162 BOOL is_selection = FALSE, is_shift;
1163
1164 editor->nUDArrowX = -1;
1165
1166 x += editor->horz_si.nPos;
1167 y += editor->vert_si.nPos;
1168
1169 tmp_cursor = editor->pCursors[0];
1170 is_selection = ME_IsSelection(editor);
1171 is_shift = GetKeyState(VK_SHIFT) < 0;
1172
1173 ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd, FALSE);
1174
1175 if (x >= editor->rcFormat.left || is_shift)
1176 {
1177 if (clickNum > 1)
1178 {
1179 editor->pCursors[1] = editor->pCursors[0];
1180 if (is_shift) {
1181 if (x >= editor->rcFormat.left)
1182 ME_SelectByType(editor, stWord);
1183 else
1185 } else if (clickNum % 2 == 0) {
1186 ME_SelectByType(editor, stWord);
1187 } else {
1189 }
1190 }
1191 else if (!is_shift)
1192 {
1193 editor->nSelectionType = stPosition;
1194 editor->pCursors[1] = editor->pCursors[0];
1195 }
1196 else if (!is_selection)
1197 {
1198 editor->nSelectionType = stPosition;
1199 editor->pCursors[1] = tmp_cursor;
1200 }
1201 else if (editor->nSelectionType != stPosition)
1202 {
1204 }
1205 }
1206 else
1207 {
1208 if (clickNum < 2) {
1209 ME_SelectByType(editor, stLine);
1210 } else if (clickNum % 2 == 0 || is_shift) {
1212 } else {
1213 ME_SelectByType(editor, stDocument);
1214 }
1215 }
1216 ME_InvalidateSelection(editor);
1217 update_caret(editor);
1218 ME_SendSelChange(editor);
1219}
1220
1221void ME_MouseMove(ME_TextEditor *editor, int x, int y)
1222{
1223 ME_Cursor tmp_cursor;
1224
1225 if (editor->nSelectionType == stDocument)
1226 return;
1227 x += editor->horz_si.nPos;
1228 y += editor->vert_si.nPos;
1229
1230 tmp_cursor = editor->pCursors[0];
1231 /* FIXME: do something with the return value of ME_FindPixelPos */
1232 ME_FindPixelPos(editor, x, y, &tmp_cursor, &editor->bCaretAtEnd, TRUE);
1233
1234 ME_InvalidateSelection(editor);
1235 editor->pCursors[0] = tmp_cursor;
1237
1238 if (editor->nSelectionType != stPosition &&
1239 memcmp(&editor->pCursors[1], &editor->pCursors[3], sizeof(ME_Cursor)))
1240 {
1241 /* The scroll the cursor towards the other end, since it was the one
1242 * extended by ME_ExtendAnchorSelection */
1243 ME_EnsureVisible(editor, &editor->pCursors[1]);
1244 } else {
1245 ME_EnsureVisible(editor, &editor->pCursors[0]);
1246 }
1247
1248 ME_InvalidateSelection(editor);
1249 update_caret(editor);
1250 ME_SendSelChange(editor);
1251}
1252
1253static int ME_GetXForArrow(ME_TextEditor *editor, ME_Cursor *pCursor)
1254{
1255 ME_DisplayItem *pRun = pCursor->pRun;
1256 int x;
1257
1258 if (editor->nUDArrowX != -1)
1259 x = editor->nUDArrowX;
1260 else {
1261 if (editor->bCaretAtEnd)
1262 {
1263 pRun = ME_FindItemBack(pRun, diRun);
1264 assert(pRun);
1265 x = pRun->member.run.pt.x + pRun->member.run.nWidth;
1266 }
1267 else {
1268 x = pRun->member.run.pt.x;
1269 x += ME_PointFromChar(editor, &pRun->member.run, pCursor->nOffset, TRUE);
1270 }
1271 editor->nUDArrowX = x;
1272 }
1273 return x;
1274}
1275
1276
1277static void
1278ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs, BOOL extend)
1279{
1280 ME_DisplayItem *pRun = pCursor->pRun;
1281 ME_DisplayItem *pOldPara = pCursor->pPara;
1282 ME_DisplayItem *pItem, *pNewPara;
1283 int x = ME_GetXForArrow(editor, pCursor);
1284
1285 if (editor->bCaretAtEnd && !pCursor->nOffset)
1286 if (!ME_PrevRun(&pOldPara, &pRun, TRUE))
1287 return;
1288
1289 if (nRelOfs == -1)
1290 {
1291 /* start of this row */
1292 pItem = ME_FindItemBack(pRun, diStartRow);
1293 assert(pItem);
1294 /* start of the previous row */
1295 pItem = ME_FindItemBack(pItem, diStartRow);
1296 if (!pItem) /* row not found */
1297 {
1298 if (extend)
1299 ME_SetCursorToStart(editor, pCursor);
1300 return;
1301 }
1302 pNewPara = ME_GetParagraph(pItem);
1303 if (pOldPara->member.para.nFlags & MEPF_ROWEND ||
1304 (pOldPara->member.para.pCell &&
1305 pOldPara->member.para.pCell != pNewPara->member.para.pCell))
1306 {
1307 /* Brought out of a cell */
1308 pNewPara = ME_GetTableRowStart(pOldPara)->member.para.prev_para;
1309 if (pNewPara->type == diTextStart)
1310 return; /* At the top, so don't go anywhere. */
1311 pItem = ME_FindItemFwd(pNewPara, diStartRow);
1312 }
1313 if (pNewPara->member.para.nFlags & MEPF_ROWEND)
1314 {
1315 /* Brought into a table row */
1316 ME_Cell *cell = &ME_FindItemBack(pNewPara, diCell)->member.cell;
1317 while (x < cell->pt.x && cell->prev_cell)
1318 cell = &cell->prev_cell->member.cell;
1319 if (cell->next_cell) /* else - we are still at the end of the row */
1320 pItem = ME_FindItemBack(cell->next_cell, diStartRow);
1321 }
1322 }
1323 else
1324 {
1325 /* start of the next row */
1326 pItem = ME_FindItemFwd(pRun, diStartRow);
1327 if (!pItem) /* row not found */
1328 {
1329 if (extend)
1330 ME_SetCursorToEnd(editor, pCursor, TRUE);
1331 return;
1332 }
1333 pNewPara = ME_GetParagraph(pItem);
1334 if (pOldPara->member.para.nFlags & MEPF_ROWSTART ||
1335 (pOldPara->member.para.pCell &&
1336 pOldPara->member.para.pCell != pNewPara->member.para.pCell))
1337 {
1338 /* Brought out of a cell */
1339 pNewPara = ME_GetTableRowEnd(pOldPara)->member.para.next_para;
1340 if (pNewPara->type == diTextEnd)
1341 return; /* At the bottom, so don't go anywhere. */
1342 pItem = ME_FindItemFwd(pNewPara, diStartRow);
1343 }
1344 if (pNewPara->member.para.nFlags & MEPF_ROWSTART)
1345 {
1346 /* Brought into a table row */
1347 ME_DisplayItem *cell = ME_FindItemFwd(pNewPara, diCell);
1348 while (cell->member.cell.next_cell &&
1349 x >= cell->member.cell.next_cell->member.cell.pt.x)
1350 cell = cell->member.cell.next_cell;
1351 pItem = ME_FindItemFwd(cell, diStartRow);
1352 }
1353 }
1354 if (!pItem)
1355 {
1356 /* row not found - ignore */
1357 return;
1358 }
1359 ME_FindRunInRow(editor, pItem, x, pCursor, &editor->bCaretAtEnd);
1360 assert(pCursor->pRun);
1361 assert(pCursor->pRun->type == diRun);
1362}
1363
1364static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
1365{
1367
1368 if (editor->vert_si.nPos < p->member.row.nHeight)
1369 {
1370 ME_SetCursorToStart(editor, pCursor);
1371 editor->bCaretAtEnd = FALSE;
1372 /* Native clears seems to clear this x value on page up at the top
1373 * of the text, but not on page down at the end of the text.
1374 * Doesn't make sense, but we try to be bug for bug compatible. */
1375 editor->nUDArrowX = -1;
1376 } else {
1377 ME_DisplayItem *pRun = pCursor->pRun;
1378 ME_DisplayItem *pLast;
1379 int x, y, yd, yp;
1380 int yOldScrollPos = editor->vert_si.nPos;
1381
1382 x = ME_GetXForArrow(editor, pCursor);
1383 if (!pCursor->nOffset && editor->bCaretAtEnd)
1384 pRun = ME_FindItemBack(pRun, diRun);
1385
1387 assert(p->type == diStartRow);
1389 y = yp + p->member.row.pt.y;
1390
1391 ME_ScrollUp(editor, editor->sizeWindow.cy);
1392 /* Only move the cursor by the amount scrolled. */
1393 yd = y + editor->vert_si.nPos - yOldScrollPos;
1394 pLast = p;
1395
1396 do {
1398 if (!p)
1399 break;
1400 if (p->type == diParagraph) { /* crossing paragraphs */
1401 if (p->member.para.prev_para == NULL)
1402 break;
1403 yp = p->member.para.prev_para->member.para.pt.y;
1404 continue;
1405 }
1406 y = yp + p->member.row.pt.y;
1407 if (y < yd)
1408 break;
1409 pLast = p;
1410 } while(1);
1411
1412 ME_FindRunInRow(editor, pLast, x, pCursor, &editor->bCaretAtEnd);
1413 }
1414 assert(pCursor->pRun);
1415 assert(pCursor->pRun->type == diRun);
1416}
1417
1418static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
1419{
1420 ME_DisplayItem *pLast;
1421 int x, y;
1422
1423 /* Find y position of the last row */
1424 pLast = editor->pBuffer->pLast;
1425 y = pLast->member.para.prev_para->member.para.pt.y
1427
1428 x = ME_GetXForArrow(editor, pCursor);
1429
1430 if (editor->vert_si.nPos >= y - editor->sizeWindow.cy)
1431 {
1432 ME_SetCursorToEnd(editor, pCursor, FALSE);
1433 editor->bCaretAtEnd = FALSE;
1434 } else {
1435 ME_DisplayItem *pRun = pCursor->pRun;
1437 int yd, yp;
1438 int yOldScrollPos = editor->vert_si.nPos;
1439
1440 if (!pCursor->nOffset && editor->bCaretAtEnd)
1441 pRun = ME_FindItemBack(pRun, diRun);
1442
1444 assert(p->type == diStartRow);
1446 y = yp + p->member.row.pt.y;
1447
1448 /* For native richedit controls:
1449 * v1.0 - v3.1 can only scroll down as far as the scrollbar lets us
1450 * v4.1 can scroll past this position here. */
1451 ME_ScrollDown(editor, editor->sizeWindow.cy);
1452 /* Only move the cursor by the amount scrolled. */
1453 yd = y + editor->vert_si.nPos - yOldScrollPos;
1454 pLast = p;
1455
1456 do {
1458 if (!p)
1459 break;
1460 if (p->type == diParagraph) {
1461 yp = p->member.para.pt.y;
1462 continue;
1463 }
1464 y = yp + p->member.row.pt.y;
1465 if (y >= yd)
1466 break;
1467 pLast = p;
1468 } while(1);
1469
1470 ME_FindRunInRow(editor, pLast, x, pCursor, &editor->bCaretAtEnd);
1471 }
1472 assert(pCursor->pRun);
1473 assert(pCursor->pRun->type == diRun);
1474}
1475
1476static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
1477{
1478 ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow);
1479 if (pRow) {
1480 ME_DisplayItem *pRun;
1481 if (editor->bCaretAtEnd && !pCursor->nOffset) {
1482 pRow = ME_FindItemBack(pRow, diStartRow);
1483 if (!pRow)
1484 return;
1485 }
1486 pRun = ME_FindItemFwd(pRow, diRun);
1487 if (pRun) {
1488 pCursor->pRun = pRun;
1489 assert(pCursor->pPara == ME_GetParagraph(pRun));
1490 pCursor->nOffset = 0;
1491 }
1492 }
1493 editor->bCaretAtEnd = FALSE;
1494}
1495
1496static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor)
1497{
1498 ME_SetCursorToStart(editor, pCursor);
1499 editor->bCaretAtEnd = FALSE;
1500}
1501
1502static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
1503{
1504 ME_DisplayItem *pRow;
1505
1506 if (editor->bCaretAtEnd && !pCursor->nOffset)
1507 return;
1508
1510 assert(pRow);
1511 if (pRow->type == diStartRow) {
1512 ME_DisplayItem *pRun = ME_FindItemFwd(pRow, diRun);
1513 assert(pRun);
1514 pCursor->pRun = pRun;
1515 assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun));
1516 pCursor->nOffset = 0;
1517 editor->bCaretAtEnd = TRUE;
1518 return;
1519 }
1520 pCursor->pRun = ME_FindItemBack(pRow, diRun);
1521 assert(pCursor->pRun && pCursor->pRun->member.run.nFlags & MERF_ENDPARA);
1522 assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun));
1523 pCursor->nOffset = 0;
1524 editor->bCaretAtEnd = FALSE;
1525}
1526
1527static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
1528{
1529 ME_SetCursorToEnd(editor, pCursor, FALSE);
1530 editor->bCaretAtEnd = FALSE;
1531}
1532
1534{
1535 return editor->pCursors[0].pRun != editor->pCursors[1].pRun ||
1536 editor->pCursors[0].nOffset != editor->pCursors[1].nOffset;
1537}
1538
1540{
1541 int from, to;
1542 int nStartCursor = ME_GetSelectionOfs(editor, &from, &to);
1543 int nEndCursor = nStartCursor ^ 1;
1544 ME_DeleteTextAtCursor(editor, nStartCursor, to - from);
1545 editor->pCursors[nEndCursor] = editor->pCursors[nStartCursor];
1546}
1547
1549{
1550 return ME_GetInsertStyle(editor, 0);
1551}
1552
1554{
1555 SELCHANGE sc;
1556
1557 sc.nmhdr.hwndFrom = NULL;
1558 sc.nmhdr.idFrom = 0;
1559 sc.nmhdr.code = EN_SELCHANGE;
1560 ME_GetSelectionOfs(editor, &sc.chrg.cpMin, &sc.chrg.cpMax);
1561 sc.seltyp = SEL_EMPTY;
1562 if (sc.chrg.cpMin != sc.chrg.cpMax)
1563 sc.seltyp |= SEL_TEXT;
1564 if (sc.chrg.cpMin < sc.chrg.cpMax+1) /* what were RICHEDIT authors thinking ? */
1565 sc.seltyp |= SEL_MULTICHAR;
1566
1567 if (sc.chrg.cpMin != editor->notified_cr.cpMin || sc.chrg.cpMax != editor->notified_cr.cpMax)
1568 {
1569 ME_ClearTempStyle(editor);
1570
1571 editor->notified_cr = sc.chrg;
1572
1573 if (editor->nEventMask & ENM_SELCHANGE)
1574 {
1575 TRACE("cpMin=%d cpMax=%d seltyp=%d (%s %s)\n",
1576 sc.chrg.cpMin, sc.chrg.cpMax, sc.seltyp,
1577 (sc.seltyp & SEL_TEXT) ? "SEL_TEXT" : "",
1578 (sc.seltyp & SEL_MULTICHAR) ? "SEL_MULTICHAR" : "");
1579 ITextHost_TxNotify(editor->texthost, sc.nmhdr.code, &sc);
1580 }
1581 }
1582}
1583
1584BOOL
1585ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
1586{
1587 int nCursor = 0;
1588 ME_Cursor *p = &editor->pCursors[nCursor];
1589 ME_Cursor tmp_curs = *p;
1590 BOOL success = FALSE;
1591
1592 ME_CheckCharOffsets(editor);
1593 switch(nVKey) {
1594 case VK_LEFT:
1595 editor->bCaretAtEnd = FALSE;
1596 if (ctrl)
1597 success = ME_MoveCursorWords(editor, &tmp_curs, -1);
1598 else
1599 success = ME_MoveCursorChars(editor, &tmp_curs, -1, extend);
1600 break;
1601 case VK_RIGHT:
1602 editor->bCaretAtEnd = FALSE;
1603 if (ctrl)
1604 success = ME_MoveCursorWords(editor, &tmp_curs, +1);
1605 else
1606 success = ME_MoveCursorChars(editor, &tmp_curs, +1, extend);
1607 break;
1608 case VK_UP:
1609 ME_MoveCursorLines(editor, &tmp_curs, -1, extend);
1610 break;
1611 case VK_DOWN:
1612 ME_MoveCursorLines(editor, &tmp_curs, +1, extend);
1613 break;
1614 case VK_PRIOR:
1615 ME_ArrowPageUp(editor, &tmp_curs);
1616 break;
1617 case VK_NEXT:
1618 ME_ArrowPageDown(editor, &tmp_curs);
1619 break;
1620 case VK_HOME: {
1621 if (ctrl)
1622 ME_ArrowCtrlHome(editor, &tmp_curs);
1623 else
1624 ME_ArrowHome(editor, &tmp_curs);
1625 editor->bCaretAtEnd = FALSE;
1626 break;
1627 }
1628 case VK_END:
1629 if (ctrl)
1630 ME_ArrowCtrlEnd(editor, &tmp_curs);
1631 else
1632 ME_ArrowEnd(editor, &tmp_curs);
1633 break;
1634 }
1635
1636 if (!extend)
1637 editor->pCursors[1] = tmp_curs;
1638 *p = tmp_curs;
1639
1640 ME_InvalidateSelection(editor);
1641 ME_Repaint(editor);
1642 hide_caret(editor);
1643 ME_EnsureVisible(editor, &tmp_curs);
1644 update_caret(editor);
1645 ME_SendSelChange(editor);
1646 return success;
1647}
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:65
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define E_INVALIDARG
Definition: ddrawi.h:101
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI GetCPInfo(UINT CodePage, LPCPINFO CodePageInfo)
Definition: nls.c:2039
void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor)
Definition: caret.c:535
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:465
BOOL ME_IsSelection(ME_TextEditor *editor)
Definition: caret.c:1533
void ME_DeleteSelection(ME_TextEditor *editor)
Definition: caret.c:1539
static int ME_GetXForArrow(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1253
static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1476
static void ME_ExtendAnchorSelection(ME_TextEditor *editor)
Definition: caret.c:1107
int ME_GetCursorOfs(const ME_Cursor *cursor)
Definition: caret.c:912
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, const WCHAR *str, int len, ME_Style *style)
Definition: caret.c:550
int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BOOL final_eop)
Definition: caret.c:675
BOOL ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
Definition: caret.c:754
void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT *reo, int nCursor)
Definition: caret.c:501
void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
Definition: caret.c:1159
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:1364
static void ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs, BOOL extend)
Definition: caret.c:1278
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:315
static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *result, BOOL *is_eol, BOOL final_eop)
Definition: caret.c:1010
void hide_caret(ME_TextEditor *editor)
Definition: caret.c:288
static void ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType)
Definition: caret.c:854
static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1527
void ME_MouseMove(ME_TextEditor *editor, int x, int y)
Definition: caret.c:1221
BOOL ME_CharFromPos(ME_TextEditor *editor, int x, int y, ME_Cursor *cursor, BOOL *isExact)
Definition: caret.c:1077
static ME_DisplayItem * ME_FindPixelPosInTableRow(int x, int y, ME_DisplayItem *para)
Definition: caret.c:919
void ME_SendSelChange(ME_TextEditor *editor)
Definition: caret.c:1553
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:1585
static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1418
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:957
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:1502
static ME_DisplayItem * ME_InternalInsertTextFromCursor(ME_TextEditor *editor, int nCursor, const WCHAR *str, int len, ME_Style *style, int flags)
Definition: caret.c:475
void update_caret(ME_TextEditor *editor)
Definition: caret.c:298
static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor)
Definition: caret.c:1496
ME_Style * ME_GetSelectionInsertStyle(ME_TextEditor *editor)
Definition: caret.c:1548
static struct re_object * create_re_object(const REOBJECT *reo)
Definition: caret.c:488
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_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
static __inline int is_eol(struct parser *parser, const CHAR *ptr)
Definition: inffile.c:422
#define c
Definition: ke_i.h:80
#define shift
Definition: input.c:1755
#define ctrl
Definition: input.c:1756
#define min(a, b)
Definition: monoChain.cc:55
#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 GTL_PRECISE
Definition: richedit.h:1056
#define PFM_TABLEROWDELIMITER
Definition: richedit.h:868
#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
LONG cpMax
Definition: richedit.h:501
LONG cpMin
Definition: richedit.h:500
UINT MaxCharSize
Definition: winnls.h:581
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
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
ME_DIType type
Definition: editstr.h:256
ME_Cell cell
Definition: editstr.h:261
union tagME_DisplayItem::@523 member
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:439
ITextHost * texthost
Definition: editstr.h:383
struct list reobj_list
Definition: editstr.h:446
ME_SelectionType nSelectionType
Definition: editstr.h:432
ME_Cursor * pCursors
Definition: editstr.h:387
SCROLLINFO horz_si
Definition: editstr.h:439
ME_TextBuffer * pBuffer
Definition: editstr.h:386
CHARRANGE notified_cr
Definition: editstr.h:436
BOOL bEmulateVersion10
Definition: editstr.h:385
BOOL caret_hidden
Definition: editstr.h:442
BOOL bCaretAtEnd
Definition: editstr.h:399
UINT_PTR idFrom
Definition: winuser.h:3148
UINT code
Definition: winuser.h:3149
HWND hwndFrom
Definition: winuser.h:3147
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
LONG cy
Definition: windef.h:335
#define success(from, fromstr, to, tostr)
#define WB_ISDELIMITER
Definition: winuser.h:549
#define VK_UP
Definition: winuser.h:2215
#define VK_NEXT
Definition: winuser.h:2211
#define VK_END
Definition: winuser.h:2212
#define VK_HOME
Definition: winuser.h:2213
#define VK_LEFT
Definition: winuser.h:2214
#define VK_RIGHT
Definition: winuser.h:2216
#define VK_DOWN
Definition: winuser.h:2217
#define VK_SHIFT
Definition: winuser.h:2192
#define VK_PRIOR
Definition: winuser.h:2210
SHORT WINAPI GetKeyState(_In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180