Introduction
Introduction Statistics Contact Development Disclaimer Help
tAdd initial work for selection support - 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 10a6b45de3f15406bb82817a1bf28c79d492145f
parent b4ed6ddf9920d90814860156ed32a40404ece243
Author: lumidify <[email protected]>
Date: Sat, 15 May 2021 21:07:54 +0200
Add initial work for selection support
Diffstat:
M IDEAS | 1 +
A LICENSE | 15 +++++++++++++++
M buffer.c | 19 +++++++++++++++++++
M buffer.h | 9 +++++++++
M common.h | 1 +
M ledit.c | 107 +++++++++++++++++++++++++++++…
6 files changed, 152 insertions(+), 0 deletions(-)
---
diff --git a/IDEAS b/IDEAS
t@@ -1,2 +1,3 @@
* allow editing same file in multiple places at same time (like in acme)
* add different (more basic) text backend
+* visual selection mode - allow to switch cursor between selection ends
diff --git a/LICENSE b/LICENSE
t@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2021 lumidify <[email protected]>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/buffer.c b/buffer.c
t@@ -35,6 +35,8 @@ ledit_create_buffer(ledit_common_state *state) {
buffer->end_of_soft_line = 0;
buffer->total_height = 0;
buffer->display_offset = 0;
+ buffer->sel.line1 = buffer->sel.byte1 = -1;
+ buffer->sel.line2 = buffer->sel.byte2 = -1;
ledit_append_line(buffer, -1, -1);
return buffer;
t@@ -51,6 +53,23 @@ ledit_destroy_buffer(ledit_buffer *buffer) {
}
void
+ledit_set_line_selection(ledit_buffer *buffer, int line, int start_byte, int e…
+ PangoAttribute *attr0 = pango_attr_background_new(0, 0, 0);
+ PangoAttribute *attr1 = pango_attr_foreground_new(65535, 65535, 65535);
+ attr0->start_index = start_byte;
+ attr0->end_index = end_byte;
+ attr1->start_index = start_byte;
+ attr1->end_index = end_byte;
+ PangoAttribute *attr2 = pango_attr_insert_hyphens_new(FALSE);
+ PangoAttrList *list = pango_attr_list_new();
+ pango_attr_list_insert(list, attr0);
+ pango_attr_list_insert(list, attr1);
+ pango_attr_list_insert(list, attr2);
+ pango_layout_set_attributes(buffer->lines[line].layout, list);
+ buffer->lines[line].dirty = 1;
+}
+
+void
ledit_set_line_cursor_attrs(ledit_buffer *buffer, int line, int index) {
if (buffer->state->mode == NORMAL) {
PangoAttribute *attr0 = pango_attr_background_new(0, 0, 0);
diff --git a/buffer.h b/buffer.h
t@@ -1,3 +1,10 @@
+typedef struct {
+ int line1;
+ int byte1;
+ int line2;
+ int byte2;
+} ledit_selection;
+
typedef struct ledit_buffer ledit_buffer;
/* FIXME: size_t for len, etc. */
t@@ -28,10 +35,12 @@ struct ledit_buffer {
long total_height; /* total pixel height of all lines */
double display_offset; /* current pixel offset of viewport - this
* is a double to make scrolling smoother */
+ ledit_selection sel; /* current selection; all entries -1 if no select…
};
ledit_buffer *ledit_create_buffer(ledit_common_state *state);
void ledit_destroy_buffer(ledit_buffer *buffer);
+void ledit_set_line_selection(ledit_buffer *buffer, int line, int start_byte, …
void ledit_set_line_cursor_attrs(ledit_buffer *buffer, int line, int index);
void ledit_wipe_line_cursor_attrs(ledit_buffer *buffer, int line);
void ledit_insert_text(ledit_buffer *buffer, int line_index, int index, char *…
diff --git a/common.h b/common.h
t@@ -21,6 +21,7 @@ typedef struct {
int h;
int scroll_dragging;
int scroll_grab_handle;
+ int selecting;
enum ledit_mode mode;
XIM xim;
XIC xic;
diff --git a/ledit.c b/ledit.c
t@@ -476,6 +476,7 @@ setup(int argc, char *argv[]) {
state.scroll_dragging = 0;
state.scroll_grab_handle = 0;
+ state.selecting = 0;
state.w = 500;
state.h = 500;
state.dpy = XOpenDisplay(NULL);
t@@ -536,6 +537,7 @@ setup(int argc, char *argv[]) {
InputOutput, state.vis,
CWBackPixel | CWColormap | CWBitGravity, &attrs
);
+ XSetStandardProperties(state.dpy, state.win, "ledit", NULL, None, argv…
state.back_buf = XdbeAllocateBackBufferName(
state.dpy, state.win, XdbeBackground
t@@ -711,6 +713,97 @@ redraw(void) {
XFlush(state.dpy);
}
+static void
+xy_to_line_byte(int x, int y, int *line_ret, int *byte_ret) {
+ /* FIXME: store current line offset to speed this up */
+ /* FIXME: use y_offset in lines */
+ long h = 0;
+ double pos = buffer->display_offset + y;
+ for (int i = 0; i < buffer->lines_num; i++) {
+ ledit_line *line = ledit_get_line(buffer, i);
+ if ((h <= pos && h + line->h > pos) || i == buffer->lines_num …
+ int index, trailing;
+ pango_layout_xy_to_index(
+ line->layout,
+ x * PANGO_SCALE, (int)(pos - h) * PANGO_SCALE,
+ &index, &trailing
+ );
+ /* FIXME: make this a separate, reusable function */
+ while (trailing > 0) {
+ trailing--;
+ index++;
+ while (index < line->len && ((line->text[index…
+ index++;
+ }
+ *line_ret = i;
+ *byte_ret = index;
+ break;
+ }
+ h += line->h;
+ }
+}
+
+static void
+swap(int *a, int *b) {
+ int tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+
+static void
+sort_selection(int *line1, int *byte1, int *line2, int *byte2) {
+ if (*line1 > *line2) {
+ swap(line1, line2);
+ swap(byte1, byte2);
+ } else if (*line1 == *line2 && *byte1 > *byte2) {
+ swap(byte1, byte2);
+ }
+}
+
+static void
+set_selection(int line1, int byte1, int line2, int byte2) {
+ if (line1 == buffer->sel.line1 && line2 == buffer->sel.line2 &&
+ byte1 == buffer->sel.byte1 && byte2 == buffer->sel.byte2) {
+ return;
+ }
+ if (buffer->sel.line1 >= 0) {
+ int l1_new = line1, l2_new = line2;
+ int b1_new = byte1, b2_new = byte2;
+ sort_selection(&buffer->sel.line1, &buffer->sel.byte1, &buffer…
+ sort_selection(&l1_new, &b1_new, &l2_new, &b2_new);
+ if (buffer->sel.line1 > l2_new || buffer->sel.line2 < l1_new) {
+ for (int i = buffer->sel.line1; i <= buffer->sel.line2…
+ ledit_wipe_line_cursor_attrs(buffer, i);
+ }
+ } else {
+ for (int i = buffer->sel.line1; i < l1_new; i++) {
+ ledit_wipe_line_cursor_attrs(buffer, i);
+ }
+ for (int i = buffer->sel.line2; i > l2_new; i--) {
+ ledit_wipe_line_cursor_attrs(buffer, i);
+ }
+ }
+ if (l1_new == l2_new) {
+ ledit_set_line_selection(buffer, l1_new, b1_new, b2_ne…
+ } else {
+ ledit_line *ll1 = ledit_get_line(buffer, l1_new);
+ ledit_set_line_selection(buffer, l1_new, b1_new, ll1->…
+ ledit_set_line_selection(buffer, l2_new, 0, b2_new);
+ /* FIXME: optimize this */
+ for (int i = l1_new + 1; i < l2_new; i++) {
+ if (i <= buffer->sel.line1 || i >= buffer->sel…
+ ledit_line *llx = ledit_get_line(buffe…
+ ledit_set_line_selection(buffer, i, 0,…
+ }
+ }
+ }
+ }
+ buffer->sel.line1 = line1;
+ buffer->sel.byte1 = byte1;
+ buffer->sel.line2 = line2;
+ buffer->sel.byte2 = byte2;
+}
+
static int
button_press(XEvent *event) {
int x, y;
t@@ -728,6 +821,12 @@ button_press(XEvent *event) {
set_scroll_pos(new_scroll_y);
}
return 1;
+ } else {
+ int l, b;
+ xy_to_line_byte(x, y, &l, &b);
+ set_selection(l, b, l, b);
+ state.selecting = 1;
+ return 1;
}
break;
case Button4:
t@@ -753,6 +852,7 @@ static int
button_release(XEvent *event) {
if (event->xbutton.button == Button1) {
state.scroll_dragging = 0;
+ state.selecting = 0;
return 1;
}
return 0;
t@@ -767,6 +867,12 @@ drag_motion(XEvent *event) {
state.scroll_grab_handle = event->xbutton.y;
set_scroll_pos(scroll_y);
return 1;
+ } else if (state.selecting) {
+ int l, b;
+ int y = event->xbutton.y >= 0 ? event->xbutton.y : 0;
+ xy_to_line_byte(event->xbutton.x, y, &l, &b);
+ set_selection(buffer->sel.line1, buffer->sel.byte1, l, b);
+ return 1;
}
return 0;
}
t@@ -950,6 +1056,7 @@ return_key(void) {
static void
escape_key(void) {
state.mode = NORMAL;
+ clear_key_stack();
PangoDirection dir = PANGO_DIRECTION_RTL;
int tmp_index = buffer->cur_index;
ledit_line *cur_line = ledit_get_line(buffer, buffer->cur_line);
You are viewing proxied material from lumidify.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.