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