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