13 typedef uintptr_t Mark
;
15 /** An invalid mark, lookup of which will yield `EPOS`. */
16 #define EMARK ((Mark)0)
17 /** An invalid position. */
18 #define EPOS ((size_t)-1)
22 size_t start
; /**< Absolute byte position. */
23 size_t end
; /**< Absolute byte position. */
27 * Text object storing the buffer content being edited.
29 typedef struct Text Text
;
30 typedef struct Piece Piece
;
31 typedef struct TextSave TextSave
;
33 /** A contiguous part of the text. */
35 const char *data
; /**< Content, might not be NUL-terminated. */
36 size_t len
; /**< Length in bytes. */
40 * Iterator used to navigate the buffer content.
42 * Captures the position within a Piece.
45 * .. warning:: Any change to the Text will invalidate the iterator state.
46 * .. note:: Should be treated as an opaque type.
50 const char *start
; /**< Start of the piece data. */
51 const char *end
; /**< End of piece data. Addressable range is ``[start, end)``. */
52 const char *text
; /**< Current position within piece. Invariant ``start <= text < end`` holds. */
53 const Piece
*piece
; /**< Internal state of current piece. */
54 size_t pos
; /**< Absolute position in bytes from start of buffer. */
62 * Create a text instance populated with the given file content.
64 * @param filename The name of the file to load, if ``NULL`` an empty text is created.
65 * @return The new Text object or ``NULL`` in case of an error.
67 * .. note:: When attempting to load a non-regular file, ``errno`` will be set to:
69 * - ``EISDIR`` for a directory.
70 * - ``ENOTSUP`` otherwise.
73 Text
*text_load(const char *filename
);
74 /** Release all ressources associated with this text instance. */
75 void text_free(Text
*);
81 /** Return the size in bytes of the whole text. */
82 size_t text_size(Text
*);
84 * Get file information at time of load or last save, whichever happened more
87 * .. note:: If an empty text instance was created using ``text_load(NULL)``
88 * and it has not yet been saved, an all zero ``struct stat`` will
91 * @return See ``stat(2)`` for details.
93 struct stat
text_stat(Text
*);
94 /** Query whether the text contains any unsaved modifications. */
95 bool text_modified(Text
*);
102 * Insert data at the given byte position.
104 * @param pos The absolute byte position.
105 * @param data The data to insert.
106 * @param len The length of the data in bytes.
107 * @return Whether the insertion succeeded.
109 bool text_insert(Text
*, size_t pos
, const char *data
, size_t len
);
111 * Delete data at given byte position.
113 * @param pos The absolute byte position.
114 * @param len The number of bytes to delete, starting from ``pos``.
115 * @return Whether the deletion succeeded.
117 bool text_delete(Text
*, size_t pos
, size_t len
);
118 bool text_delete_range(Text
*, Filerange
*);
119 bool text_printf(Text
*, size_t pos
, const char *format
, ...) __attribute__((format(printf
, 3, 4)));
120 bool text_appendf(Text
*, const char *format
, ...) __attribute__((format(printf
, 2, 3)));
127 * Create a text snapshot, that is a vertice in the history graph.
129 void text_snapshot(Text
*);
131 * Revert to previous snapshot along the main branch.
133 * .. note:: Takes an implicit snapshot.
135 * @return The position of the first change or ``EPOS``, if already at the
136 * oldest state i.e. there was nothing to undo.
138 size_t text_undo(Text
*);
140 * Reapply an older change along the main brach.
142 * .. note:: Takes an implicit snapshot.
144 * @return The position of the first change or ``EPOS``, if already at the
145 * newest state i.e. there was nothing to redo.
147 size_t text_redo(Text
*);
148 size_t text_earlier(Text
*);
149 size_t text_later(Text
*);
151 * Restore the text to the state closest to the time given
153 size_t text_restore(Text
*, time_t);
155 * Get creation time of current state.
157 * .. note:: TODO: This is currently not the same as the time of the last snapshot.
160 time_t text_state(Text
*);
166 size_t text_pos_by_lineno(Text
*, size_t lineno
);
167 size_t text_lineno_by_pos(Text
*, size_t pos
);
175 * Get byte stored at ``pos``.
176 * @param pos The absolute position.
177 * @param byte Destination address to store the byte.
178 * @return Whether ``pos`` was valid and ``byte`` updated accordingly.
180 * .. note:: Unlike :c:func:`text_iterator_byte_get()` this function does not
181 * return an artificial NUL byte at EOF.
184 bool text_byte_get(Text
*, size_t pos
, char *byte
);
186 * Store at most `len` bytes starting from ``pos`` into ``buf``.
187 * @param pos The absolute starting position.
188 * @param len The length in bytes.
189 * @param buf The destination buffer.
190 * @return The number of bytes (``<= len``) stored at ``buf``.
192 * .. warning:: ``buf`` will not be NUL terminated.
195 size_t text_bytes_get(Text
*, size_t pos
, size_t len
, char *buf
);
197 * Fetch text range into newly allocate memory region.
198 * @param pos The absolute starting position.
199 * @param len The length in bytes.
200 * @return A contigious NUL terminated buffer holding the requested range, or
201 * ``NULL`` in error case.
203 * .. warning:: The returned pointer must be `free(3)`-ed by the caller.
206 char *text_bytes_alloc0(Text
*, size_t pos
, size_t len
);
212 Iterator
text_iterator_get(Text
*, size_t pos
);
213 bool text_iterator_valid(const Iterator
*);
214 bool text_iterator_next(Iterator
*);
215 bool text_iterator_prev(Iterator
*);
218 * @defgroup iterator_byte
221 bool text_iterator_byte_get(Iterator
*, char *b
);
222 bool text_iterator_byte_prev(Iterator
*, char *b
);
223 bool text_iterator_byte_next(Iterator
*, char *b
);
224 bool text_iterator_byte_find_prev(Iterator
*, char b
);
225 bool text_iterator_byte_find_next(Iterator
*, char b
);
228 * @defgroup iterator_code
231 bool text_iterator_codepoint_next(Iterator
*it
, char *c
);
232 bool text_iterator_codepoint_prev(Iterator
*it
, char *c
);
235 * @defgroup iterator_char
238 bool text_iterator_char_next(Iterator
*, char *c
);
239 bool text_iterator_char_prev(Iterator
*, char *c
);
248 * .. note:: Setting a mark to `text_size` will always return the current text
251 * @param pos The position at which to store the mark.
252 * @return The mark or `EMARK` if an invalid position was given.
254 Mark
text_mark_set(Text
*, size_t pos
);
257 * @param mark The mark to look up.
258 * @return The byte position or `EPOS` for an invalid mark.
260 size_t text_mark_get(Text
*, Mark
);
267 * Save the whole text to the given file name.
269 bool text_save(Text
*, const char *filename
);
271 * Save a file range to the given file name.
273 bool text_save_range(Text
*, Filerange
*, const char *filename
);
275 * Method used to save the text.
277 enum TextSaveMethod
{
278 /** Automatically chose best option. */
281 * Save file atomically using `rename(2)`.
283 * Creates a new file named `filename~` and tries to restore all important
284 * meta data. After which it is atomically moved to its final
285 * (possibly already existing) destination using `rename(2)`.
288 * .. warning:: This approach does not work if:
290 * - The file is a symbolic link.
291 * - The file is a hard link.
292 * - File ownership can not be preserved.
293 * - File group can not be preserved.
294 * - Directory permissions do not allow creation of a new file.
295 * - POSXI ACL can not be preserved (if enabled).
296 * - SELinux security context can not be preserved (if enabled).
301 * Overwrite file in place.
303 * .. warning:: I/O failure might cause data loss.
310 * Setup a sequence of write operations.
312 * The returned `TextSave` pointer can be used to write multiple, possibly
313 * non-contigious, file ranges.
315 * .. warning:: For every call to `text_save_begin` there must be exactly
316 * one matching call to either `text_save_commit` or
317 * `text_save_cancel` to release the underlying resources.
320 TextSave
*text_save_begin(Text
*, const char *filename
, enum TextSaveMethod
);
323 * @return The number of bytes written or ``-1`` in case of an error.
325 ssize_t
text_save_write_range(TextSave
*, Filerange
*);
327 * Commit changes to disk.
328 * @return Whether changes have been saved.
330 * .. note:: Releases the underlying resources and `free(3)`'s the given `TextSave`
331 * pointer which must no longer be used.
334 bool text_save_commit(TextSave
*);
336 * Abort a save operation.
338 * .. note:: Does not guarantee to undo the previous writes (they might have been
339 * performed in-place). However, it releases the underlying resources and
340 * `free(3)`'s the given `TextSave` pointer which must no longer be used.
343 void text_save_cancel(TextSave
*);
345 * Write whole text content to file descriptor.
346 * @return The number of bytes written or ``-1`` in case of an error.
348 ssize_t
text_write(Text
*, int fd
);
350 * Write file range to file descriptor.
351 * @return The number of bytes written or ``-1`` in case of an error.
353 ssize_t
text_write_range(Text
*, Filerange
*, int fd
);
360 * Check whether ``ptr`` is part of a memory mapped region associated with
361 * this text instance.
363 bool text_mmaped(Text
*, const char *ptr
);