URI: 
       view.h - ledit - Text editor (WIP)
  HTML git clone git://lumidify.org/ledit.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/ledit.git (encrypted, but very slow)
  HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ledit.git (over tor)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       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