/****************************************************************************** * ME_SplitRunSimple * * Does the most basic job of splitting a run into two - it does not * update the positions and extents. */ ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor) { ME_DisplayItem *run = cursor->pRun; ME_DisplayItem *new_run; int i; int nOffset = cursor->nOffset; assert(!(run->member.run.nFlags & MERF_NONTEXT)); new_run = ME_MakeRun(run->member.run.style, run->member.run.nFlags & MERF_SPLITMASK); new_run->member.run.nCharOfs = run->member.run.nCharOfs + nOffset; new_run->member.run.len = run->member.run.len - nOffset; new_run->member.run.para = run->member.run.para; run->member.run.len = nOffset; cursor->pRun = new_run; cursor->nOffset = 0; ME_InsertBefore(run->next, new_run); ME_UpdateRunFlags(editor, &run->member.run); ME_UpdateRunFlags(editor, &new_run->member.run); for (i = 0; i < editor->nCursors; i++) { if (editor->pCursors[i].pRun == run && editor->pCursors[i].nOffset >= nOffset) { editor->pCursors[i].pRun = new_run; editor->pCursors[i].nOffset -= nOffset; } } cursor->pPara->member.para.nFlags |= MEPF_REWRAP; return run; }
/****************************************************************************** * ME_JoinRuns * * Merges two adjacent runs, the one given as a parameter and the next one. */ void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) { ME_DisplayItem *pNext = p->next; int i; assert(p->type == diRun && pNext->type == diRun); assert(p->member.run.nCharOfs != -1); ME_GetParagraph(p)->member.para.nFlags |= MEPF_REWRAP; /* Update all cursors so that they don't contain the soon deleted run */ for (i=0; i<editor->nCursors; i++) { if (editor->pCursors[i].pRun == pNext) { editor->pCursors[i].pRun = p; editor->pCursors[i].nOffset += p->member.run.len; } } p->member.run.len += pNext->member.run.len; ME_Remove(pNext); ME_DestroyDisplayItem(pNext); ME_UpdateRunFlags(editor, &p->member.run); if(TRACE_ON(richedit)) { TRACE("Before check after join\n"); ME_CheckCharOffsets(editor); TRACE("After check after join\n"); } }
static void ME_WrapSizeRun(ME_WrapContext *wc, ME_DisplayItem *p) { /* FIXME compose style (out of character and paragraph styles) here */ ME_UpdateRunFlags(wc->context->editor, &p->member.run); calc_run_extent(wc->context, &wc->pPara->member.para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, &p->member.run); }
static ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, int loc) { ME_DisplayItem *piter = p, *pp; int i, idesp, len; ME_Run *run = &p->member.run; idesp = i = find_split_point( wc->context, loc, run ); len = run->len; assert(len>0); assert(i<len); if (i) { /* don't split words */ i = reverse_find_whitespace( get_text( run, 0 ), i ); pp = ME_MaximizeSplit(wc, p, i); if (pp) return pp; } TRACE("Must backtrack to split at: %s\n", debugstr_run( &p->member.run )); if (wc->pLastSplittableRun) { if (wc->pLastSplittableRun->member.run.nFlags & (MERF_GRAPHICS|MERF_TAB)) { wc->pt = wc->pLastSplittableRun->member.run.pt; return wc->pLastSplittableRun; } else if (wc->pLastSplittableRun->member.run.nFlags & MERF_SPLITTABLE) { /* the following two lines are just to check if we forgot to call UpdateRunFlags earlier, they serve no other purpose */ ME_UpdateRunFlags(wc->context->editor, run); assert((wc->pLastSplittableRun->member.run.nFlags & MERF_SPLITTABLE)); piter = wc->pLastSplittableRun; run = &piter->member.run; len = run->len; /* don't split words */ i = reverse_find_whitespace( get_text( run, 0 ), len ); if (i == len) i = reverse_find_non_whitespace( get_text( run, 0 ), len ); if (i) { ME_DisplayItem *piter2 = split_run_extents(wc, piter, i); wc->pt = piter2->member.run.pt; return piter2; } /* splittable = must have whitespaces */ assert(0 == "Splittable, but no whitespaces"); } else { /* restart from the first run beginning with spaces */ wc->pt = wc->pLastSplittableRun->member.run.pt; return wc->pLastSplittableRun; } } TRACE("Backtracking failed, trying desperate: %s\n", debugstr_run( &p->member.run )); /* OK, no better idea, so assume we MAY split words if we can split at all*/ if (idesp) return split_run_extents(wc, piter, idesp); else if (wc->pRowStart && piter != wc->pRowStart) { /* don't need to break current run, because it's possible to split before this run */ wc->bOverflown = TRUE; return piter; } else { /* split point inside first character - no choice but split after that char */ if (len != 1) { /* the run is more than 1 char, so we may split */ return split_run_extents(wc, piter, 1); } /* the run is one char, can't split it */ return piter; } }