view.h (18817B)
1 /* 2 * A view consists of a window and everything necessary for displaying 3 * the contents of the associated buffer in that window. 4 */ 5 6 #ifndef _LEDIT_VIEW_H_ 7 #define _LEDIT_VIEW_H_ 8 9 #include <stddef.h> 10 #include "common.h" 11 #include "txtbuf.h" 12 #include "window.h" 13 #include "cache.h" 14 #include "uglycrap.h" 15 16 typedef struct ledit_view ledit_view; 17 18 #include "buffer.h" 19 20 enum action_type { 21 ACTION_NONE, /* pass next key to basic key handler */ 22 ACTION_GRABKEY /* pass next key to given callback */ 23 }; 24 25 /* struct that is returned by key handlers to tell the 26 main event manager what key handler to call next */ 27 struct action { 28 enum action_type type; 29 struct action (*callback)(ledit_view *view, unsigned int key_state, KeySym sym, char *buf, int n, int lang_index); 30 }; 31 32 typedef struct { 33 ledit_view *view; /* parent view */ 34 int w; /* width in pixels */ 35 int h; /* height in pixels */ 36 long y_offset; /* pixel offset starting at the top of the file */ 37 size_t cache_pixmap_index; /* index of pixmap in cache, or -1 if not assigned */ 38 size_t cache_layout_index; /* index of pango layout in cache, or -1 if not assigned */ 39 int softlines; /* number of softlines - cached from PangoLayout */ 40 size_t cursor_index; /* cursor index (for highlight in normal mode) */ 41 char cursor_index_valid; /* whether cursor index is valid */ 42 char cache_pixmap_valid; /* whether cache_pixmap_index is valid */ 43 char cache_layout_valid; /* whether cache_layout_index is valid */ 44 char dirty; /* whether line needs to be rendered before being drawn */ 45 char text_dirty; /* whether the text in the PangoLayout needs to be 46 * updated before the layout is rendered */ 47 char highlight_dirty; /* whether highlight (cursor or selection) needs to be 48 * updated still in the PangoLayout before rendering */ 49 char h_dirty; /* whether height needs to be recalculated */ 50 } ledit_view_line; 51 52 struct ledit_view { 53 ledit_buffer *buffer; /* parent buffer */ 54 ledit_window *window; /* window showing this view */ 55 ledit_cache *cache; /* cache for pixmaps and pango layouts */ 56 ledit_view_line *lines; /* array of lines, stored as gap buffer */ 57 char *lock_text; /* text to show if view is locked, i.e. no edits allowed */ 58 /* current command type - used by key handler in keys_command.c */ 59 command_mode cur_command_type; 60 struct action cur_action; /* current action to execute on key press */ 61 size_t lines_cap; /* size of lines array */ 62 size_t lines_gap; /* position of gap for line gap buffer */ 63 size_t lines_num; /* number of lines */ 64 size_t cur_line; /* current line */ 65 size_t cur_index; /* current byte index in line */ 66 long total_height; /* total pixel height of all lines */ 67 long display_offset; /* current pixel offset of viewport */ 68 ledit_range sel; /* current selection */ 69 ledit_mode mode; /* current mode of this view */ 70 char destroy; /* whether the view should be destroyed at the next possible time */ 71 char selecting; /* whether user is currently selecting text with mouse */ 72 char button2_pressed; /* whether button 2 (middle button) is pressed */ 73 char sel_valid; /* whether there is currently a valid selection */ 74 char redraw; /* whether something has changed so the view needs to be redrawn */ 75 }; 76 77 enum delete_mode { 78 DELETE_CHAR, /* delete an exact line and byte range */ 79 DELETE_SOFTLINE, /* delete a range of complete softlines */ 80 DELETE_HARDLINE /* delete a range of complete hardlines */ 81 }; 82 83 /* 84 * Set the mode of the view. 85 * This changes the mode group of the associated buffer's 86 * undo stack and changes the mode display in the window. 87 */ 88 void view_set_mode(ledit_view *view, ledit_mode mode); 89 90 /* 91 * Create a view with associated buffer 'buffer' 92 * The initial mode, line, and byte position are given, respectively, 93 * by 'mode', 'line', and 'pos'. 94 */ 95 ledit_view *view_create(ledit_buffer *buffer, ledit_mode mode, size_t line, size_t pos); 96 97 /* 98 * Lock a view. 99 * Views are locked for instance when substitution with confirmation is 100 * being performed in another view to avoid an inconsistent state. 101 * This currently only sets the lock text - commands using the view need 102 * to make sure to check that it isn't locked. 103 */ 104 void view_lock(ledit_view *view, char *text); 105 106 /* 107 * Unlock a view. 108 */ 109 void view_unlock(ledit_view *view); 110 111 /* 112 * Get the view line at the given index. 113 * The returned line is only valid until the next 114 * action that appends or deletes line entries. 115 * The macro is used in order to give better debug 116 * information when there is an error since so many 117 * functions call this one. 118 */ 119 ledit_view_line *view_get_line_impl(ledit_view *view, size_t index, const char *file, int line, const char *func); 120 #define view_get_line(view, index) (view_get_line_impl((view), (index), __FILE__, __LINE__, __func__)) 121 122 /* 123 * These notification functions are called by the buffer when text 124 * is changed in order to keep all views in sync. 125 */ 126 127 /* 128 * Notify the view that 'len' bytes of text have been inserted at 129 * line 'line' and byte position 'index'. 130 * This marks the line as dirty, adjusts the cursor position, if it 131 * is on the same line, and sets the selection to just the current 132 * cursor position, if there was a valid selection. 133 * The line heights and offsets are not recalculated. 134 */ 135 void view_notify_insert_text(ledit_view *view, size_t line, size_t index, size_t len); 136 137 /* 138 * Notify the view that 'len' bytes of text have been deleted 139 * starting at line 'line' and byte position 'index'. 140 * This marks the line as dirty, adjusts the cursor position, if it 141 * is on the same line, and sets the selection to just the current 142 * cursor position, if there was a valid selection. 143 * The line heights and offsets are not recalculated. 144 */ 145 void view_notify_delete_text(ledit_view *view, size_t line, size_t index, size_t len); 146 147 /* 148 * Notify the view that a line has been appended after line 'line'. 149 * This adjusts the cursor position if necessary and sets the selection 150 * to just the current cursor position, if there was a valid selection. 151 * The line heights and offsets are not recalculated. 152 */ 153 void view_notify_append_line(ledit_view *view, size_t line); 154 155 /* 156 * Notify the view that all lines from 'index1' to 'index2' (inclusive) 157 * have been deleted. 158 * This adjusts the cursor position if necessary and sets the selection 159 * to just the current cursor position, if there was a valid selection. 160 * The line heights and offsets are not recalculated. 161 */ 162 void view_notify_delete_lines(ledit_view *view, size_t index1, size_t index2); 163 164 /* 165 * Destroy a view and its window. 166 */ 167 void view_destroy(ledit_view *view); 168 169 /* 170 * Perform cleanup of global data. 171 */ 172 void view_cleanup(void); 173 174 /* 175 * Set a cursor highlight on the character at line 'line' and 176 * byte position 'index'. 177 */ 178 void view_set_line_cursor_attrs(ledit_view *view, size_t line, size_t index); 179 180 /* 181 * Remove cursor highlight from line 'line'. 182 */ 183 void view_wipe_line_cursor_attrs(ledit_view *view, size_t line); 184 185 /* 186 * Recalculate the height of line 'line'. 187 * If it has changed, the offsets of all following lines are recalculated. 188 */ 189 void view_recalc_line(ledit_view *view, size_t line); 190 191 /* 192 * Recalculate the height and offset of all lines starting at 'line'. 193 * If 'line' is 0, the offset is set to 0. 194 */ 195 void view_recalc_from_line(ledit_view *view, size_t line); 196 197 /* 198 * Shortcut for recalculating all lines starting at 0. 199 */ 200 void view_recalc_all_lines(ledit_view *view); 201 202 /* 203 * The cursor movement functions here logically belong to the buffer, 204 * but they use various unicode attributes that pango exposes, so 205 * they have to be here as long as no separate library for unicode 206 * processing is used. 207 */ 208 209 /* 210 * Get the line and byte position of the cursor position 'num' positions 211 * after the position at line 'line' and byte position 'byte'. The new 212 * position is returned in 'line_ret' and 'byte_ret'. 213 * If multiline is non-zero, the new position may be on a different line. 214 * Otherwise, it is at most the length of the given line. 215 * A newline counts as one position. 216 */ 217 void view_next_cursor_pos( 218 ledit_view *view, 219 size_t line, size_t byte, 220 int num, int multiline, 221 size_t *line_ret, size_t *byte_ret 222 ); 223 224 /* 225 * Get the line and byte position of the cursor position 'num' positions 226 * before the position at line 'line' and byte position 'byte'. The new 227 * position is returned in 'line_ret' and 'byte_ret'. 228 * If multiline is non-zero, the new position may be on a different line. 229 * Otherwise, it is never earlier than position 0 on the given line. 230 * A newline counts as one position. 231 */ 232 void view_prev_cursor_pos( 233 ledit_view *view, 234 size_t line, size_t byte, 235 int num, int multiline, 236 size_t *line_ret, size_t *byte_ret 237 ); 238 239 /* 240 * The next 6 functions all return a line, a byte position, and a 241 * "real byte position". In the case of the "*prev*" functions, it 242 * is actually the same as the normal byte position (it is just 243 * returned to keep the interface the same), but in the case of the 244 * "*next*" functions, it can be different. For instance, when 245 * moving forward to the end of a word, the normal byte index will 246 * be before the last cursor of the word (i.e. the position of the 247 * cursor highlight in normal mode), while the real byte index is 248 * right after the word, so it can be used for deleting to the end 249 * of the word. 250 */ 251 252 /* 253 * Words are defined by unicode semantics (as interpreted by pango), 254 * while bigwords are simply blocks of non-whitespace characters. 255 */ 256 257 void view_next_word( 258 ledit_view *view, size_t line, size_t byte, int num_repeat, 259 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 260 ); 261 void view_next_word_end( 262 ledit_view *view, size_t line, size_t byte, int num_repeat, 263 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 264 ); 265 void view_next_bigword( 266 ledit_view *view, size_t line, size_t byte, int num_repeat, 267 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 268 ); 269 void view_next_bigword_end( 270 ledit_view *view, size_t line, size_t byte, int num_repeat, 271 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 272 ); 273 void view_prev_word( 274 ledit_view *view, size_t line, size_t byte, int num_repeat, 275 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 276 ); 277 void view_prev_bigword( 278 ledit_view *view, size_t line, size_t byte, int num_repeat, 279 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 280 ); 281 282 /* 283 * Get the byte position of the next non-whitespace character starting at 284 * 'byte' (including 'byte' itself), or the length of the line if there is 285 * no further non-whitespace character. 286 */ 287 size_t view_line_next_non_whitespace(ledit_view *view, size_t line, size_t byte); 288 289 /* 290 * Get the byte boundary of the softline at line 'line' and byte position 'pos'. 291 */ 292 void view_get_pos_softline_bounds( 293 ledit_view *view, size_t line, size_t pos, 294 size_t *start_byte_ret, size_t *end_byte_ret 295 ); 296 297 /* 298 * Get the byte boundary of the softline with index 'softline' 299 * in the hardline 'line'. 300 */ 301 void view_get_softline_bounds( 302 ledit_view *view, size_t line, int softline, 303 size_t *start_byte_ret, size_t *end_byte_ret 304 ); 305 306 /* 307 * Get the number of softlines in line 'line'. 308 */ 309 int view_get_softline_count(ledit_view *view, size_t line); 310 311 /* 312 * Get the softline index at hardline 'line' and byte position 'pos'. 313 */ 314 int view_pos_to_softline(ledit_view *view, size_t line, size_t pos); 315 316 /* 317 * Get the pixel position and height of the cursor on hardline 'line' 318 * at byte position 'pos'. 319 */ 320 void view_get_cursor_pixel_pos(ledit_view *view, size_t line, size_t pos, int *x_ret, int *y_ret, int *h_ret); 321 322 /* 323 * Get the byte index of the cursor if it is moved visually 'movement' 324 * positions from the position as line 'line' and byte position 'pos', 325 * where a negative number is to the left and a positive number to the 326 * right. 327 * If 'prev_index_ret' is not NULL, the previous valid cursor position 328 * is written to it - this is used in normal mode to move back one 329 * position if the cursor is at the end of the line. For some reason, 330 * using 'view_get_legal_normal_pos' doesn't work here. I still need 331 * to figure out why. 332 */ 333 size_t view_move_cursor_visually(ledit_view *view, size_t line, size_t pos, int movement, size_t *prev_index_ret); 334 335 /* 336 * Convert a line index and byte position to an x position and softline 337 * index. The x position is in pango units, not pixels. 338 * In normal mode, the middle of the character is returned instead of the 339 * beginning. 340 */ 341 void view_pos_to_x_softline(ledit_view *view, size_t line, size_t pos, int *x_ret, int *softline_ret); 342 343 /* 344 * Convert a line index, softline index, and x position (in pango units, 345 * not pixels) to a byte position. 346 * In insert mode, the returned byte position is the closest cursor 347 * position. In normal mode, it is simply the beginning of the character 348 * (or, rather, grapheme) that the x position was on, regardless of where 349 * on that character the position was. 350 */ 351 size_t view_x_softline_to_pos(ledit_view *view, size_t line, int x, int softline); 352 353 /* 354 * Get a legal normal mode position, i.e. move back one cursor position 355 * if 'pos' is at the very end of the line. 356 */ 357 size_t view_get_legal_normal_pos(ledit_view *view, size_t line, size_t pos); 358 359 /* 360 * Delete a range according to a delete_mode. 361 * The line and byte indeces do not need to be sorted (in fact, they often 362 * shouldn't be, as shown in the next sentence). 363 * If 'delmode' is DELETE_HARDLINE or DELETE_SOFTLINE, 'line_index1' and 364 * 'byte_index1' are used to determine where the cursor should be after 365 * the deletion. This new position is written to 'new_line_ret' and 366 * 'new_byte_ret'. 367 * If 'delmode' is DELETE_SOFTLINE, the byte indeces are additionally used 368 * to determine which softlines the range bounds are on. 369 * Both line deletion modes make sure that there is at least one line left 370 * in the buffer afterwards, although it may have its text deleted. 371 * If 'delmode' is DELETE_CHAR, the exact specified range is deleted, and 372 * the new line and byte are simply the beginning of the range. 373 * The deleted text is written to 'text_ret'. 374 * In normal mode, the new cursor index is always at a valid normal mode 375 * position. 376 * All return arguments may be NULL. 377 * The deletion is added to the undo stack with 'start_undo_group' 378 * specifying whether a new undo group should be started. 379 * The start cursor position for the undo stack is taken directly from 380 * the view's current position. The end cursor position is the same as 381 * what is returned in 'new_line_ret' and 'new_byte_ret', except that it 382 * is set before calling 'view_get_legal_normal_pos'. 383 * If different cursor positions are needed, call 384 * 'undo_change_last_cur_range' afterwards. 385 * This function does not recalculate the line heights or offsets. 386 */ 387 void view_delete_range_base( 388 ledit_view *view, 389 enum delete_mode delmode, int start_undo_group, 390 size_t line_index1, size_t byte_index1, 391 size_t line_index2, size_t byte_index2, 392 size_t *new_line_ret, size_t *new_byte_ret, 393 txtbuf *text_ret 394 ); 395 396 /* 397 * Same as 'view_delete_range_base', but the line heights and offsets of 398 * all views are recalculated afterwards. 399 */ 400 void view_delete_range( 401 ledit_view *view, 402 enum delete_mode delmode, int start_undo_group, 403 size_t line_index1, size_t byte_index1, 404 size_t line_index2, size_t byte_index2, 405 size_t *new_line_ret, size_t *new_byte_ret, 406 txtbuf *text_ret 407 ); 408 409 /* 410 * Resize the size of the textview, i.e. resize the line widths 411 * and update all scrolling related data. 412 * 'data' is the view, but is given as a void pointer so the 413 * function can be used as a callback. 414 */ 415 void view_resize_textview(void *data); 416 417 /* 418 * Scroll to the given pixel offset. 419 * The given offset is sanity-checked so new illegal positions can result. 420 */ 421 void view_scroll(ledit_view *view, long new_offset); 422 423 /* 424 * Get the position nearest to 'line' and 'byte' that is currently shown 425 * on screen. 426 */ 427 void view_get_nearest_legal_pos( 428 ledit_view *view, 429 size_t line, size_t byte, 430 /*int snap_to_nearest, int snap_middle, FIXME: take these parameters */ 431 size_t *line_ret, size_t *byte_ret 432 ); 433 434 /* 435 * Convert pixel coordinates to line and byte indeces. The pixel coordinates 436 * are relative to the current textview. 437 * If 'snap_to_nearest' is set, but grapheme boundary nearest to the position 438 * is returned. Otherwise, the start position of the grapheme under the position 439 * is returned. 440 */ 441 void view_xy_to_line_byte(ledit_view *view, int x, int y, int snap_to_nearest, size_t *line_ret, size_t *byte_ret); 442 443 /* 444 * Scroll so that the given cursor position is at the very top of the view. 445 * Note that this may not be entirely true since the final position is 446 * sanity-checked to be within the scroll bounds. 447 */ 448 void view_scroll_to_pos_top(ledit_view *view, size_t line, size_t byte); 449 450 /* 451 * Scroll so that the given cursor position is at the very bottom of the view. 452 * Note that this may not be entirely true since the final position is 453 * sanity-checked to be within the scroll bounds. 454 */ 455 void view_scroll_to_pos_bottom(ledit_view *view, size_t line, size_t byte); 456 457 /* 458 * Scroll so that the current cursor position is visible on screen. 459 */ 460 void view_ensure_cursor_shown(ledit_view *view); 461 462 /* 463 * Clear the selection. 464 */ 465 void view_wipe_selection(ledit_view *view); 466 467 /* 468 * Set the selection to the given range. 469 * The range does not need to be sorted. 470 */ 471 void view_set_selection(ledit_view *view, size_t line1, size_t byte1, size_t line2, size_t byte2); 472 473 /* 474 * Redraw the view. 475 * This only redraws if the redraw bit of the view or window are set. 476 * This should all be set automatically. 477 */ 478 void view_redraw(ledit_view *view, size_t lang_index); 479 /* FIXME: kind of ugly to pass lang_index here, but the window needs it - maybe store centrally somewhere? */ 480 481 /* 482 * Perform up to num undo steps. 483 * The cursor position of the view is set to the stored position 484 * in the undo stack. 485 * The line heights and offsets are recalculated. 486 */ 487 void view_undo(ledit_view *view, int num); 488 489 /* 490 * Perform up to num redo steps. 491 * The cursor position of the view is set to the stored position 492 * in the undo stack. 493 * The line heights and offsets are recalculated. 494 */ 495 void view_redo(ledit_view *view, int num); 496 497 /* 498 * Paste the X11 clipboard at the current cursor position. 499 */ 500 void view_paste_clipboard(ledit_view *view); 501 502 /* 503 * Paste the X11 primary selection at the current cursor position. 504 */ 505 void view_paste_primary(ledit_view *view); 506 507 #endif