diff options
Diffstat (limited to 'ieditor.pl')
-rw-r--r-- | ieditor.pl | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/ieditor.pl b/ieditor.pl new file mode 100644 index 0000000..8c6d3ab --- /dev/null +++ b/ieditor.pl @@ -0,0 +1,117 @@ +:- use_module(library(pce)). +:- consult(ieditor_gesture). + +:- pce_begin_class(iview, view, "Improved view"). + +initialise(V, L:label=[name], S:size=[size], D:display=[display], + E:editor=[editor]) :-> + send_super(V, initialise, L, S, D, when(E == @default, + new(ieditor), + E)), + send(V, wrap, word). + +:- pce_end_class(iview). + +:- pce_begin_class(ieditor, editor, "Improved editor"). + +initialise(E, T:text=[text_buffer], W:width=[int], + H:height=[int], M:margin=[int]) :-> + send_super(E, initialise, T, W, H, M), + send(E, wrap, word), + send(E, key_binding, '\\ed', message(E, kill_word)), + send(E, key_binding, '\\e\\C-h', message(E, backward_kill_word)). + +% Fix invisible terminals in some characters and fonts. + +insert_self(E, Times:[int], Character:[char]) :-> + send_super(E, insert_self, Times, Character), + send(E, redraw_line_before, E?caret). + +redraw_line_before(E, Index:int) :-> + "Redraw entire line before character at index":: + get(E?image, character_position, Index, Point), + get(E?image, line, Index, Line), + get(E?image, start, Line - 1, C0), + get(E?image, character_position, C0, Point0), + get(Point0, y, Y0), + get(Point, y, Y), + ( Y == Y0 + -> Height = Y + ; Height is Y - Y0 % Calculate line height. + ), + new(A, area(0, Y - Height, Point?x, Height)), + send(E?image, redraw, A). + +% Fix default (mis)behavior of keyboard-based selection. + +cursor_left(E, Arg:[int]) :-> + get(E, selection_save_mark, M), + send_super(E, cursor_left, Arg), + send(E, mark, M). +cursor_right(E, Arg:[int]) :-> + get(E, selection_save_mark, M), + send_super(E, cursor_right, Arg), + send(E, mark, M). +cursor_home(E, Arg:[int]) :-> + get(E, selection_save_mark, M), + send_super(E, cursor_home, Arg), + send(E, mark, M). +cursor_end(E, Arg:[int]) :-> + get(E, selection_save_mark, M), + send_super(E, cursor_end, Arg), + send(E, mark, M). +cursor_page_up(E, Arg:[int]) :-> + get(E, selection_save_mark, M), + send_super(E, cursor_page_up, Arg), + send(E, mark, M). +cursor_page_down(E, Arg:[int]) :-> + get(E, selection_save_mark, M), + send_super(E, cursor_page_down, Arg), + send(E, mark, M). + +selection_save_mark(E, M) :<- + ( get(E, mark_status, active) + -> get(E, mark, M) % Already selecting. + ; get(E, caret, C), + send(E, selection_origin, C), % Start new selection. + M = C + ). + +% Line up/down is handled specially, in order to attempt to move to the +% character closest to the character at the caret's original position. + +cursor_up(E, Arg:[int]) :-> + "Handle cursor up-arrow":: + send(E, cursor_updown, cursor_up, Arg). +cursor_down(E, Arg:[int]) :-> + "Handle cursor down-arrow":: + send(E, cursor_updown, cursor_down, Arg). + +cursor_updown(E, Msg, Arg:[int]) :-> + char_x(E, E?caret, X0), + get(E, selection_save_mark, M), + ( Msg == cursor_up -> send_super(E, cursor_up, Arg) + ; Msg == cursor_down -> send_super(E, cursor_down, Arg) + ), + send(E, mark, M), + char_x(E, E?caret, X), + char_x(E, E?caret - 1, X_prev), + char_x(E, E?caret + 1, X_next), + D is abs(X - X0), + D_prev is abs(X_prev - X0), + D_next is abs(X_next - X0), + ( D_next < D_prev, + D_next < D + -> send(E, forward_char) + ; ( D_prev < D_next, + D_prev < D + -> send(E, backward_char) + ; true + ) + ). + +char_x(E, Index, X) :- + get(E?image, character_position, Index, Point), + get(Point, x, X). + +:- pce_end_class. |