diff options
| author | Albert Cervin <albert@acervin.com> | 2023-07-12 16:20:50 +0200 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2023-10-19 22:41:33 +0200 |
| commit | 54c9b4b533210b77be998f458ff96bdc54272f64 (patch) | |
| tree | eb434343bb1083172af50b7372d1e2745af00f8f /src/dged/buffer.h | |
| parent | 3a8ae83aa13636679c151027cace905fa87ebd8e (diff) | |
| download | dged-54c9b4b533210b77be998f458ff96bdc54272f64.tar.gz dged-54c9b4b533210b77be998f458ff96bdc54272f64.tar.xz dged-54c9b4b533210b77be998f458ff96bdc54272f64.zip | |
big buffer/buffer_view rework
A buffer is only the text and the corresponding operation. A buffer view
holds information about scroll, dot and mark positions. One way to think
about it is that a buffer is stateless whereas a buffer view is stateful.
Diffstat (limited to 'src/dged/buffer.h')
| -rw-r--r-- | src/dged/buffer.h | 550 |
1 files changed, 372 insertions, 178 deletions
diff --git a/src/dged/buffer.h b/src/dged/buffer.h index 28d9797..e29e3e1 100644 --- a/src/dged/buffer.h +++ b/src/dged/buffer.h @@ -1,3 +1,6 @@ +#ifndef _BUFFER_H +#define _BUFFER_H + #include <stddef.h> #include <stdint.h> #include <stdio.h> @@ -5,81 +8,22 @@ #include "command.h" #include "lang.h" +#include "location.h" #include "text.h" #include "undo.h" #include "window.h" -struct keymap; struct command_list; -enum text_property_type { - TextProperty_Colors, -}; - -struct text_property_colors { - bool set_fg; - uint32_t fg; - bool set_bg; - uint32_t bg; -}; - -struct text_property { - enum text_property_type type; - union { - struct text_property_colors colors; - }; -}; - -/** - * Margins where buffer text should not be - */ -struct margin { - uint32_t left; - uint32_t right; - uint32_t top; - uint32_t bottom; -}; - -/** Callback for line rendering hooks */ -typedef void (*line_render_cb)(struct text_chunk *line_data, uint32_t line, - struct command_list *commands, void *userdata); - -typedef void (*line_render_empty_cb)(uint32_t line, - struct command_list *commands, - void *userdata); - -/** - * A line render hook - * - * A callback paired with userdata - */ -struct line_render_hook { - line_render_cb callback; - line_render_empty_cb empty_callback; - void *userdata; -}; - -/** - * Result of updating a buffer hook - */ -struct update_hook_result { - /** Desired margins for this hook */ - struct margin margins; - - /** Hook to be added to rendering of buffer lines */ - struct line_render_hook line_render_hook; -}; - /** Buffer update hook callback function */ -typedef struct update_hook_result (*update_hook_cb)( - struct buffer_view *view, struct command_list *commands, uint32_t width, - uint32_t height, uint64_t frame_time, void *userdata); +typedef void (*update_hook_cb)(struct buffer *buffer, uint32_t width, + uint32_t height, void *userdata); /** * A buffer update hook. * * Can be used to implement custom behavior on top of a buffer. Used for - * minibuffer, line numbers, modeline etc. + * minibuffer. */ struct update_hook { /** Callback function */ @@ -89,67 +33,9 @@ struct update_hook { void *userdata; }; -typedef void (*create_hook_cb)(struct buffer *buffer, void *userdata); - -/** - * A set of update hooks - */ -struct update_hooks { - /** The update hooks */ - struct update_hook hooks[32]; - - /** The number of update hooks */ - uint32_t nhooks; -}; - -struct buffer_location { - uint32_t line; - uint32_t col; -}; - -bool buffer_location_is_between(struct buffer_location location, - struct buffer_location start, - struct buffer_location end); - -struct match { - struct buffer_location begin; - struct buffer_location end; -}; - -struct buffer_view { - /** Location of dot (cursor) */ - struct buffer_location dot; - - /** Location of mark (where a selection starts) */ - struct buffer_location mark; - - /** Current buffer scroll position */ - struct buffer_location scroll; - - /** True if the start of a selection has been set */ - bool mark_set; - - /** Modeline buffer (may be NULL) */ - struct modeline *modeline; - - bool line_numbers; - - struct buffer *buffer; -}; - -struct buffer_view buffer_view_create(struct buffer *buffer, bool modeline, - bool line_numbers); -struct buffer_view buffer_view_clone(struct buffer_view *view); - -void buffer_view_scroll_down(struct buffer_view *view, uint32_t height); -void buffer_view_scroll_up(struct buffer_view *view, uint32_t height); - -void buffer_view_destroy(struct buffer_view *view); - -struct text_property_entry { - struct buffer_location start; - struct buffer_location end; - struct text_property property; +struct update_hook_entry { + uint32_t id; + struct update_hook hook; }; /** @@ -166,103 +52,411 @@ struct buffer { /** Associated filename, this is where the buffer will be saved to */ char *filename; + /** Time when buffer was last written to disk */ struct timespec last_write; /** Text data structure */ struct text *text; /** Buffer update hooks */ - struct update_hooks update_hooks; + VEC(struct update_hook_entry) update_hooks; /** Buffer undo stack */ struct undo_stack undo; + /** Buffer programming language */ + struct language lang; + /** Has this buffer been modified from when it was last saved */ bool modified; /** Can this buffer be changed */ bool readonly; +}; - /** Buffer programming language */ - struct language lang; +void buffer_static_init(); +void buffer_static_teardown(); - VEC(struct text_property_entry) text_properties; -}; +/** + * Create a new buffer. + * + * @param [in] name The buffer name. + * @returns A new buffer + */ +struct buffer buffer_create(const char *name); + +/** + * Create a new buffer from a file path. + * + * @param [in] path Path to the file to load into the new buffer. + * @returns A new buffer with @ref path loaded. + */ +struct buffer buffer_from_file(const char *path); + +/** + * Save buffer to the backing file. + * + * @param [in] buffer Buffer to save. + */ +void buffer_to_file(struct buffer *buffer); -struct buffer buffer_create(char *name); +/** + * Set path to backing file for buffer. + * + * The backing file is used when writing the buffer to a file. + * @param [in] buffer The buffer to set filename for. + * @param [in] filename The filename to use. It is required that this is a full + * path. + */ +void buffer_set_filename(struct buffer *buffer, const char *filename); + +/** + * Reload the buffer from disk. + * + * Reload the buffer from the backing file. + * @param [in] buffer The buffer to reload. + */ +void buffer_reload(struct buffer *buffer); + +/** + * Destroy the buffer. + * + * Destroy the buffer, releasing all associated resources. + * @param [in] buffer The buffer to destroy. + */ void buffer_destroy(struct buffer *buffer); -void buffer_static_init(); -void buffer_static_teardown(); +/** + * Add text to the buffer at the specified location. + * + * @param [in] buffer The buffer to add text to. + * @param [in] at The location to add text at. + * @param [in] text Pointer to the text bytes, not NULL-terminated. + * @param [in] nbytes Number of bytes in @ref text. + * + * @returns The location at the end of the inserted text. + */ +struct location buffer_add(struct buffer *buffer, struct location at, + uint8_t *text, uint32_t nbytes); + +/** + * Set the entire text contents of the buffer. + * + * @param [in] buffer The buffer to set text for. + * @param [in] text Pointer to the text bytes, not NULL-terminated. + * @param [in] nbytes Number of bytes in @ref text. + * + * @returns The location at the end of the inserted text + */ +struct location buffer_set_text(struct buffer *buffer, uint8_t *text, + uint32_t nbytes); + +/** + * Clear all text in the buffer + * + * @param [in] buffer The buffer to clear. + */ +void buffer_clear(struct buffer *buffer); -int buffer_add_text(struct buffer_view *view, uint8_t *text, uint32_t nbytes); -void buffer_set_text(struct buffer *buffer, uint8_t *text, uint32_t nbytes); -void buffer_clear(struct buffer_view *view); +/** + * Does buffer contain any text? + * + * @param [in] buffer The buffer to check. + * @returns True if the buffer is empty (has no text in it), false otherwise. + */ bool buffer_is_empty(struct buffer *buffer); + +/** + * Has the buffer been modified since it was last retrieved from/saved to disk? + * + * @param [in] buffer The buffer to examine. + * @returns True if the buffer has been modified, false otherwise. + */ bool buffer_is_modified(struct buffer *buffer); + +/** + * Is this buffer read-only? + * + * @param [in] buffer The buffer to examine. + * @returns True if the buffer is read-only (cannot be modified), false + * otherwise. + */ bool buffer_is_readonly(struct buffer *buffer); + +/** + * Set the read-only status for the buffer. + * + * @param [in] buffer The buffer to set read-only for. + * @param [in] readonly If true, the buffer is set to read-only, otherwise it is + * set to writable. + */ void buffer_set_readonly(struct buffer *buffer, bool readonly); + +/** + * Is the buffer backed by a file on disk? + * + * @param [in] buffer The buffer to examine. + * @returns True if the buffer has a path to a file on disk to use as backing + * file, false otherwise. Note that this function returns true even if the + * buffer has never been written to the backing file. + */ bool buffer_is_backed(struct buffer *buffer); -void buffer_kill_line(struct buffer_view *view); -void buffer_forward_delete_char(struct buffer_view *view); -void buffer_forward_delete_word(struct buffer_view *view); -void buffer_backward_delete_char(struct buffer_view *view); -void buffer_backward_delete_word(struct buffer_view *view); -void buffer_backward_char(struct buffer_view *view); -void buffer_backward_word(struct buffer_view *view); -void buffer_forward_char(struct buffer_view *view); -void buffer_forward_word(struct buffer_view *view); -void buffer_backward_line(struct buffer_view *view); -void buffer_forward_line(struct buffer_view *view); -void buffer_end_of_line(struct buffer_view *view); -void buffer_beginning_of_line(struct buffer_view *view); -void buffer_newline(struct buffer_view *view); -void buffer_indent(struct buffer_view *view); - -void buffer_undo(struct buffer_view *view); - -void buffer_goto_beginning(struct buffer_view *view); -void buffer_goto_end(struct buffer_view *view); -void buffer_goto(struct buffer_view *view, uint32_t line, uint32_t col); +/** + * Get location of previous character in buffer. + * + * @param [in] buffer The buffer to use. + * @param [in] dot The location to start from. + * @returns The location in front of the previous char given @ref dot. + */ +struct location buffer_previous_char(struct buffer *buffer, + struct location dot); + +/** + * Get location of previous word in buffer. + * + * @param [in] buffer The buffer to look in. + * @param [in] dot The location to start from. + * @returns The location at the start of the previous word, given @ref dot. + */ +struct location buffer_previous_word(struct buffer *buffer, + struct location dot); + +/** + * Get location of previous line. + * + * @param [in] buffer The buffer to look in. + * @param [in] dot The location to start from. + * @returns The location at the start of the line above the current one (the one + * @ref dot is on). If @ref dot is on the first line, the location (0, 0) is + * returned. + */ +struct location buffer_previous_line(struct buffer *buffer, + struct location dot); + +/** + * Get location of next character in buffer. + * + * @param [in] buffer The buffer to use. + * @param [in] dot The location to start from. + * @returns The location in front of the next char given @ref dot. + */ +struct location buffer_next_char(struct buffer *buffer, struct location dot); + +/** + * Get location of next word in buffer. + * + * @param [in] buffer The buffer to look in. + * @param [in] dot The location to start from. + * @returns The location at the start of the next word, given @ref dot. + */ +struct location buffer_next_word(struct buffer *buffer, struct location dot); + +/** + * Get location of next line. + * + * @param [in] buffer The buffer to look in. + * @param [in] dot The location to start from. + * @returns The location at the start of the line above the current one (the one + * @ref dot is on). If @ref dot is on the last line, the last location in the + * buffer is returned. + */ +struct location buffer_next_line(struct buffer *buffer, struct location dot); + +/** + * Clamp a buffer position to the boundaries of the buffer. + * + * Note that both @ref line and @ref col can be negative or bigger than the + * buffer. + * + * @param [in] buffer The buffer to use for clamping. + * @param [in] line The line position to clamp. + * @param [in] col The column position to clamp. + * @returns The closest position inside the buffer matching (line, col). + */ +struct location buffer_clamp(struct buffer *buffer, int64_t line, int64_t col); + +/** + * Get location of buffer end. + * + * @param [in] buffer The buffer to use. + * @returns the position after the last character in @ref buffer. + */ +struct location buffer_end(struct buffer *buffer); + +/** + * Get the number of lines in the buffer + * + * @param [in] buffer The buffer to use. + * @returns The number of lines in @ref buffer. + */ +uint32_t buffer_num_lines(struct buffer *buffer); + +/** + * Get the number of chars in a given line in buffer. + * + * @param [in] buffer The buffer to use. + * @param [in] line The line to get number of chars for. + * @returns The number of chars in @ref line. + */ +uint32_t buffer_num_chars(struct buffer *buffer, uint32_t line); + +/** + * Insert a newline in the buffer. + * + * @param [in] buffer The buffer to insert in. + * @param [in] at The point to insert at. + * @returns The location at the start of the new line. + */ +struct location buffer_newline(struct buffer *buffer, struct location at); + +/** + * Insert indentation in the buffer. + * + * @param [in] buffer The buffer to indent in. + * @param [in] at The location to insert indentation at. + * @returns The position after indenting. + */ +struct location buffer_indent(struct buffer *buffer, struct location at); + +/** + * Undo the last operation in the buffer. + * + * @param [in] buffer The buffer to undo in. + * @param [in] dot The point to undo at. + * @returns The position in the buffer after undo. + */ +struct location buffer_undo(struct buffer *buffer, struct location dot); +/** + * Search for a substring in the buffer. + * + * @param [in] buffer The buffer to search in. + * @param [in] pattern The substring to search for. + * @param [out] matches The pointer passed in is modified to point at the + * resulting matches. This pointer should be freed using @ref free. + * @param [nmatches] nmatches The pointer passed in is modified to point at the + * number of resulting matches. + */ void buffer_find(struct buffer *buffer, const char *pattern, - struct match **matches, uint32_t *nmatches); + struct region **matches, uint32_t *nmatches); -void buffer_set_mark(struct buffer_view *view); -void buffer_clear_mark(struct buffer_view *view); -void buffer_set_mark_at(struct buffer_view *view, uint32_t line, uint32_t col); +/** + * Copy a region in the buffer into the kill ring. + * + * @param [in] buffer The buffer to copy from. + * @param [in] region The region to copy. + * @returns The position in the buffer after the copy. + */ +struct location buffer_copy(struct buffer *buffer, struct region region); -void buffer_copy(struct buffer_view *view); -void buffer_paste(struct buffer_view *view); -void buffer_paste_older(struct buffer_view *view); -void buffer_cut(struct buffer_view *view); +/** + * Cut a region in the buffer into the kill ring. + * + * @param [in] buffer The buffer to cut from. + * @param [in] region The region to cut. + * @returns The position in the buffer after the cut. + */ +struct location buffer_cut(struct buffer *buffer, struct region region); -void buffer_clear_text_properties(struct buffer *buffer); +/** + * Delete a region in the buffer without putting it into the kill ring. + * + * @param [in] buffer The buffer to delete from. + * @param [in] region The region to delete. + * @returns The position in the buffer after the delete. + */ +struct location buffer_delete(struct buffer *buffer, struct region region); + +/** + * Paste from the kill ring into the buffer. + * + * @param [in] buffer Buffer to paste in. + * @param [in] at Location to paste at. + * @returns The location in the buffer after the paste. + */ +struct location buffer_paste(struct buffer *buffer, struct location at); + +/** + * Paste the next older entry from the kill ring into the buffer. + * + * @param [in] buffer Buffer to paste in. + * @param [in] at Location to paste at. + * @returns The location in the buffer after the paste. + */ +struct location buffer_paste_older(struct buffer *buffer, struct location at); -void buffer_add_text_property(struct buffer *buffer, - struct buffer_location start, - struct buffer_location end, +/** + * Get one line from the buffer. + * + * @param buffer The buffer to get the line from. + * @param line Line number in the buffer. + * @returns A text chunk describing the line. Note that if the line number is + * greater than the number of lines, the @ref text_chunk will be empty. + */ +struct text_chunk buffer_line(struct buffer *buffer, uint32_t line); + +void buffer_add_text_property(struct buffer *buffer, struct location start, + struct location end, struct text_property property); -void buffer_get_text_properties(struct buffer *buffer, - struct buffer_location location, +void buffer_get_text_properties(struct buffer *buffer, struct location location, struct text_property **properties, uint32_t max_nproperties, uint32_t *nproperties); -struct text_chunk buffer_get_line(struct buffer *buffer, uint32_t line); +void buffer_clear_text_properties(struct buffer *buffer); +/** + * Add a buffer update hook. + * + * @param [in] buffer The buffer to add the hook to. + * @param [in] hook The update hook callback. + * @param [in] userdata Data that is passed unmodified to the update hook. + * @returns The hook id. + */ uint32_t buffer_add_update_hook(struct buffer *buffer, update_hook_cb hook, void *userdata); +/** Buffer create hook callback function */ +typedef void (*create_hook_cb)(struct buffer *buffer, void *userdata); + +/** + * Add a buffer create hook. + * + * @param [in] hook Create hook callback. + * @param [in] userdata Pointer to data that is passed unmodified to the update + * hook. + * @returns The hook id. + */ uint32_t buffer_add_create_hook(create_hook_cb hook, void *userdata); -struct buffer buffer_from_file(char *filename); -void buffer_to_file(struct buffer *buffer); -void buffer_write_to(struct buffer *buffer, const char *filename); -void buffer_reload(struct buffer *buffer); +/** + * Parameters for updating a buffer. + */ +struct buffer_update_params { + + /** Command list to add rendering commands for the buffer */ + struct command_list *commands; + + /** Where is the upper left corner of the buffer */ + struct location origin; + + /** Window width for this buffer, -1 if it is not in a window */ + uint32_t width; + + /** Window height for this buffer, -1 if it is not in a window */ + uint32_t height; +}; + +/** + * Update a buffer. + * + * @param [in] buffer The buffer to update. + * @param [inout] params The parameters for the update. The @ref commands field + * in @ref params will be modified with the rendering commands needed for this + * buffer. + */ +void buffer_update(struct buffer *buffer, struct buffer_update_params *params); -void buffer_update(struct buffer_view *view, uint32_t window_id, uint32_t width, - uint32_t height, struct command_list *commands, - uint64_t frame_time, uint32_t *relline, uint32_t *relcol); +#endif |
