ReactOS 0.4.16-dev-1305-ge26ad0d
run.c
Go to the documentation of this file.
1/*
2 * RichEdit - operations on runs (diRun, rectangular pieces of paragraphs).
3 * Splitting/joining runs. Adjusting offsets after deleting/adding content.
4 * Character/pixel conversions.
5 *
6 * Copyright 2004 by Krzysztof Foltman
7 * Copyright 2006 by Phil Krylov
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include "editor.h"
25
29
31{
33
34 while (p->type != diTextEnd)
35 {
36 if (p->type == diParagraph && !all_para) return FALSE;
37 else if (p->type == diRun)
38 {
39 cursor->run = &p->member.run;
40 cursor->para = cursor->run->para;
41 cursor->nOffset = 0;
42 return TRUE;
43 }
44 p = p->next;
45 }
46 return FALSE;
47}
48
50{
52
53 while (p->type != diTextStart)
54 {
55 if (p->type == diParagraph && !all_para) return FALSE;
56 else if (p->type == diRun)
57 {
58 cursor->run = &p->member.run;
59 cursor->para = cursor->run->para;
60 cursor->nOffset = 0;
61 return TRUE;
62 }
63 p = p->prev;
64 }
65 return FALSE;
66}
67
69{
71
72 cursor.run = run;
73 cursor.para = run->para;
74 cursor.nOffset = 0;
75
77 return cursor.run;
78
79 return NULL;
80}
81
83{
85
86 cursor.run = run;
87 cursor.para = run->para;
88 cursor.nOffset = 0;
89
91 return cursor.run;
92
93 return NULL;
94}
95
97{
99
100 cursor.run = run;
101 cursor.para = run->para;
102 cursor.nOffset = 0;
103
104 if (cursor_next_run( &cursor, TRUE ))
105 return cursor.run;
106
107 return NULL;
108}
109
111{
113
114 cursor.run = run;
115 cursor.para = run->para;
116 cursor.nOffset = 0;
117
118 if (cursor_prev_run( &cursor, TRUE ))
119 return cursor.run;
120
121 return NULL;
122}
123
124/******************************************************************************
125 * ME_CanJoinRuns
126 *
127 * Returns TRUE if two runs can be safely merged into one, FALSE otherwise.
128 */
129BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2)
130{
131 if ((run1->nFlags | run2->nFlags) & MERF_NOJOIN)
132 return FALSE;
133 if (run1->style != run2->style)
134 return FALSE;
135 if ((run1->nFlags & MERF_STYLEFLAGS) != (run2->nFlags & MERF_STYLEFLAGS))
136 return FALSE;
137 return TRUE;
138}
139
140/******************************************************************************
141 * editor_propagate_char_ofs
142 *
143 * Shifts (increases or decreases) character offset (relative to beginning of
144 * the document) of the part of the text starting from given place.
145 * Call with only one of para or run non-NULL.
146 */
148{
149 assert( !para ^ !run );
150
151 if (run)
152 {
153 para = para_next( run->para );
154 do
155 {
156 run->nCharOfs += shift;
157 run = run_next( run );
158 } while (run);
159 }
160
161 do
162 {
163 /* update position in marked tree, if added */
164 if (para->nFlags & MEPF_REWRAP)
165 para_mark_remove( editor, para );
166 para->nCharOfs += shift;
167 if (para->nFlags & MEPF_REWRAP)
168 para_mark_add( editor, para );
169 para = para_next( para );
170 } while (para);
171}
172
173/******************************************************************************
174 * ME_CheckCharOffsets
175 *
176 * Checks if editor lists' validity and optionally dumps the document structure
177 */
179{
180 ME_DisplayItem *p = editor->pBuffer->pFirst;
181 int ofs = 0, ofsp = 0;
182
183 if (!TRACE_ON(richedit_check))
184 return;
185
186 TRACE_(richedit_check)("Checking begin\n");
187 if(TRACE_ON(richedit_lists))
188 {
189 TRACE_(richedit_lists)("---\n");
190 ME_DumpDocument(editor->pBuffer);
191 }
192 do {
194 switch(p->type) {
195 case diTextEnd:
196 TRACE_(richedit_check)("tend, real ofsp = %d, counted = %d\n", p->member.para.nCharOfs, ofsp+ofs);
197 assert(ofsp+ofs == p->member.para.nCharOfs);
198 TRACE_(richedit_check)("Checking finished\n");
199 return;
200 case diParagraph:
201 TRACE_(richedit_check)("para, real ofsp = %d, counted = %d\n", p->member.para.nCharOfs, ofsp+ofs);
202 assert(ofsp+ofs == p->member.para.nCharOfs);
203 ofsp = p->member.para.nCharOfs;
204 ofs = 0;
205 break;
206 case diRun:
207 TRACE_(richedit_check)("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = %s, flags=%08x, fx&mask = %08lx\n",
208 p->member.run.nCharOfs, p->member.run.nCharOfs+ofsp, ofsp+ofs,
209 p->member.run.len, debugstr_run( &p->member.run ),
210 p->member.run.nFlags,
211 p->member.run.style->fmt.dwMask & p->member.run.style->fmt.dwEffects);
212 assert(ofs == p->member.run.nCharOfs);
213 assert(p->member.run.len);
214 ofs += p->member.run.len;
215 break;
216 case diCell:
217 TRACE_(richedit_check)("cell\n");
218 break;
219 default:
220 assert(0);
221 }
222 } while(1);
223 TRACE_(richedit_check)("Checking finished\n");
224}
225
226/******************************************************************************
227 * run_char_ofs
228 *
229 * Converts a character position relative to the start of the run to a
230 * character position relative to the start of the document.
231 */
232
233int run_char_ofs( ME_Run *run, int ofs )
234{
235 return run->para->nCharOfs + run->nCharOfs + ofs;
236}
237
238/******************************************************************************
239 * cursor_from_char_ofs
240 *
241 * Converts a character offset (relative to the start of the document) to
242 * a cursor structure (which contains a run and a position relative to that
243 * run).
244 */
245void cursor_from_char_ofs( ME_TextEditor *editor, int char_ofs, ME_Cursor *cursor )
246{
247 ME_Paragraph *para;
248 ME_Run *run;
249
250 char_ofs = min( max( char_ofs, 0 ), ME_GetTextLength( editor ) );
251
252 /* Find the paragraph at the offset. */
253 for (para = editor_first_para( editor );
254 para_next( para )->nCharOfs <= char_ofs;
255 para = para_next( para ))
256 ;
257
258 char_ofs -= para->nCharOfs;
259
260 /* Find the run at the offset. */
261 for (run = para_first_run( para );
262 run_next( run ) && run_next( run )->nCharOfs <= char_ofs;
263 run = run_next( run ))
264 ;
265
266 char_ofs -= run->nCharOfs;
267
268 cursor->para = para;
269 cursor->run = run;
270 cursor->nOffset = char_ofs;
271}
272
273/******************************************************************************
274 * run_join
275 *
276 * Merges two adjacent runs, the one given as a parameter and the next one.
277 */
278void run_join( ME_TextEditor *editor, ME_Run *run )
279{
280 ME_Run *next = run_next( run );
281 int i;
282
283 assert( run );
284 assert( run->nCharOfs != -1 );
285 para_mark_rewrap( editor, run->para );
286
287 /* Update all cursors so that they don't contain the soon deleted run */
288 for (i = 0; i < editor->nCursors; i++)
289 {
290 if (editor->pCursors[i].run == next)
291 {
292 editor->pCursors[i].run = run;
293 editor->pCursors[i].nOffset += run->len;
294 }
295 }
296
297 run->len += next->len;
300 ME_UpdateRunFlags( editor, run );
301 ME_CheckCharOffsets( editor );
302}
303
304/******************************************************************************
305 * run_split
306 *
307 * Does the most basic job of splitting a run into two - it does not
308 * update the positions and extents.
309 */
311{
312 ME_Run *run = cursor->run, *new_run;
313 int i;
314 int nOffset = cursor->nOffset;
315
316 assert( !(run->nFlags & MERF_NONTEXT) );
317
318 new_run = run_create( run->style, run->nFlags & MERF_SPLITMASK );
319 new_run->nCharOfs = run->nCharOfs + nOffset;
320 new_run->len = run->len - nOffset;
321 new_run->para = run->para;
322 run->len = nOffset;
323 cursor->run = new_run;
324 cursor->nOffset = 0;
325
326 ME_InsertBefore( run_get_di( run )->next, run_get_di( new_run ) );
327
328 ME_UpdateRunFlags( editor, run );
329 ME_UpdateRunFlags( editor, new_run );
330 for (i = 0; i < editor->nCursors; i++)
331 {
332 if (editor->pCursors[i].run == run &&
333 editor->pCursors[i].nOffset >= nOffset)
334 {
335 editor->pCursors[i].run = new_run;
336 editor->pCursors[i].nOffset -= nOffset;
337 }
338 }
339 para_mark_rewrap( editor, run->para );
340 return run;
341}
342
343/******************************************************************************
344 * run_create
345 *
346 * A helper function to create run structures quickly.
347 */
349{
351 ME_Run *run = &item->member.run;
352
353 if (!item) return NULL;
354
355 ME_AddRefStyle( s );
356 run->style = s;
357 run->reobj = NULL;
358 run->nFlags = flags;
359 run->nCharOfs = -1;
360 run->len = 0;
361 run->para = NULL;
362 run->num_glyphs = 0;
363 run->max_glyphs = 0;
364 run->glyphs = NULL;
365 run->vis_attrs = NULL;
366 run->advances = NULL;
367 run->offsets = NULL;
368 run->max_clusters = 0;
369 run->clusters = NULL;
370 return run;
371}
372
373/******************************************************************************
374 * run_insert
375 *
376 * Inserts a new run with given style, flags and content at a given position,
377 * which is passed as a cursor structure (which consists of a run and
378 * a run-relative character offset).
379 */
381 const WCHAR *str, int len, int flags )
382{
383 ME_Run *insert_before = cursor->run, *run, *prev;
384
385 if (cursor->nOffset)
386 {
387 if (cursor->nOffset == insert_before->len)
388 {
389 insert_before = run_next_all_paras( insert_before );
390 if (!insert_before) insert_before = cursor->run; /* Always insert before the final eop run */
391 }
392 else
393 {
394 run_split( editor, cursor );
395 insert_before = cursor->run;
396 }
397 }
398
399 add_undo_delete_run( editor, insert_before->para->nCharOfs + insert_before->nCharOfs, len );
400
401 run = run_create( style, flags );
402 run->nCharOfs = insert_before->nCharOfs;
403 run->len = len;
404 run->para = insert_before->para;
405 ME_InsertString( run->para->text, run->nCharOfs, str, len );
406 ME_InsertBefore( run_get_di( insert_before ), run_get_di( run ) );
407 TRACE("Shift length:%d\n", len);
408 editor_propagate_char_ofs( editor, NULL, insert_before, len );
409 para_mark_rewrap( editor, insert_before->para );
410
411 /* Move any cursors that were at the end of the previous run to the end of the inserted run */
412 prev = run_prev_all_paras( run );
413 if (prev)
414 {
415 int i;
416
417 for (i = 0; i < editor->nCursors; i++)
418 {
419 if (editor->pCursors[i].run == prev &&
420 editor->pCursors[i].nOffset == prev->len)
421 {
422 editor->pCursors[i].run = run;
423 editor->pCursors[i].nOffset = len;
424 }
425 }
426 }
427
428 return run;
429}
430
431static BOOL run_is_splittable( const ME_Run *run )
432{
433 WCHAR *str = get_text( run, 0 ), *p;
434 int i;
435 BOOL found_ink = FALSE;
436
437 for (i = 0, p = str; i < run->len; i++, p++)
438 {
439 if (ME_IsWSpace( *p ))
440 {
441 if (found_ink) return TRUE;
442 }
443 else
444 found_ink = TRUE;
445 }
446 return FALSE;
447}
448
449static BOOL run_is_entirely_ws( const ME_Run *run )
450{
451 WCHAR *str = get_text( run, 0 ), *p;
452 int i;
453
454 for (i = 0, p = str; i < run->len; i++, p++)
455 if (!ME_IsWSpace( *p )) return FALSE;
456
457 return TRUE;
458}
459
460/******************************************************************************
461 * ME_UpdateRunFlags
462 *
463 * Determine some of run attributes given its content (style, text content).
464 * Some flags cannot be determined by this function (MERF_GRAPHICS,
465 * MERF_ENDPARA)
466 */
468{
469 assert(run->nCharOfs >= 0);
470
471 if (RUN_IS_HIDDEN(run) || run->nFlags & MERF_TABLESTART)
472 run->nFlags |= MERF_HIDDEN;
473 else
474 run->nFlags &= ~MERF_HIDDEN;
475
476 if (run_is_splittable( run ))
477 run->nFlags |= MERF_SPLITTABLE;
478 else
479 run->nFlags &= ~MERF_SPLITTABLE;
480
481 if (!(run->nFlags & MERF_NOTEXT))
482 {
483 if (run_is_entirely_ws( run ))
485 else
486 {
487 run->nFlags &= ~MERF_WHITESPACE;
488
489 if (ME_IsWSpace( *get_text( run, 0 ) ))
490 run->nFlags |= MERF_STARTWHITE;
491 else
492 run->nFlags &= ~MERF_STARTWHITE;
493
494 if (ME_IsWSpace( *get_text( run, run->len - 1 ) ))
495 run->nFlags |= MERF_ENDWHITE;
496 else
497 run->nFlags &= ~MERF_ENDWHITE;
498 }
499 }
500 else
502}
503
504/******************************************************************************
505 * ME_CharFromPointContext
506 *
507 * Returns a character position inside the run given a run-relative
508 * pixel horizontal position.
509 *
510 * If closest is FALSE return the actual character
511 * If closest is TRUE will round to the closest leading edge.
512 * ie. if the second character is at pixel position 8 and third at 16 then for:
513 * closest = FALSE cx = 0..7 return 0, cx = 8..15 return 1
514 * closest = TRUE cx = 0..3 return 0, cx = 4..11 return 1.
515 */
516int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BOOL visual_order)
517{
518 ME_String *mask_text = NULL;
519 WCHAR *str;
520 int fit = 0;
521 SIZE sz, sz2, sz3;
522 if (!run->len || cx <= 0)
523 return 0;
524
525 if (run->nFlags & (MERF_TAB | MERF_ENDCELL))
526 {
527 if (!closest || cx < run->nWidth / 2) return 0;
528 return 1;
529 }
530
531 if (run->nFlags & MERF_GRAPHICS)
532 {
533 SIZE sz;
534 ME_GetOLEObjectSize(c, run, &sz);
535 if (!closest || cx < sz.cx / 2) return 0;
536 return 1;
537 }
538
539 if (run->para->nFlags & MEPF_COMPLEX)
540 {
541 int cp, trailing;
542 if (visual_order && run->script_analysis.fRTL) cx = run->nWidth - cx - 1;
543
544 ScriptXtoCP( cx, run->len, run->num_glyphs, run->clusters, run->vis_attrs, run->advances, &run->script_analysis,
545 &cp, &trailing );
546 TRACE("x %d cp %d trailing %d (run width %d) rtl %d log order %d\n", cx, cp, trailing, run->nWidth,
548 return closest ? cp + trailing : cp;
549 }
550
551 if (c->editor->password_char)
552 {
553 mask_text = ME_MakeStringR( c->editor->password_char, run->len );
554 str = mask_text->szData;
555 }
556 else
557 str = get_text( run, 0 );
558
559 select_style(c, run->style);
560 GetTextExtentExPointW(c->hDC, str, run->len,
561 cx, &fit, NULL, &sz);
562 if (closest && fit != run->len)
563 {
564 GetTextExtentPoint32W(c->hDC, str, fit, &sz2);
565 GetTextExtentPoint32W(c->hDC, str, fit + 1, &sz3);
566 if (cx >= (sz2.cx+sz3.cx)/2)
567 fit = fit + 1;
568 }
569
570 ME_DestroyString( mask_text );
571
572 return fit;
573}
574
575int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, BOOL visual_order)
576{
578 int ret;
579 HDC hdc = ITextHost_TxGetDC( editor->texthost );
580
581 ME_InitContext( &c, editor, hdc );
582 ret = ME_CharFromPointContext( &c, cx, run, closest, visual_order );
585 return ret;
586}
587
588/******************************************************************************
589 * ME_GetTextExtent
590 *
591 * Finds a width and a height of the text using a specified style
592 */
593static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size)
594{
595 if (c->hDC)
596 {
597 select_style( c, s );
598 GetTextExtentPoint32W( c->hDC, szText, nChars, size );
599 }
600 else
601 {
602 size->cx = 0;
603 size->cy = 0;
604 }
605}
606
607/******************************************************************************
608 * ME_PointFromCharContext
609 *
610 * Returns a run-relative pixel position given a run-relative character
611 * position (character offset)
612 */
613int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order)
614{
615 SIZE size;
616 ME_String *mask_text = NULL;
617 WCHAR *str;
618
619 if (pRun->nFlags & MERF_GRAPHICS)
620 {
621 if (nOffset)
622 ME_GetOLEObjectSize(c, pRun, &size);
623 return nOffset != 0;
624 } else if (pRun->nFlags & MERF_ENDPARA) {
625 nOffset = 0;
626 }
627
628 if (pRun->para->nFlags & MEPF_COMPLEX)
629 {
630 int x;
631 ScriptCPtoX( nOffset, FALSE, pRun->len, pRun->num_glyphs, pRun->clusters,
632 pRun->vis_attrs, pRun->advances, &pRun->script_analysis, &x );
633 if (visual_order && pRun->script_analysis.fRTL) x = pRun->nWidth - x - 1;
634 return x;
635 }
636 if (c->editor->password_char)
637 {
638 mask_text = ME_MakeStringR( c->editor->password_char, pRun->len );
639 str = mask_text->szData;
640 }
641 else
642 str = get_text( pRun, 0 );
643
644 ME_GetTextExtent(c, str, nOffset, pRun->style, &size);
645 ME_DestroyString( mask_text );
646 return size.cx;
647}
648
649/******************************************************************************
650 * ME_PointFromChar
651 *
652 * Calls ME_PointFromCharContext after first creating a context.
653 */
654int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visual_order)
655{
657 int ret;
658 HDC hdc = ITextHost_TxGetDC( editor->texthost );
659
660 ME_InitContext( &c, editor, hdc );
661 ret = ME_PointFromCharContext( &c, pRun, nOffset, visual_order );
664
665 return ret;
666}
667
668/******************************************************************************
669 * ME_GetRunSizeCommon
670 *
671 * Finds width, height, ascent and descent of a run, up to given character
672 * (nLen).
673 */
675 int startx, int *pAscent, int *pDescent)
676{
677 SIZE size;
678
679 nLen = min( nLen, run->len );
680
681 if (run->nFlags & MERF_ENDPARA)
682 {
683 nLen = min( nLen, 1 );
684 ME_GetTextExtent( c, L" ", nLen, run->style, &size );
685 }
686 else if (para->nFlags & MEPF_COMPLEX)
687 {
688 size.cx = run->nWidth;
689 }
690 else if (c->editor->password_char)
691 {
692 ME_String *szMasked = ME_MakeStringR( c->editor->password_char, nLen );
693 ME_GetTextExtent(c, szMasked->szData, nLen,run->style, &size);
694 ME_DestroyString(szMasked);
695 }
696 else
697 {
698 ME_GetTextExtent(c, get_text( run, 0 ), nLen, run->style, &size);
699 }
700 *pAscent = run->style->tm.tmAscent;
701 *pDescent = run->style->tm.tmDescent;
702 size.cy = *pAscent + *pDescent;
703
704 if (run->nFlags & MERF_TAB)
705 {
706 int pos = 0, i = 0, ppos, shift = 0;
707 const PARAFORMAT2 *pFmt = &para->fmt;
708
709 if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
710 pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
711 /* The horizontal gap shifts the tab positions to leave the gap. */
712 shift = pFmt->dxOffset * 2;
713 do {
714 if (i < pFmt->cTabCount)
715 {
716 /* Only one side of the horizontal gap is needed at the end of
717 * the table row. */
718 if (i == pFmt->cTabCount -1)
719 shift = shift >> 1;
720 pos = shift + (pFmt->rgxTabs[i]&0x00FFFFFF);
721 i++;
722 }
723 else
724 {
726 }
727 ppos = ME_twips2pointsX(c, pos);
728 if (ppos > startx + run->pt.x) {
729 size.cx = ppos - startx - run->pt.x;
730 break;
731 }
732 } while(1);
733 size.cy = *pAscent + *pDescent;
734 return size;
735 }
736 if (run->nFlags & MERF_GRAPHICS)
737 {
738 ME_GetOLEObjectSize(c, run, &size);
739 if (size.cy > *pAscent)
740 *pAscent = size.cy;
741 /* descent is unchanged */
742 return size;
743 }
744 return size;
745}
746
747/******************************************************************************
748 * ME_SetSelectionCharFormat
749 *
750 * Applies a style change, either to a current selection, or to insert cursor
751 * (ie. the style next typed characters will use).
752 */
754{
755 if (!ME_IsSelection(editor))
756 {
757 ME_Style *s;
758 if (!editor->pBuffer->pCharStyle)
759 editor->pBuffer->pCharStyle = style_get_insert_style( editor, editor->pCursors );
760 s = ME_ApplyStyle(editor, editor->pBuffer->pCharStyle, pFmt);
762 editor->pBuffer->pCharStyle = s;
763 } else {
764 ME_Cursor *from, *to;
765 ME_GetSelection(editor, &from, &to);
766 ME_SetCharFormat(editor, from, to, pFmt);
767 }
768}
769
770/******************************************************************************
771 * ME_SetCharFormat
772 *
773 * Applies a style change to the specified part of the text
774 *
775 * The start and end cursors specify the part of the text. These cursors will
776 * be updated to stay valid, but this function may invalidate other
777 * non-selection cursors. The end cursor may be NULL to specify all the text
778 * following the start cursor.
779 *
780 * If no text is selected, then nothing is done.
781 */
783{
784 ME_Run *run, *start_run = start->run, *end_run = NULL;
785
786 if (end && start->run == end->run && start->nOffset == end->nOffset)
787 return;
788
789 if (start->nOffset == start->run->len)
790 start_run = run_next_all_paras( start->run );
791 else if (start->nOffset)
792 {
793 /* run_split() may or may not update the cursors, depending on whether they
794 * are selection cursors, but we need to make sure they are valid. */
795 int split_offset = start->nOffset;
796 ME_Run *split_run = run_split( editor, start );
797 start_run = start->run;
798 if (end && end->run == split_run)
799 {
800 end->run = start->run;
801 end->nOffset -= split_offset;
802 }
803 }
804
805 if (end)
806 {
807 if (end->nOffset == end->run->len)
808 end_run = run_next_all_paras( end->run );
809 else
810 {
811 if (end->nOffset) run_split( editor, end );
812 end_run = end->run;
813 }
814 }
815
816 for (run = start_run; run != end_run; run = run_next_all_paras( run ))
817 {
818 ME_Style *new_style = ME_ApplyStyle( editor, run->style, fmt );
819 ME_Paragraph *para = run->para;
820
821 add_undo_set_char_fmt( editor, para->nCharOfs + run->nCharOfs,
822 run->len, &run->style->fmt );
823 ME_ReleaseStyle( run->style );
824 run->style = new_style;
825
826 /* The para numbering style depends on the eop style */
827 if ((run->nFlags & MERF_ENDPARA) && para->para_num.style)
828 {
829 ME_ReleaseStyle(para->para_num.style);
830 para->para_num.style = NULL;
831 }
832 para_mark_rewrap( editor, para );
833 }
834}
835
837{
838 ME_CopyCharFormat( fmt, &run->style->fmt );
839}
840
841/******************************************************************************
842 * ME_GetDefaultCharFormat
843 *
844 * Retrieves the current default character style (the one applied where no
845 * other style was applied) .
846 */
848{
849 ME_CopyCharFormat(pFmt, &editor->pBuffer->pDefaultStyle->fmt);
850}
851
852/******************************************************************************
853 * ME_GetSelectionCharFormat
854 *
855 * If selection exists, it returns all style elements that are set consistently
856 * in the whole selection. If not, it just returns the current style.
857 */
859{
860 ME_Cursor *from, *to;
861 if (!ME_IsSelection(editor) && editor->pBuffer->pCharStyle)
862 {
863 ME_CopyCharFormat(pFmt, &editor->pBuffer->pCharStyle->fmt);
864 return;
865 }
866 ME_GetSelection(editor, &from, &to);
867 ME_GetCharFormat(editor, from, to, pFmt);
868}
869
870/******************************************************************************
871 * ME_GetCharFormat
872 *
873 * Returns the style consisting of those attributes which are consistently set
874 * in the whole character range.
875 */
877 const ME_Cursor *to, CHARFORMAT2W *fmt )
878{
879 ME_Run *run, *run_end, *prev_run;
880 CHARFORMAT2W tmp;
881
882 run = from->run;
883 /* special case - if selection is empty, take previous char's formatting */
884 if (from->run == to->run && from->nOffset == to->nOffset)
885 {
886 if (!from->nOffset && (prev_run = run_prev( run ))) run = prev_run;
887 run_copy_char_fmt( run, fmt );
888 return;
889 }
890
891 run_end = to->run;
892 if (!to->nOffset) run_end = run_prev_all_paras( run_end );
893
894 run_copy_char_fmt( run, fmt );
895
896 if (run == run_end) return;
897
898 do {
899 /* FIXME add more style feature comparisons */
902
903 run = run_next_all_paras( run );
904
905 memset( &tmp, 0, sizeof(tmp) );
906 tmp.cbSize = sizeof(tmp);
907 run_copy_char_fmt( run, &tmp );
908
909 assert((tmp.dwMask & dwAttribs) == dwAttribs);
910
911 /* reset flags that differ */
912 if (fmt->dwMask & CFM_FACE)
913 {
914 if (!(tmp.dwMask & CFM_FACE))
915 fmt->dwMask &= ~CFM_FACE;
916 else if (wcscmp( fmt->szFaceName, tmp.szFaceName ) ||
917 fmt->bPitchAndFamily != tmp.bPitchAndFamily)
918 fmt->dwMask &= ~CFM_FACE;
919 }
920 if (fmt->yHeight != tmp.yHeight) fmt->dwMask &= ~CFM_SIZE;
921 if (fmt->bUnderlineType != tmp.bUnderlineType) fmt->dwMask &= ~CFM_UNDERLINETYPE;
922 if (fmt->dwMask & CFM_COLOR)
923 {
924 if (!((fmt->dwEffects&CFE_AUTOCOLOR) & (tmp.dwEffects&CFE_AUTOCOLOR)))
925 {
926 if (fmt->crTextColor != tmp.crTextColor)
927 fmt->dwMask &= ~CFM_COLOR;
928 }
929 }
930
931 fmt->dwMask &= ~((fmt->dwEffects ^ tmp.dwEffects) & dwEffects);
932 fmt->dwEffects = tmp.dwEffects;
933
934 } while(run != run_end);
935}
Arabic default style
Definition: afstyles.h:94
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define TRACE_(x)
Definition: compat.h:76
#define TRACE_ON(x)
Definition: compat.h:75
#define WINE_DECLARE_DEBUG_CHANNEL(x)
Definition: compat.h:45
BOOL ME_IsSelection(ME_TextEditor *editor)
Definition: caret.c:1419
int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to)
Definition: caret.c:57
int ME_GetTextLength(ME_TextEditor *editor)
Definition: caret.c:83
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
ME_Paragraph * editor_first_para(ME_TextEditor *editor)
Definition: editor.c:276
ME_Run * run_next(ME_Run *run)
Definition: run.c:68
int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order)
Definition: run.c:613
static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size)
Definition: run.c:593
int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BOOL visual_order)
Definition: run.c:516
static BOOL run_is_splittable(const ME_Run *run)
Definition: run.c:431
int run_char_ofs(ME_Run *run, int ofs)
Definition: run.c:233
BOOL cursor_next_run(ME_Cursor *cursor, BOOL all_para)
Definition: run.c:30
void editor_propagate_char_ofs(ME_TextEditor *editor, ME_Paragraph *para, ME_Run *run, int shift)
Definition: run.c:147
ME_Run * run_insert(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, const WCHAR *str, int len, int flags)
Definition: run.c:380
ME_Run * run_prev(ME_Run *run)
Definition: run.c:82
void run_join(ME_TextEditor *editor, ME_Run *run)
Definition: run.c:278
void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from, const ME_Cursor *to, CHARFORMAT2W *fmt)
Definition: run.c:876
void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run)
Definition: run.c:467
static void run_copy_char_fmt(ME_Run *run, CHARFORMAT2W *fmt)
Definition: run.c:836
static BOOL run_is_entirely_ws(const ME_Run *run)
Definition: run.c:449
ME_Run * run_prev_all_paras(ME_Run *run)
Definition: run.c:110
int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visual_order)
Definition: run.c:654
ME_Run * run_create(ME_Style *s, int flags)
Definition: run.c:348
SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen, int startx, int *pAscent, int *pDescent)
Definition: run.c:674
BOOL cursor_prev_run(ME_Cursor *cursor, BOOL all_para)
Definition: run.c:49
BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2)
Definition: run.c:129
void cursor_from_char_ofs(ME_TextEditor *editor, int char_ofs, ME_Cursor *cursor)
Definition: run.c:245
void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
Definition: run.c:753
void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *fmt)
Definition: run.c:782
ME_Run * run_split(ME_TextEditor *editor, ME_Cursor *cursor)
Definition: run.c:310
void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
Definition: run.c:858
void ME_CheckCharOffsets(ME_TextEditor *editor)
Definition: run.c:178
ME_Run * run_next_all_paras(ME_Run *run)
Definition: run.c:96
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, BOOL visual_order)
Definition: run.c:575
void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
Definition: run.c:847
HRESULT WINAPI ScriptXtoCP(int iX, int cChars, int cGlyphs, const WORD *pwLogClust, const SCRIPT_VISATTR *psva, const int *piAdvance, const SCRIPT_ANALYSIS *psa, int *piCP, int *piTrailing)
Definition: usp10.c:2875
HRESULT WINAPI ScriptCPtoX(int iCP, BOOL fTrailing, int cChars, int cGlyphs, const WORD *pwLogClust, const SCRIPT_VISATTR *psva, const int *piAdvance, const SCRIPT_ANALYSIS *psa, int *piX)
Definition: usp10.c:2671
#define assert(x)
Definition: debug.h:53
BOOL ME_InsertString(ME_String *s, int ofs, const WCHAR *insert, int len)
Definition: string.c:103
BOOL add_undo_delete_run(ME_TextEditor *, int pos, int len)
Definition: undo.c:204
void ME_AddRefStyle(ME_Style *item)
Definition: style.c:454
void ME_Remove(ME_DisplayItem *diWhere)
Definition: list.c:35
ME_Style * style_get_insert_style(ME_TextEditor *editor, ME_Cursor *cursor)
Definition: style.c:476
void ME_ReleaseStyle(ME_Style *item)
Definition: style.c:462
void ME_DestroyString(ME_String *s)
Definition: string.c:96
void ME_CopyCharFormat(CHARFORMAT2W *pDest, const CHARFORMAT2W *pSrc)
Definition: style.c:230
ME_Style * ME_ApplyStyle(ME_TextEditor *ed, ME_Style *sSrc, CHARFORMAT2W *style)
Definition: style.c:156
void para_mark_remove(ME_TextEditor *editor, ME_Paragraph *para)
Definition: para.c:94
int ME_twips2pointsX(const ME_Context *c, int x)
Definition: paint.c:171
static ME_DisplayItem * run_get_di(ME_Run *run)
Definition: editor.h:162
void ME_DumpDocument(ME_TextBuffer *buffer)
Definition: list.c:142
void para_mark_add(ME_TextEditor *editor, ME_Paragraph *para)
Definition: para.c:99
#define ITextHost_TxGetDC(This)
Definition: editor.h:332
static int ME_IsWSpace(WCHAR ch)
Definition: editor.h:98
void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize)
Definition: richole.c:5708
ME_DisplayItem * ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass)
Definition: list.c:89
#define ITextHost_TxReleaseDC(This, a)
Definition: editor.h:333
void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat)
Definition: list.c:26
void para_mark_rewrap(ME_TextEditor *editor, ME_Paragraph *para)
Definition: para.c:26
void select_style(ME_Context *c, ME_Style *s)
Definition: style.c:369
ME_Run * para_first_run(ME_Paragraph *para)
Definition: para.c:104
#define RUN_IS_HIDDEN(run)
Definition: editor.h:29
ME_String * ME_MakeStringR(WCHAR cRepeat, int nMaxChars)
Definition: string.c:85
static WCHAR * get_text(const ME_Run *run, int offset)
Definition: editor.h:41
void ME_DestroyDisplayItem(ME_DisplayItem *item)
Definition: list.c:115
ME_Paragraph * para_next(ME_Paragraph *para)
Definition: para.c:57
ME_DisplayItem * ME_MakeDI(ME_DIType type)
Definition: list.c:133
BOOL add_undo_set_char_fmt(ME_TextEditor *, int pos, int len, const CHARFORMAT2W *fmt)
Definition: undo.c:164
static const char * debugstr_run(const ME_Run *run)
Definition: editor.h:46
#define MERF_STARTWHITE
Definition: editstr.h:114
#define MERF_TAB
Definition: editstr.h:105
#define MERF_NOTEXT
Definition: editstr.h:131
#define MERF_ENDPARA
Definition: editstr.h:120
#define MERF_NONTEXT
Definition: editstr.h:109
#define MERF_ENDWHITE
Definition: editstr.h:116
#define MERF_HIDDEN
Definition: editstr.h:124
#define MERF_ENDCELL
Definition: editstr.h:107
#define MERF_GRAPHICS
Definition: editstr.h:103
#define MEPF_COMPLEX
Definition: editstr.h:144
@ diTextEnd
Definition: editstr.h:87
@ diRunOrParagraphOrEnd
Definition: editstr.h:95
@ diCell
Definition: editstr.h:84
@ diRun
Definition: editstr.h:85
@ diTextStart
Definition: editstr.h:82
@ diParagraph
Definition: editstr.h:83
#define MERF_SPLITTABLE
Definition: editstr.h:112
#define MERF_STYLEFLAGS
Definition: editstr.h:101
#define MERF_TABLESTART
Definition: editstr.h:126
#define MEPF_REWRAP
Definition: editstr.h:139
#define MERF_SPLITMASK
Definition: editstr.h:134
#define MERF_WHITESPACE
Definition: editstr.h:118
#define MERF_NOJOIN
Definition: editstr.h:129
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
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 c
Definition: ke_i.h:80
POINT cp
Definition: magnifier.c:59
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:88
static ATOM item
Definition: dde.c:856
#define shift
Definition: input.c:1755
#define min(a, b)
Definition: monoChain.cc:55
#define L(x)
Definition: ntvdm.h:50
_Out_opt_ int * cx
Definition: commctrl.h:585
static unsigned __int64 next
Definition: rand_nt.c:6
#define CFM_PROTECTED
Definition: richedit.h:336
#define CFM_STRIKEOUT
Definition: richedit.h:335
#define CFE_AUTOCOLOR
Definition: richedit.h:414
#define PFM_TABLE
Definition: richedit.h:870
#define CFM_ITALIC
Definition: richedit.h:333
#define lDefaultTab
Definition: richedit.h:215
#define CFM_LINK
Definition: richedit.h:337
#define CFM_SIZE
Definition: richedit.h:362
#define PFE_TABLE
Definition: richedit.h:944
#define CFM_BOLD
Definition: richedit.h:332
#define CFM_UNDERLINETYPE
Definition: richedit.h:355
#define CFM_FACE
Definition: richedit.h:360
#define CFM_UNDERLINE
Definition: richedit.h:334
#define CFM_COLOR
Definition: richedit.h:361
#define CFM_SUPERSCRIPT
Definition: richedit.h:349
const WCHAR * str
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
CardRegion * from
Definition: spigame.cpp:19
LONG cx
Definition: kdterminal.h:27
DWORD dwMask
Definition: richedit.h:306
WCHAR szFaceName[LF_FACESIZE]
Definition: richedit.h:313
DWORD dwEffects
Definition: richedit.h:307
BYTE bUnderlineType
Definition: richedit.h:321
LONG yHeight
Definition: richedit.h:308
COLORREF crTextColor
Definition: richedit.h:310
BYTE bPitchAndFamily
Definition: richedit.h:312
DWORD dwMask
Definition: richedit.h:667
LONG dxOffset
Definition: richedit.h:672
LONG rgxTabs[MAX_TAB_STOPS]
Definition: richedit.h:675
SHORT cTabCount
Definition: richedit.h:674
WORD wEffects
Definition: richedit.h:669
struct define * next
Definition: compiler.c:65
Definition: dsound.c:943
int nOffset
Definition: editstr.h:277
ME_Run * run
Definition: editstr.h:276
struct tagME_DisplayItem * prev
Definition: editstr.h:257
struct tagME_DisplayItem * next
Definition: editstr.h:257
struct para_num para_num
Definition: editstr.h:215
PARAFORMAT2 fmt
Definition: editstr.h:204
int num_glyphs
Definition: editstr.h:171
POINT pt
Definition: editstr.h:167
GOFFSET * offsets
Definition: editstr.h:175
int nCharOfs
Definition: editstr.h:162
SCRIPT_VISATTR * vis_attrs
Definition: editstr.h:173
int max_clusters
Definition: editstr.h:176
struct tagME_Paragraph * para
Definition: editstr.h:161
int * advances
Definition: editstr.h:174
WORD * glyphs
Definition: editstr.h:172
ME_Style * style
Definition: editstr.h:160
SCRIPT_ANALYSIS script_analysis
Definition: editstr.h:170
int nWidth
Definition: editstr.h:164
struct re_object * reobj
Definition: editstr.h:168
int max_glyphs
Definition: editstr.h:171
int nFlags
Definition: editstr.h:165
int len
Definition: editstr.h:163
WORD * clusters
Definition: editstr.h:177
WCHAR * szData
Definition: editstr.h:54
CHARFORMAT2W fmt
Definition: editstr.h:71
TEXTMETRICW tm
Definition: editstr.h:74
ME_DisplayItem * pFirst
Definition: editstr.h:268
ME_Style * pDefaultStyle
Definition: editstr.h:270
ME_Style * pCharStyle
Definition: editstr.h:269
ITextHost2 * texthost
Definition: editstr.h:391
ME_Cursor * pCursors
Definition: editstr.h:396
ME_TextBuffer * pBuffer
Definition: editstr.h:395
long x
Definition: polytest.cpp:48
LONG tmAscent
Definition: wingdi.h:2384
LONG tmDescent
Definition: wingdi.h:2385
WORD fLogicalOrder
Definition: usp10.h:144
#define max(a, b)
Definition: svc.c:63
int ret
BOOL WINAPI GetTextExtentExPointW(_In_ HDC hdc, _In_reads_(cchString) LPCWSTR lpszString, _In_ int cchString, _In_ int nMaxExtent, _Out_opt_ LPINT lpnFit, _Out_writes_to_opt_(cchString, *lpnFit) LPINT lpnDx, _Out_ LPSIZE lpSize)
BOOL WINAPI GetTextExtentPoint32W(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpString, _In_ int c, _Out_ LPSIZE psizl)
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185