ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/ledit.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ledit.git (over tor)
Log | Files | Refs | README | LICENSE

buffer.h (11292B)


      1 #ifndef _LEDIT_BUFFER_H_
      2 #define _LEDIT_BUFFER_H_
      3 
      4 #include <time.h>
      5 #include <stdio.h>
      6 #include <stddef.h>
      7 
      8 #include "common.h"
      9 #include "txtbuf.h"
     10 #include "undo.h"
     11 
     12 typedef struct ledit_buffer ledit_buffer;
     13 
     14 #include "view.h"
     15 
     16 typedef struct {
     17 	ledit_buffer *parent_buffer;
     18 	char *text;      /* text, stored as gap buffer */
     19 	size_t gap;      /* position of gap for gap buffer */
     20 	size_t cap;      /* allocated space for text */
     21 	size_t len;      /* actual length of text */
     22 } ledit_line;
     23 
     24 typedef struct {
     25 	char *text;
     26 	size_t line;
     27 	size_t byte;
     28 } ledit_buffer_mark;
     29 
     30 typedef struct {
     31 	size_t len, alloc;
     32 	ledit_buffer_mark *marks;
     33 } ledit_buffer_marklist;
     34 
     35 /* TODO: advisory lock on file */
     36 struct ledit_buffer {
     37 	ledit_common *common;            /* common stuff, e.g. display, etc. - this doesn't really belong here */
     38 	ledit_clipboard *clipboard;      /* this also doesn't really belong here */
     39 	/* FIXME: add some sort of manager that holds shared stuff like clipboard and manages the buffer and views */
     40 	char *filename;                  /* last opened filename */
     41 	struct timespec file_mtime;      /* last modified time of file */
     42 	undo_stack *undo;                /* undo manager */
     43 	ledit_buffer_marklist *marklist; /* list of mark positions set */
     44 	ledit_line *lines;               /* array of lines */
     45 	ledit_view **views;              /* array of registered views */
     46 	size_t views_num;                /* number of views in array */
     47 	size_t lines_cap;                /* size of lines array */
     48 	size_t lines_gap;                /* position of gap for line gap buffer */
     49 	size_t lines_num;                /* number of lines */
     50 	int modified;                    /* whether buffer was modified since loading a file */
     51 	int hard_line_based;             /* whether operations should work on soft- or hardlines
     52 	                                    Note that this doesn't actually change any behavior of
     53 	                                    the buffer functions, it is just stored here so all
     54 	                                    views can be updated to display it in their status. */
     55 };
     56 
     57 /*
     58  * Create a new buffer with one empty line
     59  */
     60 ledit_buffer *buffer_create(ledit_common *common, ledit_clipboard *clipboard);
     61 
     62 /*
     63  * Lock all views except the given view.
     64  */
     65 void buffer_lock_all_views_except(ledit_buffer *buffer, ledit_view *view, char *lock_text);
     66 
     67 /*
     68  * Unlock all views.
     69  */
     70 void buffer_unlock_all_views(ledit_buffer *buffer);
     71 
     72 /*
     73  * Set the hard line mode of the buffer and update the
     74  * displayed mode in all views.
     75  */
     76 void buffer_set_hard_line_based(ledit_buffer *buffer, int hl);
     77 
     78 /*
     79  * Add a new view to the buffer.
     80  * 'line' and 'pos' are the initial line and byte position of the cursor.
     81  * 'scroll_offset' is the initial pixel scroll offset.
     82  */
     83 void buffer_add_view(
     84     ledit_buffer *buffer, ledit_mode mode, size_t line, size_t pos, long scroll_offset
     85 );
     86 
     87 /*
     88  * Remove the given view from the buffer.
     89  * Nothing is done if the view does not belong to the buffer.
     90  */
     91 void buffer_remove_view(ledit_buffer *buffer, ledit_view *view);
     92 
     93 /*
     94  * Call 'view_recalc_from_line' for all views.
     95  */
     96 void buffer_recalc_all_views_from_line(ledit_buffer *buffer, size_t line);
     97 
     98 /*
     99  * Load a file into the buffer at line 'line'.
    100  * If the line is empty, the text is inserted directly.
    101  * Otherwise it is appended after the line.
    102  * Returns 0 on success and 1 on error. In case of an error, *errstr is filled
    103  * with an error message which must be copied as soon as possible because it may
    104  * be overwritten by subsequent function calls.
    105  */
    106 int buffer_load_file(ledit_buffer *buffer, char *filename, size_t line, char **errstr);
    107 
    108 /*
    109  * Write the buffer to a FILE pointer.
    110  * Returns 0 on success and 1 on error. In case of an error, *errstr is filled
    111  * with an error message which must be copied as soon as possible because it may
    112  * be overwritten by subsequent function calls.
    113  * In all cases, 'file' is closed.
    114  */
    115 int buffer_write_to_file(ledit_buffer *buffer, FILE *file, char **errstr);
    116 
    117 /*
    118  * Write the buffer to a filename.
    119  * Behaves the same as 'buffer_write_to_file'.
    120  */
    121 int buffer_write_to_filename(ledit_buffer *buffer, char *filename, char **errstr);
    122 
    123 /*
    124  * Write the buffer to a file descriptor.
    125  * Behaves the same as 'buffer_write_to_file', but if the
    126  * file descriptor cannot be fdopen'd, it is closed before returning.
    127  */
    128 int buffer_write_to_fd(ledit_buffer *buffer, int fd, char **errstr);
    129 
    130 /*
    131  * Destroy a buffer.
    132  */
    133 void buffer_destroy(ledit_buffer *buffer);
    134 
    135 /*
    136  * Normalize a line, i.e. move the gap to the end and add '\0'
    137  * so the text can be used as a normal string
    138  */
    139 void buffer_normalize_line(ledit_line *line);
    140 
    141 /*
    142  * Get the line at logical index 'index'.
    143  * The returned line is only valid until the next
    144  * action that appends or deletes line entries.
    145  * The macro is used in order to give better debug
    146  * information when there is an error since so many
    147  * functions call this one.
    148  */
    149 ledit_line *buffer_get_line_impl(ledit_buffer *buffer, size_t index, const char *file, int line, const char *func);
    150 #define buffer_get_line(buffer, index) (buffer_get_line_impl((buffer), (index), __FILE__, __LINE__, __func__))
    151 
    152 /*
    153  * Tell views to recalculate the height of line 'line' and
    154  * update the pixel offsets of the following lines.
    155  */
    156 void buffer_recalc_line(ledit_buffer *buffer, size_t line);
    157 
    158 /*
    159  * Tell views to recalculate the height for all lines starting at 'line'
    160  * where the text_dirty attribute is set and update the pixel offsets of
    161  * all lines after 'line'.
    162  * Also clear the text_dirty attribute for all lines starting at 'line'.
    163  */
    164 void buffer_recalc_from_line(ledit_buffer *buffer, size_t line);
    165 
    166 /*
    167  * Tell views to recalculate all lines.
    168  * Also clear the text_dirty attribute for all lines.
    169  */
    170 void buffer_recalc_all_lines(ledit_buffer *buffer);
    171 
    172 /*
    173  * Get needed length of text range, including newlines.
    174  * - NUL is not included
    175  * - if the last range ends at the end of a line, the newline is *not* included
    176  * - the range must be sorted already
    177  */
    178 size_t buffer_textlen(ledit_buffer *buffer, size_t line1, size_t byte1, size_t line2, size_t byte2);
    179 
    180 /*
    181  * Copy text range into given buffer and resize it if necessary.
    182  * - the range must be sorted already
    183  */
    184 void buffer_copy_text_to_txtbuf(
    185     ledit_buffer *buffer,
    186     txtbuf *buf, /* oh, isn't that a very non-confusing name? */
    187     size_t line1, size_t byte1,
    188     size_t line2, size_t byte2
    189 );
    190 
    191 /*
    192  * Get the byte index of the previous utf8 character starting at byte index 'index'.
    193  */
    194 size_t line_next_utf8(ledit_line *line, size_t index);
    195 
    196 /*
    197  * Get the byte index of the previous utf8 character starting at byte index 'index'.
    198  */
    199 size_t line_prev_utf8(ledit_line *line, size_t index);
    200 
    201 /*
    202  * Get the unicode character index of a byte position.
    203  * Note that the time complexity of this is linear.
    204  */
    205 size_t line_byte_to_char(ledit_line *line, size_t byte);
    206 
    207 /*
    208  * Get the line and byte position of the unicode character position 'num'
    209  * positions after the position at line 'line' and byte position 'byte'.
    210  * The new position is returned in 'line_ret' and 'byte_ret'.
    211  * If multiline is non-zero, the new position may be on a different line.
    212  * Otherwise, it is at most the length of the given line.
    213  * A newline counts as one position.
    214  */
    215 void buffer_next_char_pos(
    216     ledit_buffer *buffer,
    217     size_t line, size_t byte,
    218     int num, int multiline,
    219     size_t *line_ret, size_t *byte_ret
    220 );
    221 
    222 /*
    223  * Get the line and byte position of the unicode character position 'num'
    224  * positions before the position at line 'line' and byte position 'byte'.
    225  * The new position is returned in 'line_ret' and 'byte_ret'.
    226  * If multiline is non-zero, the new position may be on a different line.
    227  * Otherwise, it is never earlier than position 0 on the given line.
    228  * A newline counts as one position.
    229  */
    230 void buffer_prev_char_pos(
    231     ledit_buffer *buffer,
    232     size_t line, size_t byte,
    233     int num, int multiline,
    234     size_t *line_ret, size_t *byte_ret
    235 );
    236 
    237 /*
    238  * Insert a mark with key 'mark' (which has byte length 'len') at line 'line' and byte 'byte'.
    239  */
    240 void buffer_insert_mark(ledit_buffer *buffer, char *mark, size_t len, size_t line, size_t byte);
    241 
    242 /*
    243  * Retrieve mark 'mark' (with byte length 'len').
    244  * The line and byte of the mark are written to 'line_ret' and 'byte_ret'.
    245  * These returned positions are always valid positions in the buffer, even
    246  * if the buffer has been modified and the mark points to an invalid location.
    247  * Returns 0 if the mark was found, 1 otherwise.
    248  */
    249 int buffer_get_mark(ledit_buffer *buffer, char *mark, size_t len, size_t *line_ret, size_t *byte_ret);
    250 
    251 /*
    252  * Perform one undo step.
    253  * 'mode' should be the current mode of the calling view.
    254  * 'cur_line' and 'cur_byte' are filled with the new line and cursor
    255  * position after the undo.
    256  */
    257 undo_status buffer_undo(ledit_buffer *buffer, ledit_mode mode, size_t *cur_line, size_t *cur_byte);
    258 
    259 /*
    260  * Same as 'buffer_undo', but for redo.
    261  */
    262 undo_status buffer_redo(ledit_buffer *buffer, ledit_mode mode, size_t *cur_line, size_t *cur_byte);
    263 
    264 /*
    265  * Delete the given range (which does not need to be sorted yet) and
    266  * add the operation to the undo stack.
    267  * 'cur_range' is the cursor range to be added to the undo stack.
    268  * 'start_undo_group' and 'mode' are also used for the undo stack.
    269  * If 'text_ret' is not NULL, the deleted text is written to it.
    270  * This function does not tell the views to update their line heights
    271  * and offsets.
    272  */
    273 void buffer_delete_with_undo_base(
    274     ledit_buffer *buffer, ledit_range cur_range,
    275     int start_undo_group, ledit_mode mode, /* for undo */
    276     size_t line_index1, size_t byte_index1,
    277     size_t line_index2, size_t byte_index2,
    278     txtbuf *text_ret
    279 );
    280 
    281 /*
    282  * Same as 'buffer_delete_with_undo_base', but the views are told to
    283  * update their line heights and offsets afterwards.
    284  */
    285 void buffer_delete_with_undo(
    286     ledit_buffer *buffer, ledit_range cur_range,
    287     int start_undo_group, ledit_mode mode, /* for undo */
    288     size_t line_index1, size_t byte_index1,
    289     size_t line_index2, size_t byte_index2,
    290     txtbuf *text_ret
    291 );
    292 
    293 /*
    294  * Insert the given 'text' with length 'len' at line 'line' and
    295  * byte index 'byte and add the operation to the undo stack.
    296  * 'cur_range', 'start_undo_group', and 'mode' are used for the
    297  * undo stack. If 'set_range_end' is set, the end position of
    298  * 'cur_range' is set to the end position of the insertion before
    299  * adding the operation to the undo stack.
    300  * If 'line_ret' and 'byte_ret' are not NULL, they are filled with
    301  * the end position of the insertion.
    302  * This function does not tell the views to update their line heights
    303  * and offsets.
    304  */
    305 void buffer_insert_with_undo_base(
    306     ledit_buffer *buffer,
    307     ledit_range cur_range, int set_range_end,
    308     int start_undo_group, ledit_mode mode,
    309     size_t line, size_t byte,
    310     char *text, size_t len,
    311     size_t *line_ret, size_t *byte_ret
    312 );
    313 
    314 /*
    315  * Same as 'buffer_insert_with_undo_base', but the views are told to
    316  * update their line heights and offsets afterwards.
    317  */
    318 void buffer_insert_with_undo(
    319     ledit_buffer *buffer,
    320     ledit_range cur_range, int set_range_end,
    321     int start_undo_group, ledit_mode mode,
    322     size_t line, size_t byte,
    323     char *text, size_t len,
    324     size_t *line_ret, size_t *byte_ret
    325 );
    326 
    327 #endif