summaryrefslogtreecommitdiff
path: root/ieditor.pl
diff options
context:
space:
mode:
Diffstat (limited to 'ieditor.pl')
-rw-r--r--ieditor.pl117
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.