ReactOS 0.4.16-dev-981-g80eb313
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 para->nCharOfs += shift;
164 para = para_next( para );
165 } while (para);
166}
167
168/******************************************************************************
169 * ME_CheckCharOffsets
170 *
171 * Checks if editor lists' validity and optionally dumps the document structure
172 */
174{
175 ME_DisplayItem *p = editor->pBuffer->pFirst;
176 int ofs = 0, ofsp = 0;
177
178 if (!TRACE_ON(richedit_check))
179 return;
180
181 TRACE_(richedit_check)("Checking begin\n");
182 if(TRACE_ON(richedit_lists))
183 {
184 TRACE_(richedit_lists)("---\n");
185 ME_DumpDocument(editor->pBuffer);
186 }
187 do {
189 switch(p->type) {
190 case diTextEnd:
191 TRACE_(richedit_check)("tend, real ofsp = %d, counted = %d\n", p->member.para.nCharOfs, ofsp+ofs);
192 assert(ofsp+ofs == p->member.para.nCharOfs);
193 TRACE_(richedit_check)("Checking finished\n");
194 return;
195 case diParagraph:
196 TRACE_(richedit_check)("para, real ofsp = %d, counted = %d\n", p->member.para.nCharOfs, ofsp+ofs);
197 assert(ofsp+ofs == p->member.para.nCharOfs);
198 ofsp = p->member.para.nCharOfs;
199 ofs = 0;
200 break;
201 case diRun:
202 TRACE_(richedit_check)("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = %s, flags=%08x, fx&mask = %08x\n",
203 p->member.run.nCharOfs, p->member.run.nCharOfs+ofsp, ofsp+ofs,
204 p->member.run.len, debugstr_run( &p->member.run ),
205 p->member.run.nFlags,
206 p->member.run.style->fmt.dwMask & p->member.run.style->fmt.dwEffects);
207 assert(ofs == p->member.run.nCharOfs);
208 assert(p->member.run.len);
209 ofs += p->member.run.len;
210 break;
211 case diCell:
212 TRACE_(richedit_check)("cell\n");
213 break;
214 default:
215 assert(0);
216 }
217 } while(1);
218 TRACE_(richedit_check)("Checking finished\n");
219}
220
221/******************************************************************************
222 * run_char_ofs
223 *
224 * Converts a character position relative to the start of the run to a
225 * character position relative to the start of the document.
226 */
227
228int run_char_ofs( ME_Run *run, int ofs )
229{
230 return run->para->nCharOfs + run->nCharOfs + ofs;
231}
232
233/******************************************************************************
234 * cursor_from_char_ofs
235 *
236 * Converts a character offset (relative to the start of the document) to
237 * a cursor structure (which contains a run and a position relative to that
238 * run).
239 */
240void cursor_from_char_ofs( ME_TextEditor *editor, int char_ofs, ME_Cursor *cursor )
241{
242 ME_Paragraph *para;
243 ME_Run *run;
244
245 char_ofs = min( max( char_ofs, 0 ), ME_GetTextLength( editor ) );
246
247 /* Find the paragraph at the offset. */
248 for (para = editor_first_para( editor );
249 para_next( para )->nCharOfs <= char_ofs;
250 para = para_next( para ))
251 ;
252
253 char_ofs -= para->nCharOfs;
254
255 /* Find the run at the offset. */
256 for (run = para_first_run( para );
257 run_next( run ) && run_next( run )->nCharOfs <= char_ofs;
258 run = run_next( run ))
259 ;
260
261 char_ofs -= run->nCharOfs;
262
263 cursor->para = para;
264 cursor->run = run;
265 cursor->nOffset = char_ofs;
266}
267
268/******************************************************************************
269 * run_join
270 *
271 * Merges two adjacent runs, the one given as a parameter and the next one.
272 */
273void run_join( ME_TextEditor *editor, ME_Run *run )
274{
275 ME_Run *next = run_next( run );
276 int i;
277
278 assert( run );
279 assert( run->nCharOfs != -1 );
280 para_mark_rewrap( editor, run->para );
281
282 /* Update all cursors so that they don't contain the soon deleted run */
283 for (i = 0; i < editor->nCursors; i++)
284 {
285 if (editor->pCursors[i].run == next)
286 {
287 editor->pCursors[i].run = run;
288 editor->pCursors[i].nOffset += run->len;
289 }
290 }
291
292 run->len += next->len;
295 ME_UpdateRunFlags( editor, run );
296 ME_CheckCharOffsets( editor );
297}
298
299/******************************************************************************
300 * run_split
301 *
302 * Does the most basic job of splitting a run into two - it does not
303 * update the positions and extents.
304 */
306{
307 ME_Run *run = cursor->run, *new_run;
308 int i;
309 int nOffset = cursor->nOffset;
310
311 assert( !(run->nFlags & MERF_NONTEXT) );
312
313 new_run = run_create( run->style, run->nFlags & MERF_SPLITMASK );
314 new_run->nCharOfs = run->nCharOfs + nOffset;
315 new_run->len = run->len - nOffset;
316 new_run->para = run->para;
317 run->len = nOffset;
318 cursor->run = new_run;
319 cursor->nOffset = 0;
320
321 ME_InsertBefore( run_get_di( run )->next, run_get_di( new_run ) );
322
323 ME_UpdateRunFlags( editor, run );
324 ME_UpdateRunFlags( editor, new_run );
325 for (i = 0; i < editor->nCursors; i++)
326 {
327 if (editor->pCursors[i].run == run &&
328 editor->pCursors[i].nOffset >= nOffset)
329 {
330 editor->pCursors[i].run = new_run;
331 editor->pCursors[i].nOffset -= nOffset;
332 }
333 }
334 para_mark_rewrap( editor, run->para );
335 return run;
336}
337
338/******************************************************************************
339 * run_create
340 *
341 * A helper function to create run structures quickly.
342 */
344{
346 ME_Run *run = &item->member.run;
347
348 if (!item) return NULL;
349
350 ME_AddRefStyle( s );
351 run->style = s;
352 run->reobj = NULL;
353 run->nFlags = flags;
354 run->nCharOfs = -1;
355 run->len = 0;
356 run->para = NULL;
357 run->num_glyphs = 0;
358 run->max_glyphs = 0;
359 run->glyphs = NULL;
360 run->vis_attrs = NULL;
361 run->advances = NULL;
362 run->offsets = NULL;
363 run->max_clusters = 0;
364 run->clusters = NULL;
365 return run;
366}
367
368/******************************************************************************
369 * run_insert
370 *
371 * Inserts a new run with given style, flags and content at a given position,
372 * which is passed as a cursor structure (which consists of a run and
373 * a run-relative character offset).
374 */
376 const WCHAR *str, int len, int flags )
377{
378 ME_Run *insert_before = cursor->run, *run, *prev;
379
380 if (cursor->nOffset)
381 {
382 if (cursor->nOffset == insert_before->len)
383 {
384 insert_before = run_next_all_paras( insert_before );
385 if (!insert_before) insert_before = cursor->run; /* Always insert before the final eop run */
386 }
387 else
388 {
389 run_split( editor, cursor );
390 insert_before = cursor->run;
391 }
392 }
393
394 add_undo_delete_run( editor, insert_before->para->nCharOfs + insert_before->nCharOfs, len );
395
396 run = run_create( style, flags );
397 run->nCharOfs = insert_before->nCharOfs;
398 run->len = len;
399 run->para = insert_before->para;
400 ME_InsertString( run->para->text, run->nCharOfs, str, len );
401 ME_InsertBefore( run_get_di( insert_before ), run_get_di( run ) );
402 TRACE("Shift length:%d\n", len);
403 editor_propagate_char_ofs( NULL, insert_before, len );
404 para_mark_rewrap( editor, insert_before->para );
405
406 /* Move any cursors that were at the end of the previous run to the end of the inserted run */
407 prev = run_prev_all_paras( run );
408 if (prev)
409 {
410 int i;
411
412 for (i = 0; i < editor->nCursors; i++)
413 {
414 if (editor->pCursors[i].run == prev &&
415 editor->pCursors[i].nOffset == prev->len)
416 {
417 editor->pCursors[i].run = run;
418 editor->pCursors[i].nOffset = len;
419 }
420 }
421 }
422
423 return run;
424}
425
426static BOOL run_is_splittable( const ME_Run *run )
427{
428 WCHAR *str = get_text( run, 0 ), *p;
429 int i;
430 BOOL found_ink = FALSE;
431
432 for (i = 0, p = str; i < run->len; i++, p++)
433 {
434 if (ME_IsWSpace( *p ))
435 {
436 if (found_ink) return TRUE;
437 }
438 else
439 found_ink = TRUE;
440 }
441 return FALSE;
442}
443
444static BOOL run_is_entirely_ws( const ME_Run *run )
445{
446 WCHAR *str = get_text( run, 0 ), *p;
447 int i;
448
449 for (i = 0, p = str; i < run->len; i++, p++)
450 if (!ME_IsWSpace( *p )) return FALSE;
451
452 return TRUE;
453}
454
455/******************************************************************************
456 * ME_UpdateRunFlags
457 *
458 * Determine some of run attributes given its content (style, text content).
459 * Some flags cannot be determined by this function (MERF_GRAPHICS,
460 * MERF_ENDPARA)
461 */
463{
464 assert(run->nCharOfs >= 0);
465
466 if (RUN_IS_HIDDEN(run) || run->nFlags & MERF_TABLESTART)
467 run->nFlags |= MERF_HIDDEN;
468 else
469 run->nFlags &= ~MERF_HIDDEN;
470
471 if (run_is_splittable( run ))
472 run->nFlags |= MERF_SPLITTABLE;
473 else
474 run->nFlags &= ~MERF_SPLITTABLE;
475
476 if (!(run->nFlags & MERF_NOTEXT))
477 {
478 if (run_is_entirely_ws( run ))
480 else
481 {
482 run->nFlags &= ~MERF_WHITESPACE;
483
484 if (ME_IsWSpace( *get_text( run, 0 ) ))
485 run->nFlags |= MERF_STARTWHITE;
486 else
487 run->nFlags &= ~MERF_STARTWHITE;
488
489 if (ME_IsWSpace( *get_text( run, run->len - 1 ) ))
490 run->nFlags |= MERF_ENDWHITE;
491 else
492 run->nFlags &= ~MERF_ENDWHITE;
493 }
494 }
495 else
497}
498
499/******************************************************************************
500 * ME_CharFromPointContext
501 *
502 * Returns a character position inside the run given a run-relative
503 * pixel horizontal position.
504 *
505 * If closest is FALSE return the actual character
506 * If closest is TRUE will round to the closest leading edge.
507 * ie. if the second character is at pixel position 8 and third at 16 then for:
508 * closest = FALSE cx = 0..7 return 0, cx = 8..15 return 1
509 * closest = TRUE cx = 0..3 return 0, cx = 4..11 return 1.
510 */
511int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BOOL visual_order)
512{
513 ME_String *mask_text = NULL;
514 WCHAR *str;
515 int fit = 0;
516 SIZE sz, sz2, sz3;
517 if (!run->len || cx <= 0)
518 return 0;
519
520 if (run->nFlags & (MERF_TAB | MERF_ENDCELL))
521 {
522 if (!closest || cx < run->nWidth / 2) return 0;
523 return 1;
524 }
525
526 if (run->nFlags & MERF_GRAPHICS)
527 {
528 SIZE sz;
529 ME_GetOLEObjectSize(c, run, &sz);
530 if (!closest || cx < sz.cx / 2) return 0;
531 return 1;
532 }
533
534 if (run->para->nFlags & MEPF_COMPLEX)
535 {
536 int cp, trailing;
537 if (visual_order && run->script_analysis.fRTL) cx = run->nWidth - cx - 1;
538
539 ScriptXtoCP( cx, run->len, run->num_glyphs, run->clusters, run->vis_attrs, run->advances, &run->script_analysis,
540 &cp, &trailing );
541 TRACE("x %d cp %d trailing %d (run width %d) rtl %d log order %d\n", cx, cp, trailing, run->nWidth,
543 return closest ? cp + trailing : cp;
544 }
545
546 if (c->editor->password_char)
547 {
548 mask_text = ME_MakeStringR( c->editor->password_char, run->len );
549 str = mask_text->szData;
550 }
551 else
552 str = get_text( run, 0 );
553
554 select_style(c, run->style);
555 GetTextExtentExPointW(c->hDC, str, run->len,
556 cx, &fit, NULL, &sz);
557 if (closest && fit != run->len)
558 {
559 GetTextExtentPoint32W(c->hDC, str, fit, &sz2);
560 GetTextExtentPoint32W(c->hDC, str, fit + 1, &sz3);
561 if (cx >= (sz2.cx+sz3.cx)/2)
562 fit = fit + 1;
563 }
564
565 ME_DestroyString( mask_text );
566
567 return fit;
568}
569
570int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, BOOL visual_order)
571{
573 int ret;
574 HDC hdc = ITextHost_TxGetDC( editor->texthost );
575
576 ME_InitContext( &c, editor, hdc );
577 ret = ME_CharFromPointContext( &c, cx, run, closest, visual_order );
580 return ret;
581}
582
583/******************************************************************************
584 * ME_GetTextExtent
585 *
586 * Finds a width and a height of the text using a specified style
587 */
588static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size)
589{
590 if (c->hDC)
591 {
592 select_style( c, s );
593 GetTextExtentPoint32W( c->hDC, szText, nChars, size );
594 }
595 else
596 {
597 size->cx = 0;
598 size->cy = 0;
599 }
600}
601
602/******************************************************************************
603 * ME_PointFromCharContext
604 *
605 * Returns a run-relative pixel position given a run-relative character
606 * position (character offset)
607 */
608int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order)
609{
610 SIZE size;
611 ME_String *mask_text = NULL;
612 WCHAR *str;
613
614 if (pRun->nFlags & MERF_GRAPHICS)
615 {
616 if (nOffset)
617 ME_GetOLEObjectSize(c, pRun, &size);
618 return nOffset != 0;
619 } else if (pRun->nFlags & MERF_ENDPARA) {
620 nOffset = 0;
621 }
622
623 if (pRun->para->nFlags & MEPF_COMPLEX)
624 {
625 int x;
626 ScriptCPtoX( nOffset, FALSE, pRun->len, pRun->num_glyphs, pRun->clusters,
627 pRun->vis_attrs, pRun->advances, &pRun->script_analysis, &x );
628 if (visual_order && pRun->script_analysis.fRTL) x = pRun->nWidth - x - 1;
629 return x;
630 }
631 if (c->editor->password_char)
632 {
633 mask_text = ME_MakeStringR( c->editor->password_char, pRun->len );
634 str = mask_text->szData;
635 }
636 else
637 str = get_text( pRun, 0 );
638
639 ME_GetTextExtent(c, str, nOffset, pRun->style, &size);
640 ME_DestroyString( mask_text );
641 return size.cx;
642}
643
644/******************************************************************************
645 * ME_PointFromChar
646 *
647 * Calls ME_PointFromCharContext after first creating a context.
648 */
649int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visual_order)
650{
652 int ret;
653 HDC hdc = ITextHost_TxGetDC( editor->texthost );
654
655 ME_InitContext( &c, editor, hdc );
656 ret = ME_PointFromCharContext( &c, pRun, nOffset, visual_order );
659
660 return ret;
661}
662
663/******************************************************************************
664 * ME_GetRunSizeCommon
665 *
666 * Finds width, height, ascent and descent of a run, up to given character
667 * (nLen).
668 */
670 int startx, int *pAscent, int *pDescent)
671{
672 SIZE size;
673
674 nLen = min( nLen, run->len );
675
676 if (run->nFlags & MERF_ENDPARA)
677 {
678 nLen = min( nLen, 1 );
679 ME_GetTextExtent( c, L" ", nLen, run->style, &size );
680 }
681 else if (para->nFlags & MEPF_COMPLEX)
682 {
683 size.cx = run->nWidth;
684 }
685 else if (c->editor->password_char)
686 {
687 ME_String *szMasked = ME_MakeStringR( c->editor->password_char, nLen );
688 ME_GetTextExtent(c, szMasked->szData, nLen,run->style, &size);
689 ME_DestroyString(szMasked);
690 }
691 else
692 {
693 ME_GetTextExtent(c, get_text( run, 0 ), nLen, run->style, &size);
694 }
695 *pAscent = run->style->tm.tmAscent;
696 *pDescent = run->style->tm.tmDescent;
697 size.cy = *pAscent + *pDescent;
698
699 if (run->nFlags & MERF_TAB)
700 {
701 int pos = 0, i = 0, ppos, shift = 0;
702 const PARAFORMAT2 *pFmt = &para->fmt;
703
704 if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
705 pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
706 /* The horizontal gap shifts the tab positions to leave the gap. */
707 shift = pFmt->dxOffset * 2;
708 do {
709 if (i < pFmt->cTabCount)
710 {
711 /* Only one side of the horizontal gap is needed at the end of
712 * the table row. */
713 if (i == pFmt->cTabCount -1)
714 shift = shift >> 1;
715 pos = shift + (pFmt->rgxTabs[i]&0x00FFFFFF);
716 i++;
717 }
718 else
719 {
721 }
722 ppos = ME_twips2pointsX(c, pos);
723 if (ppos > startx + run->pt.x) {
724 size.cx = ppos - startx - run->pt.x;
725 break;
726 }
727 } while(1);
728 size.cy = *pAscent + *pDescent;
729 return size;
730 }
731 if (run->nFlags & MERF_GRAPHICS)
732 {
733 ME_GetOLEObjectSize(c, run, &size);
734 if (size.cy > *pAscent)
735 *pAscent = size.cy;
736 /* descent is unchanged */
737 return size;
738 }
739 return size;
740}
741
742/******************************************************************************
743 * ME_SetSelectionCharFormat
744 *
745 * Applies a style change, either to a current selection, or to insert cursor
746 * (ie. the style next typed characters will use).
747 */
749{
750 if (!ME_IsSelection(editor))
751 {
752 ME_Style *s;
753 if (!editor->pBuffer->pCharStyle)
754 editor->pBuffer->pCharStyle = style_get_insert_style( editor, editor->pCursors );
755 s = ME_ApplyStyle(editor, editor->pBuffer->pCharStyle, pFmt);
757 editor->pBuffer->pCharStyle = s;
758 } else {
759 ME_Cursor *from, *to;
760 ME_GetSelection(editor, &from, &to);
761 ME_SetCharFormat(editor, from, to, pFmt);
762 }
763}
764
765/******************************************************************************
766 * ME_SetCharFormat
767 *
768 * Applies a style change to the specified part of the text
769 *
770 * The start and end cursors specify the part of the text. These cursors will
771 * be updated to stay valid, but this function may invalidate other
772 * non-selection cursors. The end cursor may be NULL to specify all the text
773 * following the start cursor.
774 *
775 * If no text is selected, then nothing is done.
776 */
778{
779 ME_Run *run, *start_run = start->run, *end_run = NULL;
780
781 if (end && start->run == end->run && start->nOffset == end->nOffset)
782 return;
783
784 if (start->nOffset == start->run->len)
785 start_run = run_next_all_paras( start->run );
786 else if (start->nOffset)
787 {
788 /* run_split() may or may not update the cursors, depending on whether they
789 * are selection cursors, but we need to make sure they are valid. */
790 int split_offset = start->nOffset;
791 ME_Run *split_run = run_split( editor, start );
792 start_run = start->run;
793 if (end && end->run == split_run)
794 {
795 end->run = start->run;
796 end->nOffset -= split_offset;
797 }
798 }
799
800 if (end)
801 {
802 if (end->nOffset == end->run->len)
803 end_run = run_next_all_paras( end->run );
804 else
805 {
806 if (end->nOffset) run_split( editor, end );
807 end_run = end->run;
808 }
809 }
810
811 for (run = start_run; run != end_run; run = run_next_all_paras( run ))
812 {
813 ME_Style *new_style = ME_ApplyStyle( editor, run->style, fmt );
814 ME_Paragraph *para = run->para;
815
816 add_undo_set_char_fmt( editor, para->nCharOfs + run->nCharOfs,
817 run->len, &run->style->fmt );
818 ME_ReleaseStyle( run->style );
819 run->style = new_style;
820
821 /* The para numbering style depends on the eop style */
822 if ((run->nFlags & MERF_ENDPARA) && para->para_num.style)
823 {
824 ME_ReleaseStyle(para->para_num.style);
825 para->para_num.style = NULL;
826 }
827 para_mark_rewrap( editor, para );
828 }
829}
830
832{
833 ME_CopyCharFormat( fmt, &run->style->fmt );
834}
835
836/******************************************************************************
837 * ME_GetDefaultCharFormat
838 *
839 * Retrieves the current default character style (the one applied where no
840 * other style was applied) .
841 */
843{
844 ME_CopyCharFormat(pFmt, &editor->pBuffer->pDefaultStyle->fmt);
845}
846
847/******************************************************************************
848 * ME_GetSelectionCharFormat
849 *
850 * If selection exists, it returns all style elements that are set consistently
851 * in the whole selection. If not, it just returns the current style.
852 */
854{
855 ME_Cursor *from, *to;
856 if (!ME_IsSelection(editor) && editor->pBuffer->pCharStyle)
857 {
858 ME_CopyCharFormat(pFmt, &editor->pBuffer->pCharStyle->fmt);
859 return;
860 }
861 ME_GetSelection(editor, &from, &to);
862 ME_GetCharFormat(editor, from, to, pFmt);
863}
864
865/******************************************************************************
866 * ME_GetCharFormat
867 *
868 * Returns the style consisting of those attributes which are consistently set
869 * in the whole character range.
870 */
872 const ME_Cursor *to, CHARFORMAT2W *fmt )
873{
874 ME_Run *run, *run_end, *prev_run;
875 CHARFORMAT2W tmp;
876
877 run = from->run;
878 /* special case - if selection is empty, take previous char's formatting */
879 if (from->run == to->run && from->nOffset == to->nOffset)
880 {
881 if (!from->nOffset && (prev_run = run_prev( run ))) run = prev_run;
882 run_copy_char_fmt( run, fmt );
883 return;
884 }
885
886 run_end = to->run;
887 if (!to->nOffset) run_end = run_prev_all_paras( run_end );
888
889 run_copy_char_fmt( run, fmt );
890
891 if (run == run_end) return;
892
893 do {
894 /* FIXME add more style feature comparisons */
897
898 run = run_next_all_paras( run );
899
900 memset( &tmp, 0, sizeof(tmp) );
901 tmp.cbSize = sizeof(tmp);
902 run_copy_char_fmt( run, &tmp );
903
904 assert((tmp.dwMask & dwAttribs) == dwAttribs);
905 /* reset flags that differ */
906
907 if (fmt->yHeight != tmp.yHeight) fmt->dwMask &= ~CFM_SIZE;
908 if (fmt->dwMask & CFM_FACE)
909 {
910 if (!(tmp.dwMask & CFM_FACE))
911 fmt->dwMask &= ~CFM_FACE;
912 else if (wcscmp( fmt->szFaceName, tmp.szFaceName ) ||
913 fmt->bPitchAndFamily != tmp.bPitchAndFamily)
914 fmt->dwMask &= ~CFM_FACE;
915 }
916 if (fmt->yHeight != tmp.yHeight) fmt->dwMask &= ~CFM_SIZE;
917 if (fmt->bUnderlineType != tmp.bUnderlineType) fmt->dwMask &= ~CFM_UNDERLINETYPE;
918 if (fmt->dwMask & CFM_COLOR)
919 {
920 if (!((fmt->dwEffects&CFE_AUTOCOLOR) & (tmp.dwEffects&CFE_AUTOCOLOR)))
921 {
922 if (fmt->crTextColor != tmp.crTextColor)
923 fmt->dwMask &= ~CFM_COLOR;
924 }
925 }
926
927 fmt->dwMask &= ~((fmt->dwEffects ^ tmp.dwEffects) & dwEffects);
928 fmt->dwEffects = tmp.dwEffects;
929
930 } while(run != run_end);
931}
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:1400
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:279
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:608
static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size)
Definition: run.c:588
int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BOOL visual_order)
Definition: run.c:511
static BOOL run_is_splittable(const ME_Run *run)
Definition: run.c:426
int run_char_ofs(ME_Run *run, int ofs)
Definition: run.c:228
BOOL cursor_next_run(ME_Cursor *cursor, BOOL all_para)
Definition: run.c:30
ME_Run * run_insert(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, const WCHAR *str, int len, int flags)
Definition: run.c:375
ME_Run * run_prev(ME_Run *run)
Definition: run.c:82
void run_join(ME_TextEditor *editor, ME_Run *run)
Definition: run.c:273
void ME_GetCharFormat(ME_TextEditor *editor, const ME_Cursor *from, const ME_Cursor *to, CHARFORMAT2W *fmt)
Definition: run.c:871
void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run)
Definition: run.c:462
static void run_copy_char_fmt(ME_Run *run, CHARFORMAT2W *fmt)
Definition: run.c:831
static BOOL run_is_entirely_ws(const ME_Run *run)
Definition: run.c:444
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:649
ME_Run * run_create(ME_Style *s, int flags)
Definition: run.c:343
SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen, int startx, int *pAscent, int *pDescent)
Definition: run.c:669
void editor_propagate_char_ofs(ME_Paragraph *para, ME_Run *run, int shift)
Definition: run.c:147
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:240
void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
Definition: run.c:748
void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *fmt)
Definition: run.c:777
ME_Run * run_split(ME_TextEditor *editor, ME_Cursor *cursor)
Definition: run.c:305
void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
Definition: run.c:853
void ME_CheckCharOffsets(ME_TextEditor *editor)
Definition: run.c:173
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:570
void ME_GetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
Definition: run.c:842
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:2854
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:2650
#define assert(x)
Definition: debug.h:53
void ME_ReleaseStyle(ME_Style *item) DECLSPEC_HIDDEN
Definition: style.c:462
void ME_AddRefStyle(ME_Style *item) DECLSPEC_HIDDEN
Definition: style.c:454
ME_Run * para_first_run(ME_Paragraph *para) DECLSPEC_HIDDEN
Definition: para.c:104
BOOL add_undo_set_char_fmt(ME_TextEditor *, int pos, int len, const CHARFORMAT2W *fmt) DECLSPEC_HIDDEN
Definition: undo.c:164
ME_Style * ME_ApplyStyle(ME_TextEditor *ed, ME_Style *sSrc, CHARFORMAT2W *style) DECLSPEC_HIDDEN
Definition: style.c:156
void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize) DECLSPEC_HIDDEN
Definition: richole.c:5649
void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN
Definition: list.c:115
int ME_twips2pointsX(const ME_Context *c, int x) DECLSPEC_HIDDEN
Definition: paint.c:167
void select_style(ME_Context *c, ME_Style *s) DECLSPEC_HIDDEN
Definition: style.c:369
ME_Style * style_get_insert_style(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN
Definition: style.c:476
void para_mark_rewrap(ME_TextEditor *editor, ME_Paragraph *para) DECLSPEC_HIDDEN
Definition: para.c:26
ME_Paragraph * para_next(ME_Paragraph *para) DECLSPEC_HIDDEN
Definition: para.c:57
static ME_DisplayItem * run_get_di(ME_Run *run)
Definition: editor.h:163
void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN
Definition: list.c:142
#define ITextHost_TxGetDC(This)
Definition: editor.h:333
static int ME_IsWSpace(WCHAR ch)
Definition: editor.h:99
BOOL add_undo_delete_run(ME_TextEditor *, int pos, int len) DECLSPEC_HIDDEN
Definition: undo.c:204
#define ITextHost_TxReleaseDC(This, a)
Definition: editor.h:334
void ME_Remove(ME_DisplayItem *diWhere) DECLSPEC_HIDDEN
Definition: list.c:35
void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat) DECLSPEC_HIDDEN
Definition: list.c:26
#define RUN_IS_HIDDEN(run)
Definition: editor.h:30
void ME_CopyCharFormat(CHARFORMAT2W *pDest, const CHARFORMAT2W *pSrc) DECLSPEC_HIDDEN
Definition: style.c:230
void ME_DestroyString(ME_String *s) DECLSPEC_HIDDEN
Definition: string.c:96
ME_DisplayItem * ME_MakeDI(ME_DIType type) DECLSPEC_HIDDEN
Definition: list.c:133
static WCHAR * get_text(const ME_Run *run, int offset)
Definition: editor.h:42
ME_DisplayItem * ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN
Definition: list.c:89
BOOL ME_InsertString(ME_String *s, int ofs, const WCHAR *insert, int len) DECLSPEC_HIDDEN
Definition: string.c:103
static const char * debugstr_run(const ME_Run *run)
Definition: editor.h:47
ME_String * ME_MakeStringR(WCHAR cRepeat, int nMaxChars) DECLSPEC_HIDDEN
Definition: string.c:85
#define MERF_STARTWHITE
Definition: editstr.h:115
#define MERF_TAB
Definition: editstr.h:106
#define MERF_NOTEXT
Definition: editstr.h:132
#define MERF_ENDPARA
Definition: editstr.h:121
#define MERF_NONTEXT
Definition: editstr.h:110
#define MERF_ENDWHITE
Definition: editstr.h:117
#define MERF_HIDDEN
Definition: editstr.h:125
#define MERF_ENDCELL
Definition: editstr.h:108
#define MERF_GRAPHICS
Definition: editstr.h:104
#define MEPF_COMPLEX
Definition: editstr.h:145
@ diTextEnd
Definition: editstr.h:88
@ diRunOrParagraphOrEnd
Definition: editstr.h:96
@ diCell
Definition: editstr.h:85
@ diRun
Definition: editstr.h:86
@ diTextStart
Definition: editstr.h:83
@ diParagraph
Definition: editstr.h:84
#define MERF_SPLITTABLE
Definition: editstr.h:113
#define MERF_STYLEFLAGS
Definition: editstr.h:102
#define MERF_TABLESTART
Definition: editstr.h:127
#define MERF_SPLITMASK
Definition: editstr.h:135
#define MERF_WHITESPACE
Definition: editstr.h:119
#define MERF_NOJOIN
Definition: editstr.h:130
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:276
ME_Run * run
Definition: editstr.h:275
struct tagME_DisplayItem * prev
Definition: editstr.h:256
struct tagME_DisplayItem * next
Definition: editstr.h:256
struct para_num para_num
Definition: editstr.h:214
PARAFORMAT2 fmt
Definition: editstr.h:203
int num_glyphs
Definition: editstr.h:170
POINT pt
Definition: editstr.h:166
GOFFSET * offsets
Definition: editstr.h:174
int nCharOfs
Definition: editstr.h:161
SCRIPT_VISATTR * vis_attrs
Definition: editstr.h:172
int max_clusters
Definition: editstr.h:175
struct tagME_Paragraph * para
Definition: editstr.h:160
int * advances
Definition: editstr.h:173
WORD * glyphs
Definition: editstr.h:171
ME_Style * style
Definition: editstr.h:159
SCRIPT_ANALYSIS script_analysis
Definition: editstr.h:169
int nWidth
Definition: editstr.h:163
struct re_object * reobj
Definition: editstr.h:167
int max_glyphs
Definition: editstr.h:170
int nFlags
Definition: editstr.h:164
int len
Definition: editstr.h:162
WORD * clusters
Definition: editstr.h:176
WCHAR * szData
Definition: editstr.h:55
CHARFORMAT2W fmt
Definition: editstr.h:72
TEXTMETRICW tm
Definition: editstr.h:75
ME_DisplayItem * pFirst
Definition: editstr.h:267
ME_Style * pDefaultStyle
Definition: editstr.h:269
ME_Style * pCharStyle
Definition: editstr.h:268
ITextHost2 * texthost
Definition: editstr.h:384
ME_Cursor * pCursors
Definition: editstr.h:389
ME_TextBuffer * pBuffer
Definition: editstr.h:388
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