예제 #1
0
파일: run.c 프로젝트: mstefani/wine-stable
/******************************************************************************
 * ME_InsertRunAtCursor
 *
 * Inserts a new run with given style, flags and content at a given position,
 * which is passed as a cursor structure (which consists of a run and 
 * a run-relative character offset).
 */
ME_DisplayItem *
ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
                     const WCHAR *str, int len, int flags)
{
  ME_DisplayItem *pDI, *insert_before = cursor->pRun, *prev;

  if (cursor->nOffset)
  {
    if (cursor->nOffset == cursor->pRun->member.run.len)
    {
      insert_before = ME_FindItemFwd( cursor->pRun, diRun );
      if (!insert_before) insert_before = cursor->pRun; /* Always insert before the final eop run */
    }
    else
    {
      ME_SplitRunSimple( editor, cursor );
      insert_before = cursor->pRun;
    }
  }

  add_undo_delete_run( editor, insert_before->member.run.para->nCharOfs +
                       insert_before->member.run.nCharOfs, len );

  pDI = ME_MakeRun(style, flags);
  pDI->member.run.nCharOfs = insert_before->member.run.nCharOfs;
  pDI->member.run.len = len;
  pDI->member.run.para = insert_before->member.run.para;
  ME_InsertString( pDI->member.run.para->text, pDI->member.run.nCharOfs, str, len );
  ME_InsertBefore( insert_before, pDI );
  TRACE("Shift length:%d\n", len);
  ME_PropagateCharOffset( insert_before, len );
  insert_before->member.run.para->nFlags |= MEPF_REWRAP;

  /* Move any cursors that were at the end of the previous run to the end of the inserted run */
  prev = ME_FindItemBack( pDI, diRun );
  if (prev)
  {
    int i;

    for (i = 0; i < editor->nCursors; i++)
    {
      if (editor->pCursors[i].pRun == prev &&
          editor->pCursors[i].nOffset == prev->member.run.len)
      {
        editor->pCursors[i].pRun = pDI;
        editor->pCursors[i].nOffset = len;
      }
    }
  }

  return pDI;
}
예제 #2
0
파일: table.c 프로젝트: AmesianX/wine
static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor,
                                                  int nCursor,
                                                  const WCHAR *eol_str, int eol_len,
                                                  int paraFlags)
{
  ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
  ME_DisplayItem *tp;
  ME_Cursor* cursor = &editor->pCursors[nCursor];
  if (cursor->nOffset)
    ME_SplitRunSimple(editor, cursor);

  tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, eol_str, eol_len, paraFlags);
  ME_ReleaseStyle(pStyle);
  cursor->pPara = tp;
  cursor->pRun = ME_FindItemFwd(tp, diRun);
  return tp;
}
예제 #3
0
static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor,
        int nCursor,
        int numCR,
        int numLF,
        int paraFlags)
{
    ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
    ME_DisplayItem *tp;
    ME_Cursor* cursor = &editor->pCursors[nCursor];
    if (cursor->nOffset) {
        ME_SplitRunSimple(editor, cursor->pRun, cursor->nOffset);
        cursor = &editor->pCursors[nCursor];
    }

    tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, numCR, numLF, paraFlags);
    cursor->pRun = ME_FindItemFwd(tp, diRun);
    return tp;
}
예제 #4
0
파일: wrap.c 프로젝트: Barrell/wine
/******************************************************************************
 * split_run_extents
 *
 * Splits a run into two in a given place. It also updates the screen position
 * and size (extent) of the newly generated runs.
 */
static ME_DisplayItem *split_run_extents(ME_WrapContext *wc, ME_DisplayItem *item, int nVChar)
{
  ME_TextEditor *editor = wc->context->editor;
  ME_Run *run, *run2;
  ME_Paragraph *para = &wc->pPara->member.para;
  ME_Cursor cursor = {wc->pPara, item, nVChar};

  assert(item->member.run.nCharOfs != -1);
  if(TRACE_ON(richedit))
  {
    TRACE("Before check before split\n");
    ME_CheckCharOffsets(editor);
    TRACE("After check before split\n");
  }

  run = &item->member.run;

  TRACE("Before split: %s(%d, %d)\n", debugstr_run( run ),
        run->pt.x, run->pt.y);

  ME_SplitRunSimple(editor, &cursor);

  run2 = &cursor.pRun->member.run;

  calc_run_extent(wc->context, para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run);

  run2->pt.x = run->pt.x+run->nWidth;
  run2->pt.y = run->pt.y;

  if(TRACE_ON(richedit))
  {
    TRACE("Before check after split\n");
    ME_CheckCharOffsets(editor);
    TRACE("After check after split\n");
    TRACE("After split: %s(%d, %d), %s(%d, %d)\n",
      debugstr_run( run ), run->pt.x, run->pt.y,
      debugstr_run( run2 ), run2->pt.x, run2->pt.y);
  }

  return cursor.pRun;
}
예제 #5
0
static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
{
  ME_UndoItem *pUItem = (ME_UndoItem *)pItem;

  if (editor->nUndoMode == umIgnore)
    return;
  TRACE("Playing undo/redo item, id=%s\n", ME_GetDITypeName(pItem->type));

  switch(pItem->type)
  {
  case diUndoPotentialEndTransaction:
  case diUndoEndTransaction:
    assert(0);
  case diUndoSetParagraphFormat:
  {
    ME_Cursor tmp;
    ME_DisplayItem *para;
    ME_CursorFromCharOfs(editor, pItem->member.para.nCharOfs, &tmp);
    para = ME_FindItemBack(tmp.pRun, diParagraph);
    ME_AddUndoItem(editor, diUndoSetParagraphFormat, para);
    *para->member.para.pFmt = *pItem->member.para.pFmt;
    para->member.para.border = pItem->member.para.border;
    break;
  }
  case diUndoSetCharFormat:
  {
    ME_SetCharFormat(editor, pUItem->nStart, pUItem->nLen, &pItem->member.ustyle->fmt);
    break;
  }
  case diUndoInsertRun:
  {
    ME_InsertRun(editor, pItem->member.run.nCharOfs, pItem);
    break;
  }
  case diUndoDeleteRun:
  {
    ME_InternalDeleteText(editor, pUItem->nStart, pUItem->nLen, TRUE);
    break;
  }
  case diUndoJoinParagraphs:
  {
    ME_Cursor tmp;
    ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
    /* the only thing that's needed is paragraph offset, so no need to split runs */
    ME_JoinParagraphs(editor, ME_GetParagraph(tmp.pRun), TRUE);
    break;
  }
  case diUndoSplitParagraph:
  {
    ME_Cursor tmp;
    ME_DisplayItem *this_para, *new_para;
    BOOL bFixRowStart;
    int paraFlags = pItem->member.para.nFlags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND);
    ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
    if (tmp.nOffset)
      tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
    assert(pUItem->nCR >= 0);
    assert(pUItem->nLF >= 0);
    this_para = ME_GetParagraph(tmp.pRun);
    bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART;
    if (bFixRowStart)
    {
      /* Re-insert the paragraph before the table, making sure the nFlag value
       * is correct. */
      this_para->member.para.nFlags &= ~MEPF_ROWSTART;
    }
    new_para = ME_SplitParagraph(editor, tmp.pRun, tmp.pRun->member.run.style,
                                 pUItem->nCR, pUItem->nLF, paraFlags);
    if (bFixRowStart)
      new_para->member.para.nFlags |= MEPF_ROWSTART;
    assert(pItem->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
    *new_para->member.para.pFmt = *pItem->member.para.pFmt;
    new_para->member.para.border = pItem->member.para.border;
    if (pItem->member.para.pCell)
    {
      ME_DisplayItem *pItemCell, *pCell;
      pItemCell = pItem->member.para.pCell;
      pCell = new_para->member.para.pCell;
      pCell->member.cell.nRightBoundary = pItemCell->member.cell.nRightBoundary;
      pCell->member.cell.border = pItemCell->member.cell.border;
    }
    break;
  }
  default:
    assert(0 == "PlayUndoItem, unexpected type");
  }
}
예제 #6
0
파일: wrap.c 프로젝트: Endle/wine-gsoc
static HRESULT itemize_para( ME_Context *c, ME_DisplayItem *p )
{
    ME_Paragraph *para = &p->member.para;
    ME_Run *run;
    ME_DisplayItem *di;
    SCRIPT_ITEM buf[16], *items = buf;
    int items_passed = sizeof( buf ) / sizeof( buf[0] ), num_items, cur_item;
    SCRIPT_CONTROL control = { LANG_USER_DEFAULT, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
                               FALSE, FALSE, 0 };
    SCRIPT_STATE state = { 0, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0 };
    HRESULT hr;

    assert( p->type == diParagraph );

    while (1)
    {
        hr = ScriptItemize( para->text->szData, para->text->nLen, items_passed, &control,
                            &state, items, &num_items );
        if (hr != E_OUTOFMEMORY) break; /* may not be enough items if hr == E_OUTOFMEMORY */
        if (items_passed > para->text->nLen + 1) break; /* something else has gone wrong */
        items_passed *= 2;
        if (items == buf)
            items = heap_alloc( items_passed * sizeof( *items ) );
        else
            items = heap_realloc( items, items_passed * sizeof( *items ) );
        if (!items) break;
    }
    if (FAILED( hr )) goto end;

    if (TRACE_ON( richedit ))
    {
        TRACE( "got items:\n" );
        for (cur_item = 0; cur_item < num_items; cur_item++)
        {
            TRACE( "\t%d - %d RTL %d bidi level %d\n", items[cur_item].iCharPos, items[cur_item+1].iCharPos - 1,
                   items[cur_item].a.fRTL, items[cur_item].a.s.uBidiLevel );
        }

        TRACE( "before splitting runs into ranges\n" );
        for (di = p->next; di != p->member.para.next_para; di = di->next)
        {
            if (di->type != diRun) continue;
            TRACE( "\t%d: %s\n", di->member.run.nCharOfs, debugstr_run( &di->member.run ) );
        }
    }

    /* split runs into ranges at item boundaries */
    for (di = p->next, cur_item = 0; di != p->member.para.next_para; di = di->next)
    {
        if (di->type != diRun) continue;
        run = &di->member.run;

        if (run->nCharOfs == items[cur_item+1].iCharPos) cur_item++;

        items[cur_item].a.fLogicalOrder = TRUE;
        run->script_analysis = items[cur_item].a;

        if (run->nFlags & MERF_ENDPARA) break; /* don't split eop runs */

        if (run->nCharOfs + run->len > items[cur_item+1].iCharPos)
        {
            ME_Cursor cursor = {p, di, items[cur_item+1].iCharPos - run->nCharOfs};
            ME_SplitRunSimple( c->editor, &cursor );
        }
    }

    if (TRACE_ON( richedit ))
    {
        TRACE( "after splitting into ranges\n" );
        for (di = p->next; di != p->member.para.next_para; di = di->next)
        {
            if (di->type != diRun) continue;
            TRACE( "\t%d: %s\n", di->member.run.nCharOfs, debugstr_run( &di->member.run ) );
        }
    }

    para->nFlags |= MEPF_COMPLEX;

end:
    if (items != buf) heap_free( items );
    return hr;
}
예제 #7
0
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, 
  const WCHAR *str, int len, ME_Style *style)
{
  const WCHAR *pos;
  ME_Cursor *p = NULL;
  int oldLen;

  /* FIXME really HERE ? */
  if (ME_IsSelection(editor))
    ME_DeleteSelection(editor);

  /* FIXME: is this too slow? */
  /* Didn't affect performance for WM_SETTEXT (around 50sec/30K) */
  oldLen = ME_GetTextLength(editor);

  /* text operations set modified state */
  editor->nModifyStep = 1;

  assert(style);

  assert(nCursor>=0 && nCursor<editor->nCursors);
  if (len == -1)
    len = lstrlenW(str);

  /* grow the text limit to fit our text */
  if(editor->nTextLimit < oldLen +len)
    editor->nTextLimit = oldLen + len;

  while (len)
  {
    pos = str;
    /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
    while(pos-str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
      pos++;
    if (pos-str < len && *pos == '\t') { /* handle tabs */
      WCHAR tab = '\t';

      if (pos!=str)
        ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
    
      ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
 
      pos++;
      if(pos-str <= len) {
        len -= pos - str;
        str = pos;
        continue;
      }
    }
    /* handle special \r\r\n sequence (richedit 2.x and higher only) */
    if (!editor->bEmulateVersion10 && pos-str < len-2 && pos[0] == '\r' && pos[1] == '\r' && pos[2] == '\n') {
      WCHAR space = ' ';

      if (pos!=str)
        ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);

      ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);

      pos+=3;
      if(pos-str <= len) {
        len -= pos - str;
        str = pos;
        continue;
      }
    }
    if (pos-str < len) {   /* handle EOLs */
      ME_DisplayItem *tp, *end_run;
      ME_Style *tmp_style;
      int numCR, numLF;

      if (pos!=str)
        ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
      p = &editor->pCursors[nCursor];
      if (p->nOffset) {
        ME_SplitRunSimple(editor, p->pRun, p->nOffset);
        p = &editor->pCursors[nCursor];
      }
      tmp_style = ME_GetInsertStyle(editor, nCursor);
      /* ME_SplitParagraph increases style refcount */

      /* Encode and fill number of CR and LF according to emulation mode */
      if (editor->bEmulateVersion10) {
        const WCHAR * tpos;

        /* We have to find out how many consecutive \r are there, and if there
           is a \n terminating the run of \r's. */
        numCR = 0; numLF = 0;
        tpos = pos;
        while (tpos-str < len && *tpos == '\r') {
          tpos++;
          numCR++;
        }
        if (tpos-str >= len) {
          /* Reached end of text without finding anything but '\r' */
          if (tpos != pos) {
            pos++;
          }
          numCR = 1; numLF = 0;
        } else if (*tpos == '\n') {
          /* The entire run of \r's plus the one \n is one single line break */
          pos = tpos + 1;
          numLF = 1;
        } else {
          /* Found some other content past the run of \r's */
          pos++;
          numCR = 1; numLF = 0;
        }
      } else {
        if(pos-str < len && *pos =='\r')
          pos++;
        if(pos-str < len && *pos =='\n')
          pos++;
        numCR = 1; numLF = 0;
      }
      tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF, 0);
      p->pRun = ME_FindItemFwd(tp, diRun);
      end_run = ME_FindItemBack(tp, diRun);
      ME_ReleaseStyle(end_run->member.run.style);
      end_run->member.run.style = tmp_style;
      p->nOffset = 0;

      if(pos-str <= len) {
        len -= pos - str;
        str = pos;
        continue;
      }
    }
    ME_InternalInsertTextFromCursor(editor, nCursor, str, len, style, 0);
    len = 0;
  }
}
예제 #8
0
파일: caret.c 프로젝트: AmesianX/wine
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, 
  const WCHAR *str, int len, ME_Style *style)
{
  const WCHAR *pos;
  ME_Cursor *p = NULL;
  int oldLen;

  /* FIXME really HERE ? */
  if (ME_IsSelection(editor))
    ME_DeleteSelection(editor);

  /* FIXME: is this too slow? */
  /* Didn't affect performance for WM_SETTEXT (around 50sec/30K) */
  oldLen = ME_GetTextLength(editor);

  /* text operations set modified state */
  editor->nModifyStep = 1;

  assert(style);

  assert(nCursor>=0 && nCursor<editor->nCursors);
  if (len == -1)
    len = lstrlenW(str);

  /* grow the text limit to fit our text */
  if(editor->nTextLimit < oldLen +len)
    editor->nTextLimit = oldLen + len;

  pos = str;

  while (len)
  {
    /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
    while(pos - str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
      pos++;

    if (pos != str) { /* handle text */
      ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
    } else if (*pos == '\t') { /* handle tabs */
      WCHAR tab = '\t';
      ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
      pos++;
    } else { /* handle EOLs */
      ME_DisplayItem *tp, *end_run, *run, *prev;
      ME_Style *tmp_style;
      int eol_len = 0;

      /* Find number of CR and LF in end of paragraph run */
      if (*pos =='\r')
      {
        if (len > 1 && pos[1] == '\n')
          eol_len = 2;
        else if (len > 2 && pos[1] == '\r' && pos[2] == '\n')
          eol_len = 3;
        else
          eol_len = 1;
      } else {
        assert(*pos == '\n');
        eol_len = 1;
      }
      pos += eol_len;

      if (!editor->bEmulateVersion10 && eol_len == 3)
      {
        /* handle special \r\r\n sequence (richedit 2.x and higher only) */
        WCHAR space = ' ';
        ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);
      } else {
        const WCHAR cr = '\r', *eol_str = str;

        if (!editor->bEmulateVersion10)
        {
          eol_str = &cr;
          eol_len = 1;
        }

        p = &editor->pCursors[nCursor];

        if (p->nOffset == p->pRun->member.run.len)
        {
           run = ME_FindItemFwd( p->pRun, diRun );
           if (!run) run = p->pRun;
        }
        else
        {
          if (p->nOffset) ME_SplitRunSimple(editor, p);
          run = p->pRun;
        }

        tmp_style = ME_GetInsertStyle(editor, nCursor);
        /* ME_SplitParagraph increases style refcount */
        tp = ME_SplitParagraph(editor, run, run->member.run.style, eol_str, eol_len, 0);

        end_run = ME_FindItemBack(tp, diRun);
        ME_ReleaseStyle(end_run->member.run.style);
        end_run->member.run.style = tmp_style;

        /* Move any cursors that were at the end of the previous run to the beginning of the new para */
        prev = ME_FindItemBack( end_run, diRun );
        if (prev)
        {
          int i;
          for (i = 0; i < editor->nCursors; i++)
          {
            if (editor->pCursors[i].pRun == prev &&
                editor->pCursors[i].nOffset == prev->member.run.len)
            {
              editor->pCursors[i].pPara = tp;
              editor->pCursors[i].pRun = run;
              editor->pCursors[i].nOffset = 0;
            }
          }
        }

      }
    }
    len -= pos - str;
    str = pos;
  }
}
예제 #9
0
static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
{
  ME_UndoItem *pUItem = (ME_UndoItem *)pItem;

  if (editor->nUndoMode == umIgnore)
    return;
  TRACE("Playing undo/redo item, id=%s\n", ME_GetDITypeName(pItem->type));

  switch(pItem->type)
  {
  case diUndoEndTransaction:
    assert(0);
  case diUndoSetParagraphFormat:
  {
    ME_Cursor tmp;
    ME_CursorFromCharOfs(editor, pItem->member.para.nCharOfs, &tmp);
    ME_SetParaFormat(editor, ME_FindItemBack(tmp.pRun, diParagraph), pItem->member.para.pFmt);
    break;
  }
  case diUndoSetCharFormat:
  {
    ME_SetCharFormat(editor, pUItem->nStart, pUItem->nLen, &pItem->member.ustyle->fmt);
    break;
  }
  case diUndoSetDefaultCharFormat:
  {
    ME_SetDefaultCharFormat(editor, &pItem->member.ustyle->fmt);
    break;
  }
  case diUndoInsertRun:
  {
    ME_InsertRun(editor, pItem->member.run.nCharOfs, pItem);
    break;
  }
  case diUndoDeleteRun:
  {
    ME_InternalDeleteText(editor, pUItem->nStart, pUItem->nLen);
    break;
  }
  case diUndoJoinParagraphs:
  {
    ME_Cursor tmp;
    ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
    /* the only thing that's needed is paragraph offset, so no need to split runs */
    ME_JoinParagraphs(editor, ME_GetParagraph(tmp.pRun));
    break;
  }
  case diUndoSplitParagraph:
  {
    ME_Cursor tmp;
    ME_DisplayItem *new_para;
    ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
    if (tmp.nOffset)
      tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
    assert(pUItem->nCR >= 0);
    assert(pUItem->nLF >= 0);
    new_para = ME_SplitParagraph(editor, tmp.pRun, tmp.pRun->member.run.style,
      pUItem->nCR, pUItem->nLF);
    assert(pItem->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
    *new_para->member.para.pFmt = *pItem->member.para.pFmt;
    break;
  }
  default:
    assert(0 == "PlayUndoItem, unexpected type");
  }
}
예제 #10
0
파일: caret.c 프로젝트: NVIDIA/winex_lgpl
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, 
  const WCHAR *str, int len, ME_Style *style)
{
  const WCHAR *pos;
  ME_Cursor *p = NULL;
  /* FIXME: is this too slow? */
  /* Didn't affect performance for WM_SETTEXT (around 50sec/30K) */
  int freeSpace = editor->nTextLimit - ME_GetTextLength(editor);

  /* text operations set modified state */
  editor->nModifyStep = 1;

  assert(style);

  /* FIXME really HERE ? */
  if (ME_IsSelection(editor))
    ME_DeleteSelection(editor);

  assert(nCursor>=0 && nCursor<editor->nCursors);
  if (len == -1)
    len = lstrlenW(str);
  len = min(len, freeSpace);
  while (len)
  {
    pos = str;
    /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
    while(pos-str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
      pos++;
    if (pos-str < len && *pos == '\t') { /* handle tabs */
      WCHAR tab = '\t';

      if (pos!=str)
        ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
    
      ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
 
      pos++;
      if(pos-str <= len) {
        len -= pos - str;
        str = pos;
        continue;
      }
    }
    if (pos-str < len) {   /* handle EOLs */
      ME_DisplayItem *tp, *end_run;
      ME_Style *tmp_style;
      if (pos!=str)
        ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
      p = &editor->pCursors[nCursor];
      if (p->nOffset) {
        ME_SplitRunSimple(editor, p->pRun, p->nOffset);
        p = &editor->pCursors[nCursor];
      }
      tmp_style = ME_GetInsertStyle(editor, nCursor);
      /* ME_SplitParagraph increases style refcount */
      tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style);
      p->pRun = ME_FindItemFwd(tp, diRun);
      end_run = ME_FindItemBack(tp, diRun);
      ME_ReleaseStyle(end_run->member.run.style);
      end_run->member.run.style = tmp_style;
      p->nOffset = 0;
      if(pos-str < len && *pos =='\r')
        pos++;
      if(pos-str < len && *pos =='\n')
        pos++;
      if(pos-str <= len) {
        len -= pos - str;
        str = pos;
        continue;
      }
    }
    ME_InternalInsertTextFromCursor(editor, nCursor, str, len, style, 0);
    len = 0;
  }
}