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 991419d13fe4ec01c9898681cd5d9ab708486ed8
parent 0ac206aa676b56346dd45906fe0379a1e845fb80
Author: lumidify <nobody@lumidify.org>
Date:   Sat, 22 May 2021 09:47:27 +0200

Show current mode

Diffstat:
MMakefile | 4++--
Mledit.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Autil.c | 38++++++++++++++++++++++++++++++++++++++
Autil.h | 8++++++++
4 files changed, 114 insertions(+), 10 deletions(-)

diff --git a/Makefile b/Makefile @@ -9,8 +9,8 @@ MANPREFIX = ${PREFIX}/man BIN = ${NAME} MAN1 = ${BIN:=.1} -OBJ = ${BIN:=.o} cache.o buffer.o memory.o -HDR = cache.h buffer.h memory.h common.h +OBJ = ${BIN:=.o} cache.o buffer.o memory.o util.o +HDR = cache.h buffer.h memory.h common.h util.h CFLAGS_LEDIT = -g -Wall -Wextra -D_POSIX_C_SOURCE=200809L `pkg-config --cflags x11 xkbfile pangoxft xext` LDFLAGS_LEDIT = ${LDFLAGS} `pkg-config --libs x11 xkbfile pangoxft xext` -lm diff --git a/ledit.c b/ledit.c @@ -29,6 +29,7 @@ #include "common.h" #include "buffer.h" #include "cache.h" +#include "util.h" enum key_type { KEY_NONE = 0, @@ -42,6 +43,16 @@ enum key_type { KEY_ANY = 0xFF }; +struct { + /* FIXME: encapsulate layout, width, draw a bit */ + PangoLayout *mode; + ledit_draw *mode_draw; + int mode_w, mode_h; + PangoLayout *ruler; + ledit_draw *ruler_draw; + int ruler_w, ruler_h; +} bottom_bar; + struct key { char *text; /* for keys that correspond with text */ unsigned int mods; /* modifier mask */ @@ -138,6 +149,29 @@ struct { char *clipboard; } xsel; +static void +set_mode(enum ledit_mode mode) { + state.mode = mode; + switch (mode) { + case NORMAL: + pango_layout_set_text(bottom_bar.mode, "Normal", -1); + break; + case VISUAL: + pango_layout_set_text(bottom_bar.mode, "Visual", -1); + break; + case INSERT: + pango_layout_set_text(bottom_bar.mode, "Insert", -1); + break; + default: + pango_layout_set_text(bottom_bar.mode, "ledit is buggy", -1); + break; + } + pango_layout_get_pixel_size(bottom_bar.mode, &bottom_bar.mode_w, &bottom_bar.mode_h); + ledit_grow_draw(&state, bottom_bar.mode_draw, bottom_bar.mode_w, bottom_bar.mode_h); + XftDrawRect(bottom_bar.mode_draw->xftdraw, &state.bg, 0, 0, bottom_bar.mode_w, bottom_bar.mode_h); + pango_xft_render_layout(bottom_bar.mode_draw->xftdraw, &state.fg, bottom_bar.mode, 0, 0); +} + void clipcopy(void) { @@ -191,7 +225,7 @@ selnotify(XEvent *e) { unsigned long nitems, ofs, rem; int format; - unsigned char *data, *last, *repl; + unsigned char *data; Atom type, incratom, property = None; incratom = XInternAtom(state.dpy, "INCR", 0); @@ -396,7 +430,7 @@ static void key_d(void) { int num = 0; if (delete_selection()) { - state.mode = NORMAL; + set_mode(NORMAL); buffer->cur_index = ledit_get_legal_normal_pos(buffer, buffer->cur_line, buffer->cur_index); ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index); clear_key_stack(); @@ -834,7 +868,11 @@ setup(int argc, char *argv[]) { } XSetICFocus(state.xic); - state.mode = INSERT; + bottom_bar.mode = pango_layout_new(state.context); + pango_layout_set_font_description(bottom_bar.mode, state.font); + /* FIXME: only create "dummy draw" at first and create with proper size when needed */ + bottom_bar.mode_draw = ledit_create_draw(&state, 10, 10); + set_mode(INSERT); XMapWindow(state.dpy, state.win); @@ -947,6 +985,18 @@ redraw(void) { state.w - 10, (int)round(scroll_y), 10, (int)round(scroll_h) ); } + XSetForeground(state.dpy, state.gc, state.bg.pixel); + XFillRectangle( + state.dpy, state.drawable, state.gc, + 0, state.h - bottom_bar.mode_h, + state.w - 10, bottom_bar.mode_h + ); + XCopyArea( + state.dpy, bottom_bar.mode_draw->pixmap, + state.drawable, state.gc, + 0, 0, bottom_bar.mode_w, bottom_bar.mode_h, + state.w - 10 - bottom_bar.mode_w, state.h - bottom_bar.mode_h + ); XdbeSwapInfo swap_info; swap_info.swap_window = state.win; @@ -1124,7 +1174,7 @@ button_press(XEvent *event) { set_selection(l, b, l, b); if (state.mode == NORMAL) { ledit_wipe_line_cursor_attrs(buffer, buffer->cur_line); - state.mode = VISUAL; + set_mode(VISUAL); } buffer->cur_line = l; buffer->cur_index = b; @@ -1379,9 +1429,9 @@ escape_key(void) { if (state.mode == INSERT && (buffer->sel.line1 != buffer->sel.line2 || buffer->sel.byte1 != buffer->sel.byte2)) { - state.mode = VISUAL; + set_mode(VISUAL); } else { - state.mode = NORMAL; + set_mode(NORMAL); clear_key_stack(); PangoDirection dir = PANGO_DIRECTION_RTL; int tmp_index = buffer->cur_index; @@ -1395,6 +1445,14 @@ escape_key(void) { } else { cursor_left(); } + if (buffer->sel.line1 != buffer->sel.line2) { + int min = buffer->sel.line1 < buffer->sel.line2 ? buffer->sel.line1 : buffer->sel.line2; + int max = buffer->sel.line1 > buffer->sel.line2 ? buffer->sel.line1 : buffer->sel.line2; + for (int i = min; i <= max; i++) { + ledit_wipe_line_cursor_attrs(buffer, i); + } + } + /* FIXME: optimize this to avoid first wiping and then setting the attrs */ ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index); } } @@ -1403,7 +1461,7 @@ static void enter_insert(void) { if (state.mode == NORMAL) ledit_wipe_line_cursor_attrs(buffer, buffer->cur_line); - state.mode = INSERT; + set_mode(INSERT); clear_key_stack(); } @@ -1489,7 +1547,7 @@ cursor_to_beginning(void) { static void enter_visual(void) { - state.mode = VISUAL; + set_mode(VISUAL); buffer->sel.line1 = buffer->sel.line2 = buffer->cur_line; buffer->sel.byte1 = buffer->sel.byte2 = buffer->cur_index; ledit_wipe_line_cursor_attrs(buffer, buffer->cur_line); diff --git a/util.c b/util.c @@ -0,0 +1,38 @@ +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <pango/pangoxft.h> +#include <X11/extensions/Xdbe.h> + +#include "memory.h" +#include "common.h" +#include "util.h" + +ledit_draw * +ledit_create_draw(ledit_common_state *state, int w, int h) { + ledit_draw *draw = ledit_malloc(sizeof(ledit_draw)); + draw->w = w; + draw->h = h; + draw->pixmap = XCreatePixmap( + state->dpy, state->drawable, w, h, state->depth + ); + draw->xftdraw = XftDrawCreate( + state->dpy, draw->pixmap, state->vis, state->cm + ); + return draw; +} + +void +ledit_grow_draw(ledit_common_state *state, ledit_draw *draw, int w, int h) { + /* FIXME: sensible default pixmap sizes here */ + /* FIXME: maybe shrink the pixmaps at some point */ + if (draw->w < w || draw->h < h) { + draw->w = w > draw->w ? w + 10 : draw->w; + draw->h = h > draw->h ? h + 10 : draw->h; + XFreePixmap(state->dpy, draw->pixmap); + draw->pixmap = XCreatePixmap( + state->dpy, state->drawable, + draw->w, draw->h, state->depth + ); + XftDrawChange(draw->xftdraw, draw->pixmap); + } +} diff --git a/util.h b/util.h @@ -0,0 +1,8 @@ +typedef struct { + XftDraw *xftdraw; + Pixmap pixmap; + int w, h; +} ledit_draw; + +ledit_draw *ledit_create_draw(ledit_common_state *state, int w, int h); +void ledit_grow_draw(ledit_common_state *state, ledit_draw *draw, int w, int h);