ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit 1146213bf1660a36ffc9269f938602905847d554
parent 7ce0fd78813ad0ebd4292b7dd471528f09417d35
Author: lumidify <nobody@lumidify.org>
Date:   Thu,  2 Dec 2021 22:56:26 +0100

Add documentation for window

Diffstat:
Mledit.c | 1+
Mwindow.c | 40+++++++++++++++++++++++++++++++++-------
Mwindow.h | 242++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 256 insertions(+), 27 deletions(-)

diff --git a/ledit.c b/ledit.c @@ -1,3 +1,4 @@ +/* FIXME: Add special assert that dumps currently edited file to backup on error */ /* FIXME: On large files, expose event takes a long time for some reason -> but somehow only sometimes... */ /* FIXME: generally optimize redrawing */ diff --git a/window.c b/window.c @@ -25,33 +25,59 @@ /* FIXME: Everything to do with the bottom bar is extremely hacky */ struct bottom_bar { /* FIXME: encapsulate layout, width, draw a bit */ + /* text display of mode and possible some further text */ PangoLayout *mode; ledit_draw *mode_draw; int mode_w, mode_h; - PangoLayout *ruler; /* not implemented yet */ + + /* line and position display (not implemented yet - FIXME) */ + PangoLayout *ruler; ledit_draw *ruler_draw; int ruler_w, ruler_h; + + /* message or editable text display */ PangoLayout *line; ledit_draw *line_draw; int line_w, line_h; char *line_text; int line_alloc, line_len; - int line_cur_pos; - int min_pos; /* minimum position cursor can be at */ + int line_cur_pos; /* current position of cursor */ + int min_pos; /* minimum position cursor can be at */ }; /* clipboard handling largely stolen from st (simple terminal) */ #define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit))) +/* FIXME: maybe move this to the window struct just in case any + conflicts happen */ +/* FIXME: the paste handling is a bit weird because the text can come + in several chunks - can this cause issues in certain cases? */ struct { txtbuf *primary; char *clipboard; } xsel = {NULL, NULL}; +/* + * Recalculate the size of the actual text area (which is managed by the view). + */ static void recalc_text_size(ledit_window *window); + +/* + * Get the position and height for the scrollbar handle. + * 'height_ret' is set to the height (in pixels) of the scrollbar handle. + * 'pos_ret' is set to the y position (in pixels) of the top of the scrollbar handle. + */ static void get_scroll_pos_height(ledit_window *windown, double *pos, double *height); + +/* + * Set the scroll offset. + * 'pos' is the pixel position of the top of the scrollbar handle. + * This performs sanity checks and calls the scroll callback if set. + */ static void set_scroll_pos(ledit_window *window, double pos); + +/* event handling for clipboard events */ static void clipboard_propnotify(ledit_window *window, XEvent *e); static void clipboard_selnotify(ledit_window *window, XEvent *e); static void clipboard_selrequest(ledit_window *window, XEvent *e); @@ -291,10 +317,10 @@ window_set_mode_extra_text(ledit_window *window, char *text) { /* FIXME: give these functions more sensible names */ static void -get_scroll_pos_height(ledit_window *window, double *pos, double *height) { - *height = ((double)window->text_h / window->scroll_max) * window->text_h; - *pos = (window->scroll_offset / - (window->scroll_max - window->text_h)) * (window->text_h - *height); +get_scroll_pos_height(ledit_window *window, double *pos_ret, double *height_ret) { + *height_ret = ((double)window->text_h / window->scroll_max) * window->text_h; + *pos_ret = (window->scroll_offset / + (window->scroll_max - window->text_h)) * (window->text_h - *height_ret); } static void diff --git a/window.h b/window.h @@ -1,33 +1,45 @@ +/* + * A window is associated with exactly one view and is responsible everything + * other than the actual text handling (of the text in the buffer). + * It's a bit ugly right now because the line editor for commands is implemented + * partially here and partially in keys_command, but that's the way it is for now. + */ + typedef struct bottom_bar bottom_bar; typedef struct { + /* Pango stuff */ /* FIXME: maybe move to common? */ PangoFontMap *fontmap; PangoContext *context; PangoFontDescription *font; + + /* X stuff */ GC gc; Window xwin; - XdbeBackBuffer back_buf; - Drawable drawable; - int w; - int h; - int text_w; - int text_h; - int scroll_dragging; - int scroll_grab_handle; - long scroll_max; - double scroll_offset; /* double for smoother scrolling */ - int bottom_text_shown; - int message_shown; + XdbeBackBuffer back_buf; /* the back buffer for double buffering */ + Drawable drawable; /* the actual drawable to draw to */ + /* this is currently always the same as back_buf, + but that might be changed at some point */ XSetWindowAttributes wattrs; - Atom wm_delete_msg; - Atom xtarget; - bottom_bar *bb; - int bb_msg_shown; - int redraw; - enum ledit_mode mode; /* a bit ugly to duplicate this here... */ - - /* filtered events */ + Atom wm_delete_msg; /* used to check when window is closed */ + Atom xtarget; /* used for clipboard handling */ + + int w; /* width of window */ + int h; /* height of window */ + int text_w; /* width of the text part of the window */ + int text_h; /* height of the text part of the window */ + int scroll_dragging; /* whether scrollbar is being dragged with mouse */ + int scroll_grab_handle; /* the y position where the mouse was was while dragging the scrollbar */ + long scroll_max; /* total pixel height of displayed text */ + double scroll_offset; /* double for smoother scrolling */ + int bottom_text_shown; /* whether editable text is shown at the bottom */ + int message_shown; /* whether a readonly message is shown at the bottom */ + bottom_bar *bb; /* encapsulates the text at the bottom */ + int redraw; /* whether something has changed and the window has to be redrawn */ + enum ledit_mode mode; /* mode of the view - a bit ugly to duplicate this here... */ + + /* stuff for filtering events so not too many have to be handled */ struct timespec last_scroll; struct timespec last_motion; struct timespec last_resize; @@ -48,6 +60,8 @@ typedef struct { ledit_common *common; ledit_theme *theme; + + /* various callbacks */ void (*paste_callback)(void *, char *, size_t); void (*scroll_callback)(void *, long); void (*button_callback)(void *, XEvent *); @@ -56,56 +70,244 @@ typedef struct { void *scroll_cb_data; void *button_cb_data; void *resize_cb_data; + + /* extra text shown beside the mode display at the bottom */ char *mode_extra_text; } ledit_window; +/* + * Create a window with initial mode 'mode'. + */ ledit_window *window_create(ledit_common *common, ledit_theme *theme, enum ledit_mode mode); + +/* + * Destroy a window. + */ void window_destroy(ledit_window *window); + +/* + * Clean up global data. + */ void window_cleanup(void); /* FIXME: this is a bit confusing because there's a difference between editable text shown and non-editable message shown */ + +/* + * Move the cursor of the editable text at the bottom movement cursor positions. + * Negative movement means to the left, positive movement to the right. + */ void window_move_bottom_bar_cursor(ledit_window *window, int movement); + +/* + * Delete a unicode character from he editable text. + * Negative dir means to the left of the cursor, positive to the right. + */ void window_delete_bottom_bar_char(ledit_window *window, int dir); + +/* + * Move the cursor of the editable text to position 0. + */ void window_bottom_bar_cursor_to_beginning(ledit_window *window); + +/* + * Move the cursor of the editable text to the end of the line. + */ void window_bottom_bar_cursor_to_end(ledit_window *window); + +/* + * Set the minimum byte position of the cursor of the editable text to 'pos'. + * This means that the cursor will not be allowed to go further left + * than that position (used e.g. for the ':' in commands). + */ void window_set_bottom_bar_min_pos(ledit_window *window, int pos); + +/* + * Set whether the editable text is shown. + */ void window_set_bottom_bar_text_shown(ledit_window *window, int shown); + +/* + * get whether the editable text is shown. + */ int ledit_window_bottom_bar_text_shown(ledit_window *window); + +/* + * Set the byte position of the editable text cursor to 'byte_pos'. + */ void window_set_bottom_bar_cursor(ledit_window *window, int byte_pos); + +/* + * Get the byte position of the editable text cursor. + */ int ledit_window_get_bottom_bar_cursor(ledit_window *window); + +/* + * Insert 'len' bytes of text into the editable line at the cursor position. + */ void window_insert_bottom_bar_text(ledit_window *window, char *text, int len); + +/* + * Set the text of the editable line. + */ void window_set_bottom_bar_text(ledit_window *window, char *text, int len); + +/* + * Get the text of the editable line. + */ char *window_get_bottom_bar_text(ledit_window *window); + +/* + * Show a non-editable message at the bottom. + */ void window_show_message(ledit_window *window, char *text, int len); + +/* + * Hide the non-editable message. + */ void window_hide_message(ledit_window *window); + +/* + * Get whether a non-editable message is shown. + */ int window_message_shown(ledit_window *window); + +/* + * Set the displayed mode of the window. + */ void window_set_mode(ledit_window *window, enum ledit_mode mode); + +/* + * Set extra text that is shown to the right of the mode. + */ void window_set_mode_extra_text(ledit_window *window, char *text); +/* + * Set the total pixel height of the text. + */ void window_set_scroll_max(ledit_window *window, long max); + +/* + * Set the scroll position of the window. + * This is in absolute pixels from the top of the text. + */ void window_set_scroll_pos(ledit_window *window, long pos); + +/* + * Set a callback that will be called when the user scrolls. + * The callback is called with 'data' as the first argument and + * the scroll offset as the second argument. + */ void window_set_scroll_callback(ledit_window *window, void (*cb)(void *, long), void *data); + +/* + * Set a callback that is called with text from the clipboard/primary + * selection when it becomes available after 'clipboard_paste_clipboard' + * or 'clipboard_paste_primary' is called. + * The callback is called with 'data', the text, and the length of the text. + */ void window_set_paste_callback(ledit_window *window, void (*cb)(void *, char *, size_t), void *data); + +/* + * Set a callback that is called when Button1 is clicked or released + * in the text area. + */ void window_set_button_callback(ledit_window *window, void (*cb)(void *, XEvent *), void *data); + +/* + * Set a callback that is called when the window is resized. + */ void window_set_resize_callback(ledit_window *window, void (*cb)(void *), void *data); + +/* + * The following three functions are used to register events that + * need to be filtered in order to avoid processing too many events + * (which leads to lagging). + */ void window_register_resize(ledit_window *window, XEvent *event); void window_register_button_press(ledit_window *window, XEvent *event); void window_register_motion(ledit_window *window, XEvent *event); + +/* + * Check if any of the previously registered events should be handled + * now. This should be called every frame to check if processin is + * necessary. + */ void window_handle_filtered_events(ledit_window *window); +/* + * Clear the window. + */ void window_clear(ledit_window *window); + +/* + * Redraw the window. + * This only redraws the parts mANAGED BY THE window. + * The text area needs to be redrawn separately. + */ void window_redraw(ledit_window *window); + +/* + * Resize the window and call the resize callback if set. + */ void window_resize(ledit_window *window, int w, int h); + +/* + * Get the size of the actual text area (everything other than the + * scrollbar and the line at the bottom). + */ void window_get_textview_size(ledit_window *window, int *w_ret, int *h_ret); +/* + * Move the X primary selection the the clipboard. + */ void clipboard_primary_to_clipboard(ledit_window *window); + +/* + * Paste the X clipboard. The text is handed to the paste callback + * when it becomes available. + */ void clipboard_paste_clipboard(ledit_window *window); + +/* + * Paste the X primary selection. The text is handed to the paste + * callback when it becomes available. + */ void clipboard_paste_primary(ledit_window *window); + +/* + * Get the buffer used to store the text of the primary selection. + * This is sort of hacky because the view uses it to write the + * selection directly to this buffer and then set the selection + * owner. That should probably be changed at some point. + */ txtbuf *window_get_primary_clipboard_buffer(void); +/* + * Handle a button press. + * This does not filter events like the register function! + */ void window_button_press(ledit_window *window, XEvent *event, int scroll_num); + +/* + * Handle a button release. + */ void window_button_release(ledit_window *window, XEvent *event); + +/* + * Handle a button motion event. + * This does not filter events like the register function! + */ void window_drag_motion(ledit_window *window, XEvent *event); + +/* + * Handle a clipboard event (SelectionRequest, {Selection,Property}Notify). + */ void window_clipboard_event(ledit_window *window, XEvent *event); + +/* + * Set the pixel position of the input method context. + * This is used by some input method editors to show an editor at + * the position that text is being inserted at. + */ void xximspot(ledit_window *window, int x, int y);