view.h (18899B)
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 */ 116 /* ledit_view_line *view_get_line(ledit_view *view, size_t index); */ 117 118 /* This is very hacky - it's so the actual function calling view_get_line is returned in the assertion message. 119 * There probably is a better way to do this. 120 */ 121 #define view_get_line(view, index) (ledit_assert((index) < (view)->lines_num), (index) < (view)->lines_gap ? &(view)->lines[index] : &(view)->lines[(index) + (view)->lines_cap - (view)->lines_num]) 122 123 /* 124 * These notification functions are called by the buffer when text 125 * is changed in order to keep all views in sync. 126 */ 127 128 /* 129 * Notify the view that 'len' bytes of text have been inserted at 130 * line 'line' and byte position 'index'. 131 * This marks the line as dirty, adjusts the cursor position, if it 132 * is on the same line, and sets the selection to just the current 133 * cursor position, if there was a valid selection. 134 * The line heights and offsets are not recalculated. 135 */ 136 void view_notify_insert_text(ledit_view *view, size_t line, size_t index, size_t len); 137 138 /* 139 * Notify the view that 'len' bytes of text have been deleted 140 * starting at line 'line' and byte position 'index'. 141 * This marks the line as dirty, adjusts the cursor position, if it 142 * is on the same line, and sets the selection to just the current 143 * cursor position, if there was a valid selection. 144 * The line heights and offsets are not recalculated. 145 */ 146 void view_notify_delete_text(ledit_view *view, size_t line, size_t index, size_t len); 147 148 /* 149 * Notify the view that a line has been appended after line 'line'. 150 * This adjusts the cursor position if necessary and sets the selection 151 * to just the current cursor position, if there was a valid selection. 152 * The line heights and offsets are not recalculated. 153 */ 154 void view_notify_append_line(ledit_view *view, size_t line); 155 156 /* 157 * Notify the view that all lines from 'index1' to 'index2' (inclusive) 158 * have been deleted. 159 * This adjusts the cursor position if necessary and sets the selection 160 * to just the current cursor position, if there was a valid selection. 161 * The line heights and offsets are not recalculated. 162 */ 163 void view_notify_delete_lines(ledit_view *view, size_t index1, size_t index2); 164 165 /* 166 * Destroy a view and its window. 167 */ 168 void view_destroy(ledit_view *view); 169 170 /* 171 * Perform cleanup of global data. 172 */ 173 void view_cleanup(void); 174 175 /* 176 * Set a cursor highlight on the character at line 'line' and 177 * byte position 'index'. 178 */ 179 void view_set_line_cursor_attrs(ledit_view *view, size_t line, size_t index); 180 181 /* 182 * Remove cursor highlight from line 'line'. 183 */ 184 void view_wipe_line_cursor_attrs(ledit_view *view, size_t line); 185 186 /* 187 * Recalculate the height of line 'line'. 188 * If it has changed, the offsets of all following lines are recalculated. 189 */ 190 void view_recalc_line(ledit_view *view, size_t line); 191 192 /* 193 * Recalculate the height and offset of all lines starting at 'line'. 194 * If 'line' is 0, the offset is set to 0. 195 */ 196 void view_recalc_from_line(ledit_view *view, size_t line); 197 198 /* 199 * Shortcut for recalculating all lines starting at 0. 200 */ 201 void view_recalc_all_lines(ledit_view *view); 202 203 /* 204 * The cursor movement functions here logically belong to the buffer, 205 * but they use various unicode attributes that pango exposes, so 206 * they have to be here as long as no separate library for unicode 207 * processing is used. 208 */ 209 210 /* 211 * Get the line and byte position of the cursor position 'num' positions 212 * after the position at line 'line' and byte position 'byte'. The new 213 * position is returned in 'line_ret' and 'byte_ret'. 214 * If multiline is non-zero, the new position may be on a different line. 215 * Otherwise, it is at most the length of the given line. 216 * A newline counts as one position. 217 */ 218 void view_next_cursor_pos( 219 ledit_view *view, 220 size_t line, size_t byte, 221 int num, int multiline, 222 size_t *line_ret, size_t *byte_ret 223 ); 224 225 /* 226 * Get the line and byte position of the cursor position 'num' positions 227 * before the position at line 'line' and byte position 'byte'. The new 228 * position is returned in 'line_ret' and 'byte_ret'. 229 * If multiline is non-zero, the new position may be on a different line. 230 * Otherwise, it is never earlier than position 0 on the given line. 231 * A newline counts as one position. 232 */ 233 void view_prev_cursor_pos( 234 ledit_view *view, 235 size_t line, size_t byte, 236 int num, int multiline, 237 size_t *line_ret, size_t *byte_ret 238 ); 239 240 /* 241 * The next 6 functions all return a line, a byte position, and a 242 * "real byte position". In the case of the "*prev*" functions, it 243 * is actually the same as the normal byte position (it is just 244 * returned to keep the interface the same), but in the case of the 245 * "*next*" functions, it can be different. For instance, when 246 * moving forward to the end of a word, the normal byte index will 247 * be before the last cursor of the word (i.e. the position of the 248 * cursor highlight in normal mode), while the real byte index is 249 * right after the word, so it can be used for deleting to the end 250 * of the word. 251 */ 252 253 /* 254 * Words are defined by unicode semantics (as interpreted by pango), 255 * while bigwords are simply blocks of non-whitespace characters. 256 */ 257 258 void view_next_word( 259 ledit_view *view, size_t line, size_t byte, int num_repeat, 260 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 261 ); 262 void view_next_word_end( 263 ledit_view *view, size_t line, size_t byte, int num_repeat, 264 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 265 ); 266 void view_next_bigword( 267 ledit_view *view, size_t line, size_t byte, int num_repeat, 268 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 269 ); 270 void view_next_bigword_end( 271 ledit_view *view, size_t line, size_t byte, int num_repeat, 272 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 273 ); 274 void view_prev_word( 275 ledit_view *view, size_t line, size_t byte, int num_repeat, 276 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 277 ); 278 void view_prev_bigword( 279 ledit_view *view, size_t line, size_t byte, int num_repeat, 280 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret 281 ); 282 283 /* 284 * Get the byte position of the next non-whitespace character starting at 285 * 'byte' (including 'byte' itself), or the length of the line if there is 286 * no further non-whitespace character. 287 */ 288 size_t view_line_next_non_whitespace(ledit_view *view, size_t line, size_t byte); 289 290 /* 291 * Get the byte boundary of the softline at line 'line' and byte position 'pos'. 292 */ 293 void view_get_pos_softline_bounds( 294 ledit_view *view, size_t line, size_t pos, 295 size_t *start_byte_ret, size_t *end_byte_ret 296 ); 297 298 /* 299 * Get the byte boundary of the softline with index 'softline' 300 * in the hardline 'line'. 301 */ 302 void view_get_softline_bounds( 303 ledit_view *view, size_t line, int softline, 304 size_t *start_byte_ret, size_t *end_byte_ret 305 ); 306 307 /* 308 * Get the number of softlines in line 'line'. 309 */ 310 int view_get_softline_count(ledit_view *view, size_t line); 311 312 /* 313 * Get the softline index at hardline 'line' and byte position 'pos'. 314 */ 315 int view_pos_to_softline(ledit_view *view, size_t line, size_t pos); 316 317 /* 318 * Get the pixel position and height of the cursor on hardline 'line' 319 * at byte position 'pos'. 320 */ 321 void view_get_cursor_pixel_pos(ledit_view *view, size_t line, size_t pos, int *x_ret, int *y_ret, int *h_ret); 322 323 /* 324 * Get the byte index of the cursor if it is moved visually 'movement' 325 * positions from the position as line 'line' and byte position 'pos', 326 * where a negative number is to the left and a positive number to the 327 * right. 328 * If 'prev_index_ret' is not NULL, the previous valid cursor position 329 * is written to it - this is used in normal mode to move back one 330 * position if the cursor is at the end of the line. For some reason, 331 * using 'view_get_legal_normal_pos' doesn't work here. I still need 332 * to figure out why. 333 */ 334 size_t view_move_cursor_visually(ledit_view *view, size_t line, size_t pos, int movement, size_t *prev_index_ret); 335 336 /* 337 * Convert a line index and byte position to an x position and softline 338 * index. The x position is in pango units, not pixels. 339 * In normal mode, the middle of the character is returned instead of the 340 * beginning. 341 */ 342 void view_pos_to_x_softline(ledit_view *view, size_t line, size_t pos, int *x_ret, int *softline_ret); 343 344 /* 345 * Convert a line index, softline index, and x position (in pango units, 346 * not pixels) to a byte position. 347 * In insert mode, the returned byte position is the closest cursor 348 * position. In normal mode, it is simply the beginning of the character 349 * (or, rather, grapheme) that the x position was on, regardless of where 350 * on that character the position was. 351 */ 352 size_t view_x_softline_to_pos(ledit_view *view, size_t line, int x, int softline); 353 354 /* 355 * Get a legal normal mode position, i.e. move back one cursor position 356 * if 'pos' is at the very end of the line. 357 */ 358 size_t view_get_legal_normal_pos(ledit_view *view, size_t line, size_t pos); 359 360 /* 361 * Delete a range according to a delete_mode. 362 * The line and byte indeces do not need to be sorted (in fact, they often 363 * shouldn't be, as shown in the next sentence). 364 * If 'delmode' is DELETE_HARDLINE or DELETE_SOFTLINE, 'line_index1' and 365 * 'byte_index1' are used to determine where the cursor should be after 366 * the deletion. This new position is written to 'new_line_ret' and 367 * 'new_byte_ret'. 368 * If 'delmode' is DELETE_SOFTLINE, the byte indeces are additionally used 369 * to determine which softlines the range bounds are on. 370 * Both line deletion modes make sure that there is at least one line left 371 * in the buffer afterwards, although it may have its text deleted. 372 * If 'delmode' is DELETE_CHAR, the exact specified range is deleted, and 373 * the new line and byte are simply the beginning of the range. 374 * The deleted text is written to 'text_ret'. 375 * In normal mode, the new cursor index is always at a valid normal mode 376 * position. 377 * All return arguments may be NULL. 378 * The deletion is added to the undo stack with 'start_undo_group' 379 * specifying whether a new undo group should be started. 380 * The start cursor position for the undo stack is taken directly from 381 * the view's current position. The end cursor position is the same as 382 * what is returned in 'new_line_ret' and 'new_byte_ret', except that it 383 * is set before calling 'view_get_legal_normal_pos'. 384 * If different cursor positions are needed, call 385 * 'undo_change_last_cur_range' afterwards. 386 * This function does not recalculate the line heights or offsets. 387 */ 388 void view_delete_range_base( 389 ledit_view *view, 390 enum delete_mode delmode, int start_undo_group, 391 size_t line_index1, size_t byte_index1, 392 size_t line_index2, size_t byte_index2, 393 size_t *new_line_ret, size_t *new_byte_ret, 394 txtbuf *text_ret 395 ); 396 397 /* 398 * Same as 'view_delete_range_base', but the line heights and offsets of 399 * all views are recalculated afterwards. 400 */ 401 void view_delete_range( 402 ledit_view *view, 403 enum delete_mode delmode, int start_undo_group, 404 size_t line_index1, size_t byte_index1, 405 size_t line_index2, size_t byte_index2, 406 size_t *new_line_ret, size_t *new_byte_ret, 407 txtbuf *text_ret 408 ); 409 410 /* 411 * Resize the size of the textview, i.e. resize the line widths 412 * and update all scrolling related data. 413 * 'data' is the view, but is given as a void pointer so the 414 * function can be used as a callback. 415 */ 416 void view_resize_textview(void *data); 417 418 /* 419 * Scroll to the given pixel offset. 420 * The given offset is sanity-checked so new illegal positions can result. 421 */ 422 void view_scroll(ledit_view *view, long new_offset); 423 424 /* 425 * Get the position nearest to 'line' and 'byte' that is currently shown 426 * on screen. 427 */ 428 void view_get_nearest_legal_pos( 429 ledit_view *view, 430 size_t line, size_t byte, 431 /*int snap_to_nearest, int snap_middle, FIXME: take these parameters */ 432 size_t *line_ret, size_t *byte_ret 433 ); 434 435 /* 436 * Convert pixel coordinates to line and byte indeces. The pixel coordinates 437 * are relative to the current textview. 438 * If 'snap_to_nearest' is set, but grapheme boundary nearest to the position 439 * is returned. Otherwise, the start position of the grapheme under the position 440 * is returned. 441 */ 442 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); 443 444 /* 445 * Scroll so that the given cursor position is at the very top of the view. 446 * Note that this may not be entirely true since the final position is 447 * sanity-checked to be within the scroll bounds. 448 */ 449 void view_scroll_to_pos_top(ledit_view *view, size_t line, size_t byte); 450 451 /* 452 * Scroll so that the given cursor position is at the very bottom of the view. 453 * Note that this may not be entirely true since the final position is 454 * sanity-checked to be within the scroll bounds. 455 */ 456 void view_scroll_to_pos_bottom(ledit_view *view, size_t line, size_t byte); 457 458 /* 459 * Scroll so that the current cursor position is visible on screen. 460 */ 461 void view_ensure_cursor_shown(ledit_view *view); 462 463 /* 464 * Clear the selection. 465 */ 466 void view_wipe_selection(ledit_view *view); 467 468 /* 469 * Set the selection to the given range. 470 * The range does not need to be sorted. 471 */ 472 void view_set_selection(ledit_view *view, size_t line1, size_t byte1, size_t line2, size_t byte2); 473 474 /* 475 * Redraw the view. 476 * This only redraws if the redraw bit of the view or window are set. 477 * This should all be set automatically. 478 */ 479 void view_redraw(ledit_view *view, size_t lang_index); 480 /* FIXME: kind of ugly to pass lang_index here, but the window needs it - maybe store centrally somewhere? */ 481 482 /* 483 * Perform up to num undo steps. 484 * The cursor position of the view is set to the stored position 485 * in the undo stack. 486 * The line heights and offsets are recalculated. 487 */ 488 void view_undo(ledit_view *view, int num); 489 490 /* 491 * Perform up to num redo steps. 492 * The cursor position of the view is set to the stored position 493 * in the undo stack. 494 * The line heights and offsets are recalculated. 495 */ 496 void view_redo(ledit_view *view, int num); 497 498 /* 499 * Paste the X11 clipboard at the current cursor position. 500 */ 501 void view_paste_clipboard(ledit_view *view); 502 503 /* 504 * Paste the X11 primary selection at the current cursor position. 505 */ 506 void view_paste_primary(ledit_view *view); 507 508 #endif