static InfAdoptedOperation* inf_text_remote_delete_operation_transform(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* operation_lcs, InfAdoptedOperation* against_lcs, InfAdoptedConcurrencyId cid) { g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(operation)); if(INF_TEXT_IS_INSERT_OPERATION(against)) { return inf_text_delete_operation_transform_insert( INF_TEXT_DELETE_OPERATION(operation), INF_TEXT_INSERT_OPERATION(against) ); } else if(INF_TEXT_IS_DELETE_OPERATION(against)) { return inf_text_delete_operation_transform_delete( INF_TEXT_DELETE_OPERATION(operation), INF_TEXT_DELETE_OPERATION(against) ); } else { g_assert_not_reached(); return NULL; } }
static gboolean inf_text_remote_delete_operation_need_concurrency_id( InfAdoptedOperation* operation, InfAdoptedOperation* against) { g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(operation)); return inf_text_delete_operation_need_concurrency_id( INF_TEXT_DELETE_OPERATION(operation), against ); }
static void inf_text_remote_delete_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer) { InfTextRemoteDeleteOperationPrivate* priv; g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(operation)); g_assert(INF_TEXT_IS_BUFFER(buffer)); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); inf_text_buffer_erase_text( INF_TEXT_BUFFER(buffer), priv->position, priv->length, INF_USER(by) ); }
static gboolean inf_text_remote_delete_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfTextRemoteDeleteOperationPrivate* priv; g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(operation)); g_assert(INF_TEXT_IS_BUFFER(buffer)); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); if(priv->position + priv->length > inf_text_buffer_get_length(INF_TEXT_BUFFER(buffer))) { g_set_error( error, g_quark_from_static_string("INF_TEXT_OPERATION_ERROR"), INF_TEXT_OPERATION_ERROR_INVALID_DELETE, "%s", _("Attempt to remove text from after the end of the document") ); return FALSE; } else { inf_text_buffer_erase_text( INF_TEXT_BUFFER(buffer), priv->position, priv->length, INF_USER(by) ); return TRUE; } }
static InfAdoptedOperation* inf_text_remote_delete_operation_apply_transformed(InfAdoptedOperation* op, InfAdoptedOperation* trans, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfTextRemoteDeleteOperationPrivate* priv; InfTextChunk* chunk; InfTextChunk* temp_slice; GSList* list; GSList* item; InfAdoptedOperation* operation; GSList* recon_list; GSList* recon_item; InfTextRemoteDeleteOperationRecon* recon; InfTextDefaultDeleteOperation* result; g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(op)); g_assert(INF_TEXT_IS_BUFFER(buffer)); /* TODO: We can probably optimize this function, but then we should * a) profile it and b) in many cases input parameters to this function * are trivial anyway. */ if(INF_ADOPTED_IS_SPLIT_OPERATION(trans)) { list = inf_adopted_split_operation_unsplit( INF_ADOPTED_SPLIT_OPERATION(trans) ); } else { list = g_slist_prepend(NULL, trans); } chunk = inf_text_chunk_new( inf_text_buffer_get_encoding(INF_TEXT_BUFFER(buffer)) ); /* We assume the list of remote delete operations to be in order */ for(item = list; item != NULL; item = g_slist_next(item)) { g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(item->data)); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(item->data); operation = INF_ADOPTED_OPERATION(item->data); if(priv->length > 0) { temp_slice = inf_text_buffer_get_slice( INF_TEXT_BUFFER(buffer), priv->position, priv->length ); recon_list = inf_text_remote_delete_operation_recon_feed( priv->recon, 0, temp_slice ); inf_text_chunk_free(temp_slice); } else { recon_list = priv->recon; } for(recon_item = recon_list; recon_item != NULL; recon_item = g_slist_next(recon_item)) { recon = (InfTextRemoteDeleteOperationRecon*)recon_item->data; g_assert(priv->recon_offset + recon->position == inf_text_chunk_get_length(chunk)); inf_text_chunk_insert_chunk( chunk, inf_text_chunk_get_length(chunk), recon->chunk ); } /* Free recon list if newly allocated */ if(priv->length > 0) inf_text_remote_delete_operation_recon_free(recon_list); if(!inf_adopted_operation_apply(operation, by, buffer, error)) { g_slist_free(list); inf_text_chunk_free(chunk); return NULL; } } g_slist_free(list); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(op); result = inf_text_default_delete_operation_new(priv->position, chunk); inf_text_chunk_free(chunk); return INF_ADOPTED_OPERATION(result); }