ReactOS 0.4.16-dev-1537-g4e425b5
wrap.c
Go to the documentation of this file.
1/*
2 * RichEdit - Paragraph wrapping. Don't try to understand it. You've been
3 * warned !
4 *
5 * Copyright 2004 by Krzysztof Foltman
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
27/*
28 * Unsolved problems:
29 *
30 * - center and right align in WordPad omits all spaces at the start, we don't
31 * - objects/images are not handled yet
32 * - no tabs
33 */
34
35typedef struct tagME_WrapContext
36{
40 int nFirstMargin; /* Offset to first line's text, always to the text itself even if a para number is present */
41 int nParaNumOffset; /* Offset to the para number */
42 int nAvailWidth; /* Width avail for text to wrap into. Does not include any para number text */
43 int nRow;
50
52{
53 free( run->glyphs );
54 run->glyphs = malloc( run->max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR) + sizeof(int) + sizeof(GOFFSET)) );
55 if (!run->glyphs) return FALSE;
56
57 run->vis_attrs = (SCRIPT_VISATTR*)((char*)run->glyphs + run->max_glyphs * sizeof(WORD));
58 run->advances = (int*)((char*)run->glyphs + run->max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR)));
59 run->offsets = (GOFFSET*)((char*)run->glyphs + run->max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR) + sizeof(int)));
60
61 return TRUE;
62}
63
65{
66 HRESULT hr;
67 int i;
68
69 if (!run->glyphs)
70 {
71 run->max_glyphs = 1.5 * run->len + 16; /* This is suggested in the uniscribe documentation */
72 run->max_glyphs = (run->max_glyphs + 7) & ~7; /* Keep alignment simple */
74 }
75
76 if (run->max_clusters < run->len)
77 {
78 free( run->clusters );
79 run->max_clusters = run->len * 2;
80 run->clusters = malloc( run->max_clusters * sizeof(WORD) );
81 }
82
83 select_style( c, run->style );
84 while (1)
85 {
86 hr = ScriptShape( c->hDC, &run->style->script_cache, get_text( run, 0 ), run->len, run->max_glyphs,
87 &run->script_analysis, run->glyphs, run->clusters, run->vis_attrs, &run->num_glyphs );
88 if (hr != E_OUTOFMEMORY) break;
89 if (run->max_glyphs > 10 * run->len) break; /* something has clearly gone wrong */
90 run->max_glyphs *= 2;
92 }
93
94 if (SUCCEEDED(hr))
95 hr = ScriptPlace( c->hDC, &run->style->script_cache, run->glyphs, run->num_glyphs, run->vis_attrs,
96 &run->script_analysis, run->advances, run->offsets, NULL );
97
98 if (SUCCEEDED(hr))
99 {
100 for (i = 0, run->nWidth = 0; i < run->num_glyphs; i++)
101 run->nWidth += run->advances[i];
102 }
103
104 return hr;
105}
106
107/******************************************************************************
108 * calc_run_extent
109 *
110 * Updates the size of the run (fills width, ascent and descent). The height
111 * is calculated based on whole row's ascent and descent anyway, so no need
112 * to use it here.
113 */
114static void calc_run_extent(ME_Context *c, const ME_Paragraph *para, int startx, ME_Run *run)
115{
116 if (run->nFlags & MERF_HIDDEN) run->nWidth = 0;
117 else
118 {
119 SIZE size = ME_GetRunSizeCommon( c, para, run, run->len, startx, &run->nAscent, &run->nDescent );
120 run->nWidth = size.cx;
121 }
122}
123
124/******************************************************************************
125 * split_run_extents
126 *
127 * Splits a run into two in a given place. It also updates the screen position
128 * and size (extent) of the newly generated runs.
129 */
130static ME_Run *split_run_extents( ME_WrapContext *wc, ME_Run *run, int nVChar )
131{
132 ME_TextEditor *editor = wc->context->editor;
133 ME_Run *run2;
134 ME_Cursor cursor = { wc->para, run, nVChar };
135
136 assert( run->nCharOfs != -1 );
137 ME_CheckCharOffsets(editor);
138
139 TRACE("Before split: %s(%ld, %ld)\n", debugstr_run( run ),
140 run->pt.x, run->pt.y);
141
142 run_split( editor, &cursor );
143
144 run2 = cursor.run;
145 run2->script_analysis = run->script_analysis;
146
147 shape_run( wc->context, run );
148 shape_run( wc->context, run2 );
149 calc_run_extent(wc->context, wc->para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run);
150
151 run2->pt.x = run->pt.x + run->nWidth;
152 run2->pt.y = run->pt.y;
153
154 ME_CheckCharOffsets(editor);
155
156 TRACE("After split: %s(%ld, %ld), %s(%ld, %ld)\n",
157 debugstr_run( run ), run->pt.x, run->pt.y,
158 debugstr_run( run2 ), run2->pt.x, run2->pt.y);
159
160 return cursor.run;
161}
162
163/******************************************************************************
164 * find_split_point
165 *
166 * Returns a character position to split inside the run given a run-relative
167 * pixel horizontal position. This version rounds left (ie. if the second
168 * character is at pixel position 8, then for cx=0..7 it returns 0).
169 */
170static int find_split_point( ME_Context *c, int cx, ME_Run *run )
171{
172 if (!run->len || cx <= 0) return 0;
173 return ME_CharFromPointContext( c, cx, run, FALSE, FALSE );
174}
175
176static ME_Row *row_create( int height, int baseline, int width )
177{
179
180 item->member.row.nHeight = height;
181 item->member.row.nBaseline = baseline;
182 item->member.row.nWidth = width;
183 return &item->member.row;
184}
185
187{
188 ME_Cell *cell;
189
190 wc->pRowStart = NULL;
191 wc->bOverflown = FALSE;
193 wc->bWordWrap = wc->context->editor->bWordWrap;
194 if (wc->para->nFlags & (MEPF_ROWSTART | MEPF_ROWEND))
195 {
196 wc->nAvailWidth = 0;
197 wc->bWordWrap = FALSE;
198 if (wc->para->nFlags & MEPF_ROWEND)
199 {
200 cell = table_row_end_cell( wc->para );
201 cell->nWidth = 0;
202 }
203 }
204 else if (para_cell( wc->para ))
205 {
206 int width;
207
208 cell = para_cell( wc->para );
209 width = cell->nRightBoundary;
210 if (cell_prev( cell )) width -= cell_prev( cell )->nRightBoundary;
211 else
212 {
213 int rowIndent = table_row_end( wc->para )->fmt.dxStartIndent;
214 width -= rowIndent;
215 }
216 cell->nWidth = max(ME_twips2pointsX(wc->context, width), 0);
217
218 wc->nAvailWidth = cell->nWidth
219 - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin;
220 wc->bWordWrap = TRUE;
221 }
222 else
224 - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin;
225
226 wc->pt.x = wc->context->pt.x;
227 if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
228 para_in_table( wc->para ))
229 /* Shift the text down because of the border. */
230 wc->pt.y++;
231}
232
234{
235 ME_Run *run;
236 int i, num_runs = 0;
237 int buf[16 * 5]; /* 5 arrays - 4 of int & 1 of BYTE, alloc space for 5 of ints */
238 int *vis_to_log = buf, *log_to_vis, *widths, *pos;
239 BYTE *levels;
240 BOOL found_black = FALSE;
241
242 for (run = last; run; run = run_prev( run ))
243 {
244 if (!found_black) found_black = !(run->nFlags & (MERF_WHITESPACE | MERF_ENDPARA));
245 if (found_black) num_runs++;
246 if (run == start) break;
247 }
248
249 TRACE("%d runs\n", num_runs);
250 if (!num_runs) return;
251
252 if (num_runs > ARRAY_SIZE( buf ) / 5)
253 vis_to_log = malloc( num_runs * sizeof(int) * 5 );
254
255 log_to_vis = vis_to_log + num_runs;
256 widths = vis_to_log + 2 * num_runs;
257 pos = vis_to_log + 3 * num_runs;
258 levels = (BYTE*)(vis_to_log + 4 * num_runs);
259
260 for (i = 0, run = start; i < num_runs; run = run_next( run ))
261 {
263 widths[i] = run->nWidth;
264 TRACE( "%d: level %d width %d\n", i, levels[i], widths[i] );
265 i++;
266 }
267
268 ScriptLayout( num_runs, levels, vis_to_log, log_to_vis );
269
270 pos[0] = run->para->pt.x;
271 for (i = 1; i < num_runs; i++)
272 pos[i] = pos[i - 1] + widths[ vis_to_log[ i - 1 ] ];
273
274 for (i = 0, run = start; i < num_runs; run = run_next( run ))
275 {
276 run->pt.x = pos[ log_to_vis[ i ] ];
277 TRACE( "%d: x = %ld\n", i, run->pt.x );
278 i++;
279 }
280
281 if (vis_to_log != buf) free( vis_to_log );
282}
283
285{
286 ME_Run *run;
287 ME_Row *row;
288 BOOL bSkippingSpaces = TRUE;
289 int ascent = 0, descent = 0, width = 0, shift = 0, align = 0;
290
291 /* Include height of para numbering label */
292 if (wc->nRow == 0 && wc->para->fmt.wNumbering)
293 {
294 ascent = wc->para->para_num.style->tm.tmAscent;
295 descent = wc->para->para_num.style->tm.tmDescent;
296 }
297
298 for (run = last; run; run = run_prev( run ))
299 {
300 /* ENDPARA run shouldn't affect row height, except if it's the only run in the paragraph */
301 if (run == wc->pRowStart || !(run->nFlags & MERF_ENDPARA))
302 {
303 if (run->nAscent > ascent) ascent = run->nAscent;
304 if (run->nDescent > descent) descent = run->nDescent;
305 if (bSkippingSpaces)
306 {
307 /* Exclude space characters from run width.
308 * Other whitespace or delimiters are not treated this way. */
309 int len = run->len;
310 WCHAR *text = get_text( run, len - 1 );
311
312 assert(len);
313 if (~run->nFlags & MERF_GRAPHICS)
314 while (len && *(text--) == ' ') len--;
315 if (len)
316 {
317 if (len == run->len)
318 width += run->nWidth;
319 else
321 }
322 bSkippingSpaces = !len;
323 }
324 else if (!(run->nFlags & MERF_ENDPARA))
325 width += run->nWidth;
326 }
327 if (run == wc->pRowStart) break;
328 }
329
330 wc->para->nWidth = max( wc->para->nWidth, width );
331 row = row_create( ascent + descent, ascent, width );
332 if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
333 (wc->para->fmt.dwMask & PFM_TABLE) && (wc->para->fmt.wEffects & PFE_TABLE))
334 {
335 /* The text was shifted down in ME_BeginRow so move the wrap context
336 * back to where it should be. */
337 wc->pt.y--;
338 /* The height of the row is increased by the borders. */
339 row->nHeight += 2;
340 }
341 row->pt = wc->pt;
342 row->nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin);
343 row->nRMargin = wc->nRightMargin;
345 align = wc->para->fmt.wAlignment;
346 if (align == PFA_CENTER) shift = max((wc->nAvailWidth-width)/2, 0);
347 if (align == PFA_RIGHT) shift = max(wc->nAvailWidth-width, 0);
348
349 if (wc->para->nFlags & MEPF_COMPLEX) layout_row( wc->pRowStart, last );
350
351 row->pt.x = row->nLMargin + shift;
352
353 for (run = wc->pRowStart; run; run = run_next( run ))
354 {
355 run->pt.x += row->nLMargin + shift;
356 if (run == last) break;
357 }
358
359 if (wc->nRow == 0 && wc->para->fmt.wNumbering)
360 {
361 wc->para->para_num.pt.x = wc->nParaNumOffset + shift;
362 wc->para->para_num.pt.y = wc->pt.y + row->nBaseline;
363 }
364
366 wc->nRow++;
367 wc->pt.y += row->nHeight;
368 ME_BeginRow( wc );
369}
370
372{
373 if (wc->pRowStart) ME_InsertRowStart( wc, wc->para->eop_run );
374
375 if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
377 {
378 /* ME_BeginRow was called an extra time for the paragraph, and it shifts the
379 * text down by one pixel for the border, so fix up the wrap context. */
380 wc->pt.y--;
381 }
382}
383
384static void ME_WrapSizeRun( ME_WrapContext *wc, ME_Run *run )
385{
386 /* FIXME compose style (out of character and paragraph styles) here */
387
388 ME_UpdateRunFlags( wc->context->editor, run );
389
390 calc_run_extent( wc->context, wc->para,
391 wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run );
392}
393
394
395static int find_non_whitespace(const WCHAR *s, int len, int start)
396{
397 int i;
398 for (i = start; i < len && ME_IsWSpace( s[i] ); i++)
399 ;
400
401 return i;
402}
403
404/* note: these two really return the first matching offset (starting from EOS)+1
405 * in other words, an offset of the first trailing white/black */
406
407/* note: returns offset of the first trailing whitespace */
409{
410 int i;
411 for (i = start; i > 0 && ME_IsWSpace( s[i - 1] ); i--)
412 ;
413
414 return i;
415}
416
417/* note: returns offset of the first trailing nonwhitespace */
418static int reverse_find_whitespace(const WCHAR *s, int start)
419{
420 int i;
421 for (i = start; i > 0 && !ME_IsWSpace( s[i - 1] ); i--)
422 ;
423
424 return i;
425}
426
428{
429 ME_Run *new_run, *iter = run;
430 int j;
431 if (!i)
432 return NULL;
433 j = reverse_find_non_whitespace( get_text( run, 0 ), i );
434 if (j > 0)
435 {
436 new_run = split_run_extents( wc, iter, j );
437 wc->pt.x += iter->nWidth;
438 return new_run;
439 }
440 else
441 {
442 new_run = iter;
443 /* omit all spaces before split point */
444 while (iter != wc->pRowStart)
445 {
446 iter = run_prev( iter );
447 if (iter->nFlags & MERF_WHITESPACE)
448 {
449 new_run = iter;
450 continue;
451 }
452 if (iter->nFlags & MERF_ENDWHITE)
453 {
454 i = reverse_find_non_whitespace( get_text( iter, 0 ), iter->len );
455 new_run = split_run_extents( wc, iter, i );
456 wc->pt = new_run->pt;
457 return new_run;
458 }
459 /* this run is the end of spaces, so the run edge is a good point to split */
460 wc->pt = new_run->pt;
461 wc->bOverflown = TRUE;
462 TRACE( "Split point is: %s|%s\n", debugstr_run( iter ), debugstr_run( new_run ) );
463 return new_run;
464 }
465 wc->pt = iter->pt;
466 return iter;
467 }
468}
469
471{
472 ME_Run *new_run;
473 int i, idesp, len;
474
475 idesp = i = find_split_point( wc->context, loc, run );
476 len = run->len;
477 assert( len > 0 );
478 assert( i < len );
479 if (i)
480 {
481 /* don't split words */
482 i = reverse_find_whitespace( get_text( run, 0 ), i );
483 new_run = ME_MaximizeSplit(wc, run, i);
484 if (new_run) return new_run;
485 }
486 TRACE("Must backtrack to split at: %s\n", debugstr_run( run ));
487 if (wc->pLastSplittableRun)
488 {
490 {
491 wc->pt = wc->pLastSplittableRun->pt;
492 return wc->pLastSplittableRun;
493 }
495 {
496 /* the following two lines are just to check if we forgot to call UpdateRunFlags earlier,
497 they serve no other purpose */
500
501 run = wc->pLastSplittableRun;
502 len = run->len;
503 /* don't split words */
504 i = reverse_find_whitespace( get_text( run, 0 ), len );
505 if (i == len)
507 new_run = split_run_extents(wc, run, i);
508 wc->pt = new_run->pt;
509 return new_run;
510 }
511 else
512 {
513 /* restart from the first run beginning with spaces */
514 wc->pt = wc->pLastSplittableRun->pt;
515 return wc->pLastSplittableRun;
516 }
517 }
518 TRACE("Backtracking failed, trying desperate: %s\n", debugstr_run( run ));
519 /* OK, no better idea, so assume we MAY split words if we can split at all*/
520 if (idesp)
521 return split_run_extents(wc, run, idesp);
522 else
523 if (wc->pRowStart && run != wc->pRowStart)
524 {
525 /* don't need to break current run, because it's possible to split
526 before this run */
527 wc->bOverflown = TRUE;
528 return run;
529 }
530 else
531 {
532 /* split point inside first character - no choice but split after that char */
533 if (len != 1)
534 /* the run is more than 1 char, so we may split */
535 return split_run_extents( wc, run, 1 );
536
537 /* the run is one char, can't split it */
538 return run;
539 }
540}
541
543{
544 ME_Run *new_run;
545 int len;
546
547 if (!wc->pRowStart) wc->pRowStart = run;
548 run->pt.x = wc->pt.x;
549 run->pt.y = wc->pt.y;
550 ME_WrapSizeRun( wc, run );
551 len = run->len;
552
553 if (wc->bOverflown) /* just skipping final whitespaces */
554 {
555 /* End paragraph run can't overflow to the next line by itself. */
556 if (run->nFlags & MERF_ENDPARA) return run_next( run );
557
558 if (run->nFlags & MERF_WHITESPACE)
559 {
560 wc->pt.x += run->nWidth;
561 /* skip runs consisting of only whitespaces */
562 return run_next( run );
563 }
564
565 if (run->nFlags & MERF_STARTWHITE)
566 {
567 /* try to split the run at the first non-white char */
568 int black;
569 black = find_non_whitespace( get_text( run, 0 ), run->len, 0 );
570 if (black)
571 {
572 ME_Run *new_run;
573 wc->bOverflown = FALSE;
574 new_run = split_run_extents( wc, run, black );
575 calc_run_extent( wc->context, wc->para,
576 wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run );
577 ME_InsertRowStart( wc, run );
578 return new_run;
579 }
580 }
581 /* black run: the row goes from pRowStart to the previous run */
582 ME_InsertRowStart( wc, run_prev( run ) );
583 return run;
584 }
585 /* simply end the current row and move on to next one */
586 if (run->nFlags & MERF_ENDROW)
587 {
588 ME_InsertRowStart( wc, run );
589 return run_next( run );
590 }
591
592 /* will current run fit? */
593 if (wc->bWordWrap &&
594 wc->pt.x + run->nWidth - wc->context->pt.x > wc->nAvailWidth)
595 {
596 int loc = wc->context->pt.x + wc->nAvailWidth - wc->pt.x;
597 /* total white run or end para */
598 if (run->nFlags & (MERF_WHITESPACE | MERF_ENDPARA)) {
599 /* let the overflow logic handle it */
600 wc->bOverflown = TRUE;
601 return run;
602 }
603 /* TAB: we can split before */
604 if (run->nFlags & MERF_TAB) {
605 wc->bOverflown = TRUE;
606 if (wc->pRowStart == run)
607 /* Don't split before the start of the run, or we will get an
608 * endless loop. */
609 return run_next( run );
610 else
611 return run;
612 }
613 /* graphics: we can split before, if run's width is smaller than row's width */
614 if ((run->nFlags & MERF_GRAPHICS) && run->nWidth <= wc->nAvailWidth) {
615 wc->bOverflown = TRUE;
616 return run;
617 }
618 /* can we separate out the last spaces ? (to use overflow logic later) */
619 if (run->nFlags & MERF_ENDWHITE)
620 {
621 /* we aren't sure if it's *really* necessary, it's a good start however */
622 int black = reverse_find_non_whitespace( get_text( run, 0 ), len );
623 split_run_extents( wc, run, black );
624 /* handle both parts again */
625 return run;
626 }
627 /* determine the split point by backtracking */
628 new_run = ME_SplitByBacktracking( wc, run, loc );
629 if (new_run == wc->pRowStart)
630 {
631 if (run->nFlags & MERF_STARTWHITE)
632 {
633 /* We had only spaces so far, so we must be on the first line of the
634 * paragraph (or the first line after MERF_ENDROW forced the line
635 * break within the paragraph), since no other lines of the paragraph
636 * start with spaces. */
637
638 /* The lines will only contain spaces, and the rest of the run will
639 * overflow onto the next line. */
640 wc->bOverflown = TRUE;
641 return run;
642 }
643 /* Couldn't split the first run, possible because we have a large font
644 * with a single character that caused an overflow.
645 */
646 wc->pt.x += run->nWidth;
647 return run_next( run );
648 }
649 if (run != new_run) /* found a suitable split point */
650 {
651 wc->bOverflown = TRUE;
652 return new_run;
653 }
654 /* we detected that it's best to split on start of this run */
655 if (wc->bOverflown)
656 return new_run;
657 ERR("failure!\n");
658 /* not found anything - writing over margins is the only option left */
659 }
660 if ((run->nFlags & (MERF_SPLITTABLE | MERF_STARTWHITE))
661 || ((run->nFlags & (MERF_GRAPHICS|MERF_TAB)) && (run != wc->pRowStart)))
662 {
663 wc->pLastSplittableRun = run;
664 }
665 wc->pt.x += run->nWidth;
666 return run_next( run );
667}
668
670{
671 int sp = 0, ls = 0;
672 if (!(para->fmt.dwMask & PFM_LINESPACING)) return 0;
673
674 /* FIXME: how to compute simply the line space in ls ??? */
675 /* FIXME: does line spacing include the line itself ??? */
676 switch (para->fmt.bLineSpacingRule)
677 {
678 case 0: sp = ls; break;
679 case 1: sp = (3 * ls) / 2; break;
680 case 2: sp = 2 * ls; break;
681 case 3: sp = ME_twips2pointsY(c, para->fmt.dyLineSpacing); if (sp < ls) sp = ls; break;
682 case 4: sp = ME_twips2pointsY(c, para->fmt.dyLineSpacing); break;
683 case 5: sp = para->fmt.dyLineSpacing / 20; break;
684 default: FIXME("Unsupported spacing rule value %d\n", para->fmt.bLineSpacingRule);
685 }
686 if (c->editor->nZoomNumerator == 0)
687 return sp;
688 else
689 return sp * c->editor->nZoomNumerator / c->editor->nZoomDenominator;
690}
691
693{
695
696 para->nWidth = 0;
697 /* remove row start items as they will be reinserted by the
698 * paragraph wrapper anyway */
699 editor->total_rows -= para->nRows;
700 para->nRows = 0;
701 for (p = para_get_di( para ); p != para->next_para; p = p->next)
702 {
703 if (p->type == diStartRow)
704 {
705 ME_DisplayItem *pRow = p;
706 p = p->prev;
707 ME_Remove( pRow );
708 ME_DestroyDisplayItem( pRow );
709 }
710 }
711
712 /* join runs that can be joined */
713 for (p = para_get_di( para )->next; p != para->next_para; p = p->next)
714 {
715 assert(p->type != diStartRow); /* should have been deleted above */
716 if (p->type == diRun)
717 {
718 while (p->next->type == diRun && ME_CanJoinRuns( &p->member.run, &p->next->member.run ))
719 run_join( c->editor, &p->member.run );
720 }
721 }
722}
723
725{
726 ME_Run *run;
727 SCRIPT_ITEM buf[16], *items = buf;
728 int items_passed = ARRAY_SIZE( buf ), num_items, cur_item;
730 FALSE, FALSE, 0 };
732 HRESULT hr;
733
734 if (para->fmt.dwMask & PFM_RTLPARA && para->fmt.wEffects & PFE_RTLPARA)
735 state.uBidiLevel = 1;
736
737 TRACE( "Base embedding level %d\n", state.uBidiLevel );
738
739 while (1)
740 {
741 hr = ScriptItemize( para->text->szData, para->text->nLen, items_passed, &control,
742 &state, items, &num_items );
743 if (hr != E_OUTOFMEMORY) break; /* may not be enough items if hr == E_OUTOFMEMORY */
744 if (items_passed > para->text->nLen + 1) break; /* something else has gone wrong */
745 items_passed *= 2;
746 if (items == buf)
747 items = malloc( items_passed * sizeof( *items ) );
748 else
749 items = realloc( items, items_passed * sizeof( *items ) );
750 if (!items) break;
751 }
752 if (FAILED( hr )) goto end;
753
754 if (TRACE_ON( richedit ))
755 {
756 TRACE( "got items:\n" );
757 for (cur_item = 0; cur_item < num_items; cur_item++)
758 {
759 TRACE( "\t%d - %d RTL %d bidi level %d\n", items[cur_item].iCharPos, items[cur_item+1].iCharPos - 1,
760 items[cur_item].a.fRTL, items[cur_item].a.s.uBidiLevel );
761 }
762
763 TRACE( "before splitting runs into ranges\n" );
764 for (run = para_first_run( para ); run; run = run_next( run ))
765 TRACE( "\t%d: %s\n", run->nCharOfs, debugstr_run( run ) );
766 }
767
768 /* split runs into ranges at item boundaries */
769 for (run = para_first_run( para ), cur_item = 0; run; run = run_next( run ))
770 {
771 if (run->nCharOfs == items[cur_item+1].iCharPos) cur_item++;
772
773 items[cur_item].a.fLogicalOrder = TRUE;
774 run->script_analysis = items[cur_item].a;
775
776 if (run->nFlags & MERF_ENDPARA) break; /* don't split eop runs */
777
778 if (run->nCharOfs + run->len > items[cur_item+1].iCharPos)
779 {
780 ME_Cursor cursor = { para, run, items[cur_item + 1].iCharPos - run->nCharOfs };
781 run_split( c->editor, &cursor );
782 }
783 }
784
785 if (TRACE_ON( richedit ))
786 {
787 TRACE( "after splitting into ranges\n" );
788 for (run = para_first_run( para ); run; run = run_next( run ))
789 TRACE( "\t%d: %s\n", run->nCharOfs, debugstr_run( run ) );
790 }
791
792 para->nFlags |= MEPF_COMPLEX;
793
794end:
795 if (items != buf) free( items );
796 return hr;
797}
798
799
801{
802 ME_Run *run;
803 HRESULT hr;
804
805 for (run = para_first_run( para ); run; run = run_next( run ))
806 {
807 hr = shape_run( c, run );
808 if (FAILED( hr ))
809 {
810 para->nFlags &= ~MEPF_COMPLEX;
811 return hr;
812 }
813 }
814 return hr;
815}
816
818{
819 ME_Run *run;
821 int border = 0;
822 int linespace = 0;
823
824 if (!(para->nFlags & MEPF_REWRAP)) return;
825
826 ME_PrepareParagraphForWrapping( editor, c, para );
827
828 /* Calculate paragraph numbering label */
829 para_num_init( c, para );
830
831 /* For now treating all non-password text as complex for better testing */
832 if (!c->editor->password_char /* &&
833 ScriptIsComplex( tp->member.para.text->szData, tp->member.para.text->nLen, SIC_COMPLEX ) == S_OK */)
834 {
835 if (SUCCEEDED( itemize_para( c, para ) ))
836 shape_para( c, para );
837 }
838 else
839 {
840 /* If the user has just converted a normal rich editor with already
841 * existing text into a password input, the text may contain paragraphs
842 * with MEPF_COMPLEX set. Since we don't really shape any paragraphs
843 * here, we need to ensure that the MEPF_COMPLEX flag is unset.
844 */
845 para->nFlags &= ~MEPF_COMPLEX;
846 }
847
848 wc.context = c;
849 wc.para = para;
850 wc.style = NULL;
851 wc.nParaNumOffset = 0;
852 if (para->nFlags & MEPF_ROWEND)
853 wc.nFirstMargin = wc.nLeftMargin = wc.nRightMargin = 0;
854 else
855 {
856 int dxStartIndent = para->fmt.dxStartIndent;
857 if (para_cell( wc.para )) dxStartIndent += table_row_end( para )->fmt.dxOffset;
858
859 wc.nLeftMargin = ME_twips2pointsX( c, dxStartIndent + para->fmt.dxOffset );
860 wc.nFirstMargin = ME_twips2pointsX( c, dxStartIndent );
861 if (para->fmt.wNumbering)
862 {
864 dxStartIndent = max( ME_twips2pointsX(c, para->fmt.wNumberingTab),
865 para->para_num.width );
866 wc.nFirstMargin += dxStartIndent;
867 }
869
870 if (wc.nFirstMargin < 0) wc.nFirstMargin = 0;
871 if (wc.nLeftMargin < 0) wc.nLeftMargin = 0;
872 }
873 if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
874 para->fmt.dwMask & PFM_TABLE && para->fmt.wEffects & PFE_TABLE)
875 {
876 wc.nFirstMargin += ME_twips2pointsX( c, para->fmt.dxOffset * 2 );
877 }
878 wc.nRow = 0;
879 wc.pt.y = 0;
880 if (para->fmt.dwMask & PFM_SPACEBEFORE)
881 wc.pt.y += ME_twips2pointsY( c, para->fmt.dySpaceBefore );
882 if (!(para->fmt.dwMask & PFM_TABLE && para->fmt.wEffects & PFE_TABLE) &&
883 para->fmt.dwMask & PFM_BORDER)
884 {
886 if (para->fmt.wBorders & 1)
887 {
888 wc.nFirstMargin += border;
889 wc.nLeftMargin += border;
890 }
891 if (para->fmt.wBorders & 2) wc.nRightMargin -= border;
892 if (para->fmt.wBorders & 4) wc.pt.y += border;
893 }
894
895 linespace = ME_GetParaLineSpace( c, para );
896
897 ME_BeginRow( &wc );
898 run = para_first_run( para );
899 while (run)
900 {
901 run = ME_WrapHandleRun( &wc, run );
902 if (wc.nRow && run == wc.pRowStart) wc.pt.y += linespace;
903 }
904 ME_WrapEndParagraph( &wc );
905 if (!(para->fmt.dwMask & PFM_TABLE && para->fmt.wEffects & PFE_TABLE) &&
906 (para->fmt.dwMask & PFM_BORDER) && (para->fmt.wBorders & 8))
907 wc.pt.y += border;
908 if (para->fmt.dwMask & PFM_SPACEAFTER)
909 wc.pt.y += ME_twips2pointsY( c, para->fmt.dySpaceAfter );
910
911 para->nFlags &= ~MEPF_REWRAP;
912 para->nHeight = wc.pt.y;
913 para->nRows = wc.nRow;
914 editor->total_rows += wc.nRow;
915}
916
918{
920};
921
922static void update_repaint( ME_Paragraph *para, struct repaint_range *repaint )
923{
924 if (!repaint->start) repaint->start = para;
925 repaint->end = para;
926}
927
928static void adjust_para_y( ME_Paragraph *para, ME_Context *c, struct repaint_range *repaint )
929{
930 ME_Cell *cell;
931
932 if (para->nFlags & MEPF_ROWSTART)
933 {
934 ME_Paragraph *end_row_para = table_row_end( para );
935 int borderWidth = 0;
936
937 cell = table_row_first_cell( para );
938 cell->pt = c->pt;
939 /* Offset the text by the largest top border width. */
940 while (cell_next( cell ))
941 {
942 borderWidth = max( borderWidth, cell->border.top.width );
943 cell = cell_next( cell );
944 }
945 if (borderWidth > 0)
946 {
947 borderWidth = max(ME_twips2pointsY(c, borderWidth), 1);
948 while (cell)
949 {
950 cell->yTextOffset = borderWidth;
951 cell = cell_prev( cell );
952 }
953 c->pt.y += borderWidth;
954 }
955 if (end_row_para->fmt.dxStartIndent > 0)
956 {
957 cell = table_row_first_cell( para );
958 cell->pt.x += ME_twips2pointsX( c, end_row_para->fmt.dxStartIndent );
959 c->pt.x = cell->pt.x;
960 }
961 }
962 else if (para->nFlags & MEPF_ROWEND)
963 {
964 /* Set all the cells to the height of the largest cell */
965 ME_Paragraph *start_row_para = table_row_start( para );
966 int prevHeight, nHeight, bottomBorder = 0;
967
968 cell = table_row_end_cell( para );
969 para->nWidth = cell->pt.x + cell->nWidth;
970 if (!(para_next( para )->nFlags & MEPF_ROWSTART))
971 {
972 /* Last row, the bottom border is added to the height. */
973 while ((cell = cell_prev( cell )))
974 bottomBorder = max( bottomBorder, cell->border.bottom.width );
975
976 bottomBorder = ME_twips2pointsY(c, bottomBorder);
977 cell = table_row_end_cell( para );
978 }
979 prevHeight = cell->nHeight;
980 nHeight = cell_prev( cell )->nHeight + bottomBorder;
981 cell->nHeight = nHeight;
982 para->nHeight = nHeight;
983 while (cell_prev( cell ))
984 {
985 cell = cell_prev( cell );
986 cell->nHeight = nHeight;
987 }
988
989 /* Also set the height of the start row paragraph */
990 start_row_para->nHeight = nHeight;
991 c->pt.x = start_row_para->pt.x;
992 c->pt.y = cell->pt.y + nHeight;
993 if (prevHeight < nHeight)
994 {
995 /* The height of the cells has grown, so invalidate the bottom of
996 * the cells. */
997 update_repaint( para, repaint );
998 cell = cell_prev( table_row_end_cell( para ) );
999 while (cell)
1000 {
1001 update_repaint( cell_end_para( cell ), repaint );
1002 cell = cell_prev( cell );
1003 }
1004 }
1005 }
1006 else if ((cell = para_cell( para )) && para == cell_end_para( cell ))
1007 {
1008 /* The next paragraph is in the next cell in the table row. */
1009 cell->nHeight = c->pt.y + para->nHeight - cell->pt.y;
1010
1011 /* Propagate the largest height to the end so that it can be easily
1012 * sent back to all the cells at the end of the row. */
1013 if (cell_prev( cell ))
1014 cell->nHeight = max( cell->nHeight, cell_prev( cell )->nHeight );
1015
1016 c->pt.x = cell->pt.x + cell->nWidth;
1017 c->pt.y = cell->pt.y;
1018 cell_next( cell )->pt = c->pt;
1019 if (!(para_next( para )->nFlags & MEPF_ROWEND))
1020 c->pt.y += cell->yTextOffset;
1021 }
1022 else
1023 {
1024 if ((cell = para_cell( para ))) /* Next paragraph in the same cell. */
1025 c->pt.x = cell->pt.x;
1026 else /* Normal paragraph */
1027 c->pt.x = 0;
1028 c->pt.y += para->nHeight;
1029 }
1030}
1031
1033{
1034 ME_Paragraph *para, *next;
1035 struct wine_rb_entry *entry, *next_entry = NULL;
1036 ME_Context c;
1037 int totalWidth = editor->nTotalWidth, prev_width;
1038 struct repaint_range repaint = { NULL, NULL };
1039
1040 if (!editor->marked_paras.root) return FALSE;
1041
1042 ME_InitContext( &c, editor, hdc );
1043
1044 entry = rb_head( editor->marked_paras.root );
1045 while (entry)
1046 {
1047 para = WINE_RB_ENTRY_VALUE( entry, ME_Paragraph, marked_entry );
1048
1049 /* If the first entry lies inside a table, go back to the start
1050 of the table to ensure cell heights are kept in sync. */
1051 if (!next_entry && para_in_table( para ) && para != table_outer_para( para ))
1052 {
1053 para = table_outer_para( para );
1054 next_entry = entry;
1055 }
1056 else
1057 next_entry = rb_next( entry );
1058
1059 c.pt = para->pt;
1060 prev_width = para->nWidth;
1061 ME_WrapTextParagraph( editor, &c, para );
1062 if (prev_width == totalWidth && para->nWidth < totalWidth)
1063 totalWidth = get_total_width(editor);
1064 else
1065 totalWidth = max(totalWidth, para->nWidth);
1066
1067 update_repaint( para, &repaint );
1068 adjust_para_y( para, &c, &repaint );
1069
1070 if (para_next( para ))
1071 {
1072 if (c.pt.x != para_next( para )->pt.x || c.pt.y != para_next( para )->pt.y ||
1073 para_in_table( para ))
1074 {
1075 next = para;
1076 while (para_next( next ) && &next->marked_entry != next_entry &&
1077 next != &editor->pBuffer->pLast->member.para)
1078 {
1079 update_repaint( para_next( next ), &repaint );
1080 para_next( next )->pt = c.pt;
1081 adjust_para_y( para_next( next ), &c, &repaint );
1082 next = para_next( next );
1083 }
1084 }
1085 }
1086 entry = next_entry;
1087 }
1088 wine_rb_destroy( &editor->marked_paras, NULL, NULL );
1089
1090 editor->sizeWindow.cx = c.rcView.right-c.rcView.left;
1091 editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top;
1092
1093 editor->nTotalLength = editor->pBuffer->pLast->member.para.pt.y;
1094 editor->nTotalWidth = totalWidth;
1095
1097
1098 if (invalidate && (repaint.start || editor->nTotalLength < editor->nLastTotalLength))
1099 para_range_invalidate( editor, repaint.start, repaint.end);
1100 return !!repaint.start;
1101}
1102
1104{
1105 HDC hdc = ITextHost_TxGetDC( editor->texthost );
1106 BOOL ret = wrap_marked_paras_dc( editor, hdc, TRUE );
1108 return ret;
1109}
1110
1112 ME_Paragraph *last_para )
1113{
1114 RECT rc;
1115 int ofs;
1116
1117 rc = editor->rcFormat;
1118 ofs = editor->vert_si.nPos;
1119
1120 if (start_para)
1121 {
1122 start_para = table_outer_para( start_para );
1123 last_para = table_outer_para( last_para );
1124 rc.top += start_para->pt.y - ofs;
1125 } else {
1126 rc.top += editor->nTotalLength - ofs;
1127 }
1128 if (editor->nTotalLength < editor->nLastTotalLength)
1129 rc.bottom = editor->rcFormat.top + editor->nLastTotalLength - ofs;
1130 else
1131 rc.bottom = editor->rcFormat.top + last_para->pt.y + last_para->nHeight - ofs;
1133}
1134
1135
1136void
1138{
1139 if (editor->nEventMask & ENM_REQUESTRESIZE)
1140 {
1141 RECT rc;
1142
1143 ITextHost_TxGetClientRect(editor->texthost, &rc);
1144
1145 if (force || rc.bottom != editor->nTotalLength)
1146 {
1148
1149 info.nmhdr.hwndFrom = NULL;
1150 info.nmhdr.idFrom = 0;
1151 info.nmhdr.code = EN_REQUESTRESIZE;
1152 info.rc = rc;
1153 info.rc.right = editor->nTotalWidth;
1154 info.rc.bottom = editor->nTotalLength;
1155
1156 editor->nEventMask &= ~ENM_REQUESTRESIZE;
1157 ITextHost_TxNotify(editor->texthost, info.nmhdr.code, &info);
1158 editor->nEventMask |= ENM_REQUESTRESIZE;
1159 }
1160 }
1161}
static int state
Definition: maze.c:121
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
void ls(int argc, const char *argv[])
Definition: cmds.c:1136
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define TRACE_ON(x)
Definition: compat.h:75
const WCHAR * text
Definition: package.c:1794
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
HRESULT WINAPI ScriptPlace(HDC hdc, SCRIPT_CACHE *psc, const WORD *pwGlyphs, int cGlyphs, const SCRIPT_VISATTR *psva, SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC)
Definition: usp10.c:3531
HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItems, const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, int *pcItems)
Definition: usp10.c:1853
HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, int cChars, int cMaxGlyphs, SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, WORD *pwLogClust, SCRIPT_VISATTR *psva, int *pcGlyphs)
Definition: usp10.c:3342
HRESULT WINAPI ScriptLayout(int runs, const BYTE *level, int *vistolog, int *logtovis)
Definition: usp10.c:3773
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
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define assert(x)
Definition: debug.h:53
#define pt(x, y)
Definition: drawing.c:79
return ret
Definition: mutex.c:146
struct rb_node * rb_next(struct rb_node *)
Definition: rbtree.c:320
int align(int length, int align)
Definition: dsound8.c:36
int ME_twips2pointsY(const ME_Context *c, int y)
Definition: paint.c:179
ME_Run * run_next(ME_Run *run)
Definition: run.c:68
void ME_Remove(ME_DisplayItem *diWhere)
Definition: list.c:35
ME_Cell * table_row_end_cell(ME_Paragraph *para)
Definition: table.c:178
int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order)
Definition: run.c:613
#define ITextHost_TxInvalidateRect(This, a, b)
Definition: editor.h:338
ME_Cell * cell_next(ME_Cell *cell)
Definition: table.c:192
int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BOOL visual_order)
Definition: run.c:516
int ME_GetParaBorderWidth(const ME_Context *c, int flags)
Definition: paint.c:541
ME_Cell * cell_prev(ME_Cell *cell)
Definition: table.c:197
static ME_DisplayItem * para_get_di(ME_Paragraph *para)
Definition: editor.h:236
ME_Run * run_prev(ME_Run *run)
Definition: run.c:82
void para_num_init(ME_Context *c, ME_Paragraph *para)
Definition: para.c:390
void run_join(ME_TextEditor *editor, ME_Run *run)
Definition: run.c:278
#define ITextHost_TxNotify(This, a, b)
Definition: editor.h:367
void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run)
Definition: run.c:467
int ME_twips2pointsX(const ME_Context *c, int x)
Definition: paint.c:171
ME_Paragraph * table_outer_para(ME_Paragraph *para)
Definition: table.c:158
ME_Cell * table_row_first_cell(ME_Paragraph *para)
Definition: table.c:170
ME_Cell * para_cell(ME_Paragraph *para)
Definition: para.c:127
static ME_DisplayItem * run_get_di(ME_Run *run)
Definition: editor.h:162
ME_Paragraph * table_row_end(ME_Paragraph *para)
Definition: table.c:127
#define ITextHost_TxGetClientRect(This, a)
Definition: editor.h:353
#define ITextHost_TxGetDC(This)
Definition: editor.h:332
static int ME_IsWSpace(WCHAR ch)
Definition: editor.h:98
static ME_DisplayItem * row_get_di(ME_Row *row)
Definition: editor.h:125
BOOL para_in_table(ME_Paragraph *para)
Definition: para.c:122
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
#define ITextHost_TxReleaseDC(This, a)
Definition: editor.h:333
void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat)
Definition: list.c:26
int get_total_width(ME_TextEditor *editor)
Definition: para.c:69
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
BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2)
Definition: run.c:129
ME_Paragraph * table_row_start(ME_Paragraph *para)
Definition: table.c:142
ME_Paragraph * cell_end_para(ME_Cell *cell)
Definition: table.c:207
ME_Run * run_split(ME_TextEditor *editor, ME_Cursor *cursor)
Definition: run.c:310
static WCHAR * get_text(const ME_Run *run, int offset)
Definition: editor.h:41
void ME_DestroyDisplayItem(ME_DisplayItem *item)
Definition: list.c:115
void ME_CheckCharOffsets(ME_TextEditor *editor)
Definition: run.c:178
ME_Paragraph * para_next(ME_Paragraph *para)
Definition: para.c:57
ME_DisplayItem * ME_MakeDI(ME_DIType type)
Definition: list.c:133
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_ENDPARA
Definition: editstr.h:120
#define MERF_ENDWHITE
Definition: editstr.h:116
#define MERF_HIDDEN
Definition: editstr.h:124
#define MERF_GRAPHICS
Definition: editstr.h:103
#define MEPF_ROWSTART
Definition: editstr.h:142
#define MEPF_ROWEND
Definition: editstr.h:143
#define MEPF_COMPLEX
Definition: editstr.h:144
@ diStartRow
Definition: editstr.h:86
@ diRun
Definition: editstr.h:85
#define MERF_SPLITTABLE
Definition: editstr.h:112
#define MEPF_REWRAP
Definition: editstr.h:139
#define MERF_ENDROW
Definition: editstr.h:122
#define MERF_WHITESPACE
Definition: editstr.h:118
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned short WORD
Definition: ntddk_ex.h:93
GLint GLint GLsizei GLsizei GLsizei GLint border
Definition: gl.h:1546
GLuint start
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLsizei levels
Definition: glext.h:7884
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
const char cursor[]
Definition: icontest.c:13
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define c
Definition: ke_i.h:80
if(dx< 0)
Definition: linetemp.h:194
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:88
static UINT UINT last
Definition: font.c:45
static const WCHAR sp[]
Definition: suminfo.c:287
#define shift
Definition: input.c:1755
static TCHAR * items[]
Definition: page1.c:45
_Out_opt_ int * cx
Definition: commctrl.h:585
static unsigned __int64 next
Definition: rand_nt.c:6
#define PFM_SPACEBEFORE
Definition: richedit.h:847
#define PFA_RIGHT
Definition: richedit.h:922
#define PFA_CENTER
Definition: richedit.h:923
#define PFE_RTLPARA
Definition: richedit.h:932
#define PFM_LINESPACING
Definition: richedit.h:849
#define EN_REQUESTRESIZE
Definition: richedit.h:192
#define PFM_TABLE
Definition: richedit.h:870
#define PFE_TABLE
Definition: richedit.h:944
#define PFM_BORDER
Definition: richedit.h:851
#define PFM_ALIGNMENT
Definition: richedit.h:841
#define PFM_RTLPARA
Definition: richedit.h:856
#define PFM_SPACEAFTER
Definition: richedit.h:848
#define ENM_REQUESTRESIZE
Definition: richedit.h:477
#define wine_rb_entry
Definition: rbtree.h:404
#define WINE_RB_ENTRY_VALUE
Definition: rbtree.h:414
static struct rb_entry * rb_head(struct rb_entry *iter)
Definition: rbtree.h:97
#define wine_rb_destroy
Definition: rbtree.h:408
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
LONG dySpaceBefore
Definition: richedit.h:676
BYTE bLineSpacingRule
Definition: richedit.h:678
WORD wAlignment
Definition: richedit.h:673
LONG dxRightIndent
Definition: richedit.h:671
DWORD dwMask
Definition: richedit.h:667
LONG dyLineSpacing
Definition: richedit.h:676
LONG dySpaceAfter
Definition: richedit.h:676
LONG dxOffset
Definition: richedit.h:672
WORD wBorders
Definition: richedit.h:681
WORD wNumbering
Definition: richedit.h:668
WORD wEffects
Definition: richedit.h:669
LONG dxStartIndent
Definition: richedit.h:670
WORD wNumberingTab
Definition: richedit.h:680
Definition: dialog.c:52
ME_Paragraph * start
Definition: wrap.c:919
ME_Paragraph * end
Definition: wrap.c:919
ME_Border bottom
Definition: editstr.h:190
ME_Border top
Definition: editstr.h:188
POINT pt
Definition: editstr.h:226
int nHeight
Definition: editstr.h:227
int nRightBoundary
Definition: editstr.h:224
ME_BorderRect border
Definition: editstr.h:225
int yTextOffset
Definition: editstr.h:228
int nWidth
Definition: editstr.h:227
int nAvailWidth
Definition: editstr.h:469
POINT pt
Definition: editstr.h:466
ME_TextEditor * editor
Definition: editstr.h:474
union tagME_DisplayItem::@595 member
ME_Paragraph para
Definition: editstr.h:262
struct tagME_DisplayItem * next_para
Definition: editstr.h:217
struct para_num para_num
Definition: editstr.h:215
ME_String * text
Definition: editstr.h:205
PARAFORMAT2 fmt
Definition: editstr.h:204
ME_Run * eop_run
Definition: editstr.h:216
int nAscent
Definition: editstr.h:166
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
int nDescent
Definition: editstr.h:166
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
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
int nLen
Definition: editstr.h:55
SCRIPT_CACHE script_cache
Definition: editstr.h:76
ME_DisplayItem * pLast
Definition: editstr.h:268
SCROLLINFO vert_si
Definition: editstr.h:449
ITextHost2 * texthost
Definition: editstr.h:391
ME_TextBuffer * pBuffer
Definition: editstr.h:395
struct wine_rb_tree marked_paras
Definition: editstr.h:460
unsigned int bEmulateVersion10
Definition: editstr.h:392
int nLastTotalLength
Definition: editstr.h:404
int nLeftMargin
Definition: wrap.c:39
int nAvailWidth
Definition: wrap.c:42
int nRightMargin
Definition: wrap.c:39
int nFirstMargin
Definition: wrap.c:40
ME_Style * style
Definition: wrap.c:37
int nParaNumOffset
Definition: wrap.c:41
ME_Run * pRowStart
Definition: wrap.c:47
ME_Paragraph * para
Definition: wrap.c:46
POINT pt
Definition: wrap.c:44
BOOL bOverflown
Definition: wrap.c:45
ME_Context * context
Definition: wrap.c:38
BOOL bWordWrap
Definition: wrap.c:45
ME_Run * pLastSplittableRun
Definition: wrap.c:48
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
SCRIPT_STATE s
Definition: usp10.h:146
WORD uBidiLevel
Definition: usp10.h:125
#define max(a, b)
Definition: svc.c:63
static void invalidate()
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50
static int ME_GetParaLineSpace(ME_Context *c, ME_Paragraph *para)
Definition: wrap.c:669
static void calc_run_extent(ME_Context *c, const ME_Paragraph *para, int startx, ME_Run *run)
Definition: wrap.c:114
static HRESULT shape_para(ME_Context *c, ME_Paragraph *para)
Definition: wrap.c:800
static ME_Row * row_create(int height, int baseline, int width)
Definition: wrap.c:176
static void ME_WrapTextParagraph(ME_TextEditor *editor, ME_Context *c, ME_Paragraph *para)
Definition: wrap.c:817
static HRESULT itemize_para(ME_Context *c, ME_Paragraph *para)
Definition: wrap.c:724
static int reverse_find_whitespace(const WCHAR *s, int start)
Definition: wrap.c:418
static ME_Run * ME_MaximizeSplit(ME_WrapContext *wc, ME_Run *run, int i)
Definition: wrap.c:427
static int reverse_find_non_whitespace(const WCHAR *s, int start)
Definition: wrap.c:408
static void layout_row(ME_Run *start, ME_Run *last)
Definition: wrap.c:233
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
Definition: wrap.c:1103
static void ME_PrepareParagraphForWrapping(ME_TextEditor *editor, ME_Context *c, ME_Paragraph *para)
Definition: wrap.c:692
void ME_SendRequestResize(ME_TextEditor *editor, BOOL force)
Definition: wrap.c:1137
static void update_repaint(ME_Paragraph *para, struct repaint_range *repaint)
Definition: wrap.c:922
static ME_Run * ME_SplitByBacktracking(ME_WrapContext *wc, ME_Run *run, int loc)
Definition: wrap.c:470
static ME_Run * split_run_extents(ME_WrapContext *wc, ME_Run *run, int nVChar)
Definition: wrap.c:130
static void ME_WrapEndParagraph(ME_WrapContext *wc)
Definition: wrap.c:371
BOOL wrap_marked_paras_dc(ME_TextEditor *editor, HDC hdc, BOOL invalidate)
Definition: wrap.c:1032
static HRESULT shape_run(ME_Context *c, ME_Run *run)
Definition: wrap.c:64
static void ME_InsertRowStart(ME_WrapContext *wc, ME_Run *last)
Definition: wrap.c:284
static BOOL get_run_glyph_buffers(ME_Run *run)
Definition: wrap.c:51
void para_range_invalidate(ME_TextEditor *editor, ME_Paragraph *start_para, ME_Paragraph *last_para)
Definition: wrap.c:1111
static void ME_WrapSizeRun(ME_WrapContext *wc, ME_Run *run)
Definition: wrap.c:384
static ME_Run * ME_WrapHandleRun(ME_WrapContext *wc, ME_Run *run)
Definition: wrap.c:542
static void adjust_para_y(ME_Paragraph *para, ME_Context *c, struct repaint_range *repaint)
Definition: wrap.c:928
struct tagME_WrapContext ME_WrapContext
static int find_non_whitespace(const WCHAR *s, int len, int start)
Definition: wrap.c:395
static void ME_BeginRow(ME_WrapContext *wc)
Definition: wrap.c:186
static int find_split_point(ME_Context *c, int cx, ME_Run *run)
Definition: wrap.c:170
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193