Beispiel #1
0
/**
 * inf_text_buffer_insert_text:
 * @buffer: A #InfTextBuffer.
 * @pos: A character offset into @buffer.
 * @text (type=guint8*) (array length=bytes) (transfer none): A pointer to
 * the text to insert.
 * @len: The length (in characters) of @text.
 * @bytes: The length (in bytes) of @text.
 * @user: (allow-none): A #InfUser that has inserted the new text, or %NULL.
 *
 * Inserts @text into @buffer as written by @author. @text must be encoded in
 * the character encoding of the buffer, see inf_text_buffer_get_encoding().
 **/
void
inf_text_buffer_insert_text(InfTextBuffer* buffer,
                            guint pos,
                            gconstpointer text,
                            gsize bytes,
                            guint len,
                            InfUser* user)
{
  InfTextBufferInterface* iface;
  InfTextChunk* chunk;

  g_return_if_fail(INF_TEXT_IS_BUFFER(buffer));
  g_return_if_fail(text != NULL);
  g_return_if_fail(user == NULL || INF_IS_USER(user));

  iface = INF_TEXT_BUFFER_GET_IFACE(buffer);
  g_return_if_fail(iface->insert_text != NULL);

  chunk = inf_text_chunk_new(inf_text_buffer_get_encoding(buffer));

  inf_text_chunk_insert_text(
    chunk,
    0,
    text,
    bytes,
    len,
    user == NULL ? 0 : inf_user_get_id(user)
  );

  iface->insert_text(buffer, pos, chunk, user);

  inf_text_chunk_free(chunk);
}
static guint
infinoted_plugin_linekeeper_count_lines(InfTextBuffer* buffer)
{
  /* Count the number of lines at the end of the document. This assumes the
   * buffer content is in UTF-8, which is currently hardcoded in infinoted. */
  InfTextBufferIter* iter;
  guint n_lines;
  gboolean has_iter;

  guint length;
  gsize bytes;
  gchar* text;
  gchar* pos;
  gchar* new_pos;
  gunichar c;

  g_assert(strcmp(inf_text_buffer_get_encoding(buffer), "UTF-8") == 0);

  n_lines = 0;

  iter = inf_text_buffer_create_end_iter(buffer);
  if(iter == NULL) return 0;

  do
  {
    length = inf_text_buffer_iter_get_length(buffer, iter);
    bytes = inf_text_buffer_iter_get_bytes(buffer, iter);
    text = inf_text_buffer_iter_get_text(buffer, iter);
    pos = text + bytes;

    while(length > 0)
    {
      new_pos = g_utf8_prev_char(pos);
      g_assert(bytes >= (pos - new_pos));

      c = g_utf8_get_char(new_pos);
      if(c == '\n' || g_unichar_type(c) == G_UNICODE_LINE_SEPARATOR)
        ++n_lines;
      else
        break;

      --length;
      bytes -= (pos - new_pos);
      pos = new_pos;
    }

    g_free(text);
  } while(length == 0 && inf_text_buffer_iter_prev(buffer, iter));

  inf_text_buffer_destroy_iter(buffer, iter);
  return n_lines;
}
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);
}
Beispiel #4
0
QString TextBuffer::encoding()
{
    return inf_text_buffer_get_encoding( INF_TEXT_BUFFER(gobject()) );
}