static InfAdoptedSplitOperation*
inf_text_default_delete_operation_transform_split(
  InfTextDeleteOperation* operation,
  guint split_pos,
  guint split_len)
{
  InfTextDefaultDeleteOperationPrivate* priv;
  InfTextChunk* first_chunk;
  InfTextChunk* second_chunk;
  GObject* first;
  GObject* second;
  InfAdoptedSplitOperation* result;

  priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation);

  first_chunk = inf_text_chunk_substring(priv->chunk, 0, split_pos);
  second_chunk = inf_text_chunk_substring(
    priv->chunk,
    split_pos,
    inf_text_chunk_get_length(priv->chunk) - split_pos
  );

  first = g_object_new(
    INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION,
    "position", priv->position,
    "chunk", first_chunk,
    NULL
  );

  second = g_object_new(
    INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION,
    "position", priv->position + split_pos + split_len,
    "chunk", second_chunk,
    NULL
  );

  inf_text_chunk_free(first_chunk);
  inf_text_chunk_free(second_chunk);

  result = inf_adopted_split_operation_new(
    INF_ADOPTED_OPERATION(first),
    INF_ADOPTED_OPERATION(second)
  );

  g_object_unref(first);
  g_object_unref(second);
  return result;
}
static InfAdoptedSplitOperation*
inf_text_remote_delete_operation_transform_split(
  InfTextDeleteOperation* operation,
  guint split_pos,
  guint split_len)
{
  /* Need to split the delete operation and the recon list */
  InfTextRemoteDeleteOperationPrivate* priv;
  InfAdoptedSplitOperation* result;
  GObject* first_operation;
  GObject* second_operation;
  InfTextRemoteDeleteOperationPrivate* result_priv;
  InfTextRemoteDeleteOperationRecon* recon;
  InfTextRemoteDeleteOperationRecon* new_recon;
  GSList* first_recon;
  GSList* second_recon;
  guint recon_cur_len;
  GSList* item;

  priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation);

  first_recon = NULL;
  second_recon = NULL;
  recon_cur_len = 0;

  for(item = priv->recon; item != NULL; item = g_slist_next(item))
  {
    recon = (InfTextRemoteDeleteOperationRecon*)item->data;

    g_assert(recon->position >= recon_cur_len);
    if(recon->position - recon_cur_len <= split_pos)
    {
      new_recon = g_slice_new(InfTextRemoteDeleteOperationRecon);
      new_recon->position = recon->position;
      new_recon->chunk = inf_text_chunk_copy(recon->chunk);
      first_recon = g_slist_prepend(first_recon, new_recon);

      recon_cur_len += inf_text_chunk_get_length(recon->chunk);
    }
    else
    {
      new_recon = g_slice_new(InfTextRemoteDeleteOperationRecon);
      new_recon->position = recon->position - (split_pos + recon_cur_len);
      new_recon->chunk = inf_text_chunk_copy(recon->chunk);
      second_recon = g_slist_prepend(second_recon, new_recon);
    }
  }

  first_operation = g_object_new(
    INF_TEXT_TYPE_REMOTE_DELETE_OPERATION,
    "position", priv->position,
    "length", split_pos,
    NULL
  );
  
  second_operation = g_object_new(
    INF_TEXT_TYPE_REMOTE_DELETE_OPERATION,
    "position", priv->position + split_len,
    "length", priv->length - split_pos,
    NULL
  );

  result_priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(first_operation);
  result_priv->recon = g_slist_reverse(first_recon);
  result_priv->recon_offset = priv->recon_offset;

  result_priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(second_operation);
  result_priv->recon = g_slist_reverse(second_recon);
  result_priv->recon_offset = priv->recon_offset + split_pos + recon_cur_len;

  result = inf_adopted_split_operation_new(
    INF_ADOPTED_OPERATION(first_operation),
    INF_ADOPTED_OPERATION(second_operation)
  );

  g_object_unref(G_OBJECT(second_operation));
  g_object_unref(G_OBJECT(first_operation));
  return result;
}