commit a3b601c93fde71dd598f855980897a1e3ead492e
parent 7a93ac1c6f53c9464eb548bef555f22da0d9bbac
Author: lumidify <nobody@lumidify.org>
Date: Mon, 2 Oct 2023 10:49:08 +0200
Add rudimentary support for extra line spacing
Diffstat:
7 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/configparser.c b/configparser.c
@@ -32,7 +32,7 @@ struct config {
char **langs;
size_t num_langs;
size_t alloc_langs;
-} config = {NULL};
+} config = {NULL, NULL, NULL, NULL, NULL, 0, 0};
enum toktype {
STRING,
@@ -576,6 +576,7 @@ load_destroy_theme(ledit_common *common, ast_list *theme_list, ledit_theme *them
{"text-size", &theme->text_size, &parse_theme_number, &destroy_theme_number, TEXT_SIZE, default_init},
{"scrollbar-width", &theme->scrollbar_width, &parse_theme_number, &destroy_theme_number, SCROLLBAR_WIDTH, default_init},
{"scrollbar-step", &theme->scrollbar_step, &parse_theme_number, &destroy_theme_number, SCROLLBAR_STEP, default_init},
+ {"extra-line-spacing", &theme->extra_line_spacing, &parse_theme_number, &destroy_theme_number, EXTRA_LINE_SPACING, default_init},
{"text-fg", &theme->text_fg, &parse_theme_color, &destroy_theme_color, TEXT_FG, default_init},
{"text-bg", &theme->text_bg, &parse_theme_color, &destroy_theme_color, TEXT_BG, default_init},
{"cursor-fg", &theme->cursor_fg, &parse_theme_color, &destroy_theme_color, CURSOR_FG, default_init},
@@ -664,6 +665,17 @@ load_destroy_theme(ledit_common *common, ast_list *theme_list, ledit_theme *them
}
}
+ /* FIXME: make this check part of the generic handling above (also, < 0 is already checked anyways) */
+ /* FIXME: 100 is completely arbitrary */
+ if (theme->extra_line_spacing < 0 || theme->extra_line_spacing > 100) {
+ *errstr = print_fmt(
+ "%s: Invalid value '%d' for theme setting 'extra-line-spacing' "
+ "(allowed values are 0-100)",
+ filename, theme->extra_line_spacing
+ );
+ goto cleanup;
+ }
+
return theme;
cleanup:
for (size_t i = 0; i < LENGTH(settings); i++) {
@@ -1658,7 +1670,7 @@ config_loadfile(ledit_common *common, char *filename, char **errstr) {
clock_gettime(CLOCK_MONOTONIC, &last);
#endif
- struct config cfg = {NULL};
+ struct config cfg = {NULL, NULL, NULL, NULL, NULL, 0, 0};
int theme_init = 0, bindings_init = 0, mappings_init = 0;
ast_assignment *assignment;
for (size_t i = 0; i < list.len; i++) {
diff --git a/configparser.h b/configparser.h
@@ -11,6 +11,7 @@ typedef struct {
int scrollbar_step;
int text_size;
int highlight_search;
+ int extra_line_spacing;
XftColor text_fg;
XftColor text_bg;
XftColor cursor_fg;
diff --git a/keys_basic.c b/keys_basic.c
@@ -714,10 +714,9 @@ static void
push_undo_empty_insert(ledit_view *view, size_t line, size_t index, int start_group) {
/* WARNING: Don't abuse txtbuf like this unless you're stupid like me. */
txtbuf ins_buf = {.text = "", .len = 0, .cap = 0};
- ledit_range ins_range = {.line1 = line, .byte1 = index, .line2 = line, .byte2 = index};
- ledit_range cur_range = {.line1 = line, .byte1 = index, .line2 = line, .byte2 = index};
+ ledit_range range = {.line1 = line, .byte1 = index, .line2 = line, .byte2 = index};
undo_push_insert(
- view->buffer->undo, &ins_buf, ins_range, cur_range, start_group, view->mode
+ view->buffer->undo, &ins_buf, range, range, start_group, view->mode
);
}
diff --git a/leditrc.5 b/leditrc.5
@@ -1,4 +1,4 @@
-.Dd October 22, 2022
+.Dd October 2, 2023
.Dt LEDITRC 5
.Os
.Sh NAME
@@ -175,6 +175,11 @@ Note that the mode is automatically switched to visual when this is set and a wo
This is a bit weird, but in order to keep everything a bit more consistent, selections are curently
only allowed in visual mode.
Default: true
+.It Ar extra-line-spacing
+Extra space between each line (in pixels).
+Note that this is very rudimentary at the moment.
+In particular, selections covering multiple lines do not highlight the extra space.
+Default: 0
.El
.Sh BINDINGS
The key bindings may be configured by assigning
diff --git a/leditrc.example b/leditrc.example
@@ -19,6 +19,7 @@ theme = {
scrollbar-bg = CCCCCC
scrollbar-fg = 000000
highlight-search = true
+ extra-line-spacing = 0
}
bindings = {
diff --git a/theme_config.h b/theme_config.h
@@ -49,4 +49,7 @@ static const char *SCROLLBAR_FG = "#000000";
/* FIXME: this should maybe be in a separate "general config" section */
static const char *HIGHLIGHT_SEARCH = "true";
+/* extra space between lines (in pixels) */
+static const char *EXTRA_LINE_SPACING = "0";
+
#endif /* _THEME_CONFIG_H_ */
diff --git a/view.c b/view.c
@@ -492,6 +492,7 @@ invalidate_layout_line_helper(void *data, size_t line) {
void
view_recalc_line(ledit_view *view, size_t line) {
+ ledit_theme *theme = config_get_theme();
ledit_view_line *l = view_get_line(view, line);
if (l->text_dirty)
set_pango_text_and_highlight(view, line);
@@ -503,13 +504,13 @@ view_recalc_line(ledit_view *view, size_t line) {
if (l->h_dirty) {
l->h_dirty = 0;
/* FIXME: maybe also check overflow for offset? */
- long off = l->y_offset + l->h;
+ long off = l->y_offset + l->h + theme->extra_line_spacing;
for (size_t i = line + 1; i < view->lines_num; i++) {
l = view_get_line(view, i);
l->y_offset = off;
- off += l->h;
+ off += l->h + theme->extra_line_spacing;
}
- view->total_height = off;
+ view->total_height = off - theme->extra_line_spacing;
if (l->y_offset < view->display_offset + text_h)
view->redraw = 1;
}
@@ -524,6 +525,7 @@ view_recalc_line(ledit_view *view, size_t line) {
void
view_recalc_from_line(ledit_view *view, size_t line) {
+ ledit_theme *theme = config_get_theme();
ledit_view_line *l = view_get_line(view, line);
/* force first line to offset 0 */
if (line == 0)
@@ -539,9 +541,9 @@ view_recalc_from_line(ledit_view *view, size_t line) {
set_pango_text_and_highlight(view, i);
l->h_dirty = 0;
l->y_offset = off;
- off += l->h;
+ off += l->h + theme->extra_line_spacing;
}
- view->total_height = off;
+ view->total_height = off - theme->extra_line_spacing;
window_set_scroll_max(view->window, view->total_height);
view_scroll(view, view->display_offset);
}
@@ -1071,6 +1073,7 @@ ledit_line_word_boundaries(ledit_line *line, int byte, int *start_ret, int *end_
static void
set_pango_text_and_highlight(ledit_view *view, size_t line) {
cache_layout *cl;
+ ledit_theme *theme = config_get_theme();
ledit_line *ll = buffer_get_line(view->buffer, line);
ledit_view_line *vl = view_get_line(view, line);
char old_valid = vl->cache_layout_valid;
@@ -1087,6 +1090,7 @@ set_pango_text_and_highlight(ledit_view *view, size_t line) {
cl->layout = pango_layout_new(view->window->context);
pango_layout_set_font_description(cl->layout, view->window->font);
pango_layout_set_wrap(cl->layout, PANGO_WRAP_WORD_CHAR);
+ pango_layout_set_spacing(cl->layout, theme->extra_line_spacing * PANGO_SCALE);
}
if (vl->text_dirty || !old_valid) {
buffer_normalize_line(ll);
@@ -1512,6 +1516,7 @@ view_delete_range_base(
/* FIXME: any way to make this more efficient? */
void
view_resize_textview(void *data) {
+ ledit_theme *theme = config_get_theme();
ledit_view *view = (ledit_view *)data;
view->total_height = 0;
int text_w, text_h;
@@ -1524,8 +1529,9 @@ view_resize_textview(void *data) {
line->y_offset = view->total_height;
line->dirty = 1;
line->h_dirty = 0;
- view->total_height += line->h;
+ view->total_height += line->h + theme->extra_line_spacing;
}
+ view->total_height -= theme->extra_line_spacing;
window_set_scroll_max(view->window, view->total_height);
if (view->display_offset > 0 &&
view->display_offset + text_h > view->total_height) {
@@ -1547,6 +1553,7 @@ view_scroll(ledit_view *view, long new_offset) {
/* FIXME: there's gotta be a better/more efficient way to do this... */
/* FIXME: make sure h_dirty is not set here */
+/* FIXME: this might cause weird effects when used together with extra-line-spacing */
void
view_get_nearest_legal_pos(
ledit_view *view,
@@ -1648,19 +1655,19 @@ view_get_nearest_legal_pos(
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) {
- /* FIXME: store current line offset to speed this up */
- /* FIXME: use y_offset in lines */
- long h = 0;
+ ledit_theme *theme = config_get_theme();
long pos = view->display_offset + y;
for (size_t i = 0; i < view->lines_num; i++) {
ledit_view_line *vline = view_get_line(view, i);
- if ((h <= pos && h + vline->h > pos) || i == view->lines_num - 1) {
+ long y1 = vline->y_offset - (i == 0 ? 0 : theme->extra_line_spacing / 2);
+ long y2 = vline->y_offset + vline->h + theme->extra_line_spacing / 2 + theme->extra_line_spacing % 2;
+ if ((y1 <= pos && y2 > pos) || i == view->lines_num - 1) {
int index, trailing;
PangoLayout *layout = get_pango_layout(view, i);
/* FIXME: what if i == view->lines_num - 1 but pos - h < 0? */
pango_layout_xy_to_index(
layout,
- x * PANGO_SCALE, (int)(pos - h) * PANGO_SCALE,
+ x * PANGO_SCALE, (int)(pos - y1) * PANGO_SCALE,
&index, &trailing
);
*byte_ret = (size_t)index;
@@ -1674,7 +1681,6 @@ view_xy_to_line_byte(ledit_view *view, int x, int y, int snap_to_nearest, size_t
*line_ret = i;
return;
}
- h += vline->h;
}
*line_ret = 0;
*byte_ret = 0;
@@ -1894,15 +1900,16 @@ view_button_handler(void *data, XEvent *event) {
static void
view_redraw_text(ledit_view *view) {
ledit_theme *theme = config_get_theme();
- int h = 0;
int cur_line_y = 0;
int cursor_displayed = 0;
int text_w, text_h;
window_get_textview_size(view->window, &text_w, &text_h);
/* FIXME: use binary search here */
+ /* FIXME: draw extra highlight when extra-line-spacing set
+ (also between soft lines because pango doesn't do that) */
for (size_t i = 0; i < view->lines_num; i++) {
ledit_view_line *vline = view_get_line(view, i);
- if (h + vline->h > view->display_offset) {
+ if (vline->y_offset + vline->h > view->display_offset) {
/* FIXME: vline->text_dirty should not happen here */
if (vline->text_dirty || vline->highlight_dirty)
set_pango_text_and_highlight(view, i);
@@ -1910,12 +1917,12 @@ view_redraw_text(ledit_view *view) {
render_line(view, i);
}
int final_y = 0;
- int dest_y = h - view->display_offset;
+ int dest_y = vline->y_offset - view->display_offset;
int final_h = vline->h;
- if (h < view->display_offset) {
+ if (vline->y_offset < view->display_offset) {
dest_y = 0;
- final_y = view->display_offset - h;
- final_h -= view->display_offset - h;
+ final_y = view->display_offset - vline->y_offset;
+ final_h -= view->display_offset - vline->y_offset;
}
if (dest_y + final_h > text_h) {
final_h -= final_y + final_h -
@@ -1930,13 +1937,12 @@ view_redraw_text(ledit_view *view) {
0, final_y, vline->w, final_h, 0, dest_y
);
if (i == view->cur_line) {
- cur_line_y = h - view->display_offset;
+ cur_line_y = vline->y_offset - view->display_offset;
cursor_displayed = 1;
}
- if (h + vline->h >= view->display_offset + text_h)
+ if (vline->y_offset + vline->h >= view->display_offset + text_h)
break;
}
- h += vline->h;
}
XSetForeground(view->buffer->common->dpy, view->window->gc, theme->cursor_bg.pixel);