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 (10999B)


      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  */
    146 ledit_line *buffer_get_line(ledit_buffer *buffer, size_t index);
    147 
    148 /*
    149  * Tell views to recalculate the height of line 'line' and
    150  * update the pixel offsets of the following lines.
    151  */
    152 void buffer_recalc_line(ledit_buffer *buffer, size_t line);
    153 
    154 /*
    155  * Tell views to recalculate the height for all lines starting at 'line'
    156  * where the text_dirty attribute is set and update the pixel offsets of
    157  * all lines after 'line'.
    158  * Also clear the text_dirty attribute for all lines starting at 'line'.
    159  */
    160 void buffer_recalc_from_line(ledit_buffer *buffer, size_t line);
    161 
    162 /*
    163  * Tell views to recalculate all lines.
    164  * Also clear the text_dirty attribute for all lines.
    165  */
    166 void buffer_recalc_all_lines(ledit_buffer *buffer);
    167 
    168 /*
    169  * Get needed length of text range, including newlines.
    170  * - NUL is not included
    171  * - if the last range ends at the end of a line, the newline is *not* included
    172  * - the range must be sorted already
    173  */
    174 size_t buffer_textlen(ledit_buffer *buffer, size_t line1, size_t byte1, size_t line2, size_t byte2);
    175 
    176 /*
    177  * Copy text range into given buffer and resize it if necessary.
    178  * - the range must be sorted already
    179  */
    180 void buffer_copy_text_to_txtbuf(
    181     ledit_buffer *buffer,
    182     txtbuf *buf, /* oh, isn't that a very non-confusing name? */
    183     size_t line1, size_t byte1,
    184     size_t line2, size_t byte2
    185 );
    186 
    187 /*
    188  * Get the byte index of the previous utf8 character starting at byte index 'index'.
    189  */
    190 size_t line_next_utf8(ledit_line *line, size_t index);
    191 
    192 /*
    193  * Get the byte index of the previous utf8 character starting at byte index 'index'.
    194  */
    195 size_t line_prev_utf8(ledit_line *line, size_t index);
    196 
    197 /*
    198  * Get the unicode character index of a byte position.
    199  * Note that the time complexity of this is linear.
    200  */
    201 size_t line_byte_to_char(ledit_line *line, size_t byte);
    202 
    203 /*
    204  * Get the line and byte position of the unicode character position 'num'
    205  * positions after the position at line 'line' and byte position 'byte'.
    206  * The new position is returned in 'line_ret' and 'byte_ret'.
    207  * If multiline is non-zero, the new position may be on a different line.
    208  * Otherwise, it is at most the length of the given line.
    209  * A newline counts as one position.
    210  */
    211 void buffer_next_char_pos(
    212     ledit_buffer *buffer,
    213     size_t line, size_t byte,
    214     int num, int multiline,
    215     size_t *line_ret, size_t *byte_ret
    216 );
    217 
    218 /*
    219  * Get the line and byte position of the unicode character position 'num'
    220  * positions before the position at line 'line' and byte position 'byte'.
    221  * The new position is returned in 'line_ret' and 'byte_ret'.
    222  * If multiline is non-zero, the new position may be on a different line.
    223  * Otherwise, it is never earlier than position 0 on the given line.
    224  * A newline counts as one position.
    225  */
    226 void buffer_prev_char_pos(
    227     ledit_buffer *buffer,
    228     size_t line, size_t byte,
    229     int num, int multiline,
    230     size_t *line_ret, size_t *byte_ret
    231 );
    232 
    233 /*
    234  * Insert a mark with key 'mark' (which has byte length 'len') at line 'line' and byte 'byte'.
    235  */
    236 void buffer_insert_mark(ledit_buffer *buffer, char *mark, size_t len, size_t line, size_t byte);
    237 
    238 /*
    239  * Retrieve mark 'mark' (with byte length 'len').
    240  * The line and byte of the mark are written to 'line_ret' and 'byte_ret'.
    241  * These returned positions are always valid positions in the buffer, even
    242  * if the buffer has been modified and the mark points to an invalid location.
    243  * Returns 0 if the mark was found, 1 otherwise.
    244  */
    245 int buffer_get_mark(ledit_buffer *buffer, char *mark, size_t len, size_t *line_ret, size_t *byte_ret);
    246 
    247 /*
    248  * Perform one undo step.
    249  * 'mode' should be the current mode of the calling view.
    250  * 'cur_line' and 'cur_byte' are filled with the new line and cursor
    251  * position after the undo.
    252  */
    253 undo_status buffer_undo(ledit_buffer *buffer, ledit_mode mode, size_t *cur_line, size_t *cur_byte);
    254 
    255 /*
    256  * Same as 'buffer_undo', but for redo.
    257  */
    258 undo_status buffer_redo(ledit_buffer *buffer, ledit_mode mode, size_t *cur_line, size_t *cur_byte);
    259 
    260 /*
    261  * Delete the given range (which does not need to be sorted yet) and
    262  * add the operation to the undo stack.
    263  * 'cur_range' is the cursor range to be added to the undo stack.
    264  * 'start_undo_group' and 'mode' are also used for the undo stack.
    265  * If 'text_ret' is not NULL, the deleted text is written to it.
    266  * This function does not tell the views to update their line heights
    267  * and offsets.
    268  */
    269 void buffer_delete_with_undo_base(
    270     ledit_buffer *buffer, ledit_range cur_range,
    271     int start_undo_group, ledit_mode mode, /* for undo */
    272     size_t line_index1, size_t byte_index1,
    273     size_t line_index2, size_t byte_index2,
    274     txtbuf *text_ret
    275 );
    276 
    277 /*
    278  * Same as 'buffer_delete_with_undo_base', but the views are told to
    279  * update their line heights and offsets afterwards.
    280  */
    281 void buffer_delete_with_undo(
    282     ledit_buffer *buffer, ledit_range cur_range,
    283     int start_undo_group, ledit_mode mode, /* for undo */
    284     size_t line_index1, size_t byte_index1,
    285     size_t line_index2, size_t byte_index2,
    286     txtbuf *text_ret
    287 );
    288 
    289 /*
    290  * Insert the given 'text' with length 'len' at line 'line' and
    291  * byte index 'byte and add the operation to the undo stack.
    292  * 'cur_range', 'start_undo_group', and 'mode' are used for the
    293  * undo stack. If 'set_range_end' is set, the end position of
    294  * 'cur_range' is set to the end position of the insertion before
    295  * adding the operation to the undo stack.
    296  * If 'line_ret' and 'byte_ret' are not NULL, they are filled with
    297  * the end position of the insertion.
    298  * This function does not tell the views to update their line heights
    299  * and offsets.
    300  */
    301 void buffer_insert_with_undo_base(
    302     ledit_buffer *buffer,
    303     ledit_range cur_range, int set_range_end,
    304     int start_undo_group, ledit_mode mode,
    305     size_t line, size_t byte,
    306     char *text, size_t len,
    307     size_t *line_ret, size_t *byte_ret
    308 );
    309 
    310 /*
    311  * Same as 'buffer_insert_with_undo_base', but the views are told to
    312  * update their line heights and offsets afterwards.
    313  */
    314 void buffer_insert_with_undo(
    315     ledit_buffer *buffer,
    316     ledit_range cur_range, int set_range_end,
    317     int start_undo_group, ledit_mode mode,
    318     size_t line, size_t byte,
    319     char *text, size_t len,
    320     size_t *line_ret, size_t *byte_ret
    321 );
    322 
    323 #endif