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 void infinoted_plugin_document_stream_sync_text( InfinotedPluginDocumentStreamStream* stream) { InfTextBuffer* buffer; InfTextBufferIter* iter; gpointer text; guint32 comm; guint32 len; gboolean alive; buffer = INF_TEXT_BUFFER(stream->buffer); iter = inf_text_buffer_create_begin_iter(buffer); alive = TRUE; if(iter != NULL) { do { comm = 1; /* SYNC */ len = inf_text_buffer_iter_get_bytes(buffer, iter); alive = infinoted_plugin_document_stream_send(stream, &comm, 4); if(!alive) break; alive = infinoted_plugin_document_stream_send(stream, &len, 4); if(!alive) break; text = inf_text_buffer_iter_get_text(buffer, iter); alive = infinoted_plugin_document_stream_send(stream, text, len); g_free(text); if(!alive) break; } while(inf_text_buffer_iter_next(buffer, iter)); inf_text_buffer_destroy_iter(buffer, iter); } if(alive) { comm = 2; /* SYNC DONE */ alive = infinoted_plugin_document_stream_send(stream, &comm, 4); } }
static gboolean infd_note_plugin_text_session_write(InfdStorage* storage, InfSession* session, const gchar* path, gpointer user_data, GError** error) { InfUserTable* table; InfTextBuffer* buffer; InfTextBufferIter* iter; xmlNodePtr root; xmlNodePtr buffer_node; xmlNodePtr segment_node; guint author; gchar* content; gsize bytes; FILE* stream; xmlDocPtr doc; xmlErrorPtr xmlerror; g_assert(INFD_IS_FILESYSTEM_STORAGE(storage)); g_assert(INF_TEXT_IS_SESSION(session)); /* Open stream before exporting buffer to XML so possible errors are * catched earlier. */ stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfText", path, "w", error ); if(stream == NULL) return FALSE; root = xmlNewNode(NULL, (const xmlChar*)"inf-text-session"); buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session)); table = inf_session_get_user_table(session); inf_user_table_foreach_user( table, infd_note_plugin_text_session_write_foreach_user_func, root ); buffer_node = xmlNewChild(root, NULL, (const xmlChar*)"buffer", NULL); iter = inf_text_buffer_create_iter(buffer); if(iter != NULL) { do { author = inf_text_buffer_iter_get_author(buffer, iter); content = inf_text_buffer_iter_get_text(buffer, iter); bytes = inf_text_buffer_iter_get_bytes(buffer, iter); segment_node = xmlNewChild( buffer_node, NULL, (const xmlChar*)"segment", NULL ); inf_xml_util_set_attribute_uint(segment_node, "author", author); inf_xml_util_add_child_text(segment_node, content, bytes); g_free(content); } while(inf_text_buffer_iter_next(buffer, iter)); inf_text_buffer_destroy_iter(buffer, iter); } doc = xmlNewDoc((const xmlChar*)"1.0"); xmlDocSetRootElement(doc, root); if(xmlDocFormatDump(stream, doc, 1) == -1) { xmlerror = xmlGetLastError(); fclose(stream); xmlFreeDoc(doc); g_set_error( error, g_quark_from_static_string("LIBXML2_OUTPUT_ERROR"), xmlerror->code, "%s", xmlerror->message ); return FALSE; } fclose(stream); xmlFreeDoc(doc); return TRUE; }