4 #include <gdk/gdkkeysyms.h>
8 static void mkmm(struct movement
*mm
, int count
, enum movekind kind
)
15 static void mkmm_noeolfix(struct movement
*mm
, int count
, enum movekind kind
)
17 mkmm(mm
, count
, kind
);
21 static void command_line_mode(struct vi
*vi
, char *init
);
23 static int read_movement_key(struct vi
*vi
, GdkEventKey
*event
)
25 struct movement
*mm
= &vi
->mm
;
30 mm
->arg
.m
= event
->keyval
;
36 mm
->arg
.c
= event
->keyval
;
42 memset(&vi
->mm
, 0, sizeof(vi
->mm
));
43 switch(event
->keyval
) {
48 mkmm(mm
, -1, MM_LINE
);
54 mkmm(mm
, -1, MM_CHAR
);
60 mkmm(mm
, 1, MM_WORDEND
);
63 mkmm(mm
, -1, MM_WORDSTART
);
66 mkmm(mm
, 1, MM_WORDSTART
);
69 mkmm(mm
, 1, MM_FIRST
);
72 mkmm(mm
, 1, MM_FIRSTNB
);
75 mkmm(mm
, 1, MM_GOTOLINE
);
78 mkmm_noeolfix(mm
, 1, MM_WHOLELINE
);
82 mkmm_noeolfix(mm
, 1, MM_WHOLELINE
);
92 mkmm(mm
, 1, MM_CENTER
);
95 mkmm(mm
, 1, MM_BOTTOM
);
98 mkmm(mm
, 1, MM_SEARCH
);
100 command_line_mode(vi
, "/");
103 mkmm(mm
, -1, MM_SEARCH
);
105 command_line_mode(vi
, "?");
108 mkmm(mm
, 1, MM_SEARCH
);
109 mm
->arg
.s
= vi
->word
;
112 mkmm(mm
, -1, MM_SEARCH
);
113 mm
->arg
.s
= vi
->word
;
116 mkmm(mm
, 1, MM_CFIND
);
120 mkmm(mm
, -1, MM_CFIND
);
129 static void set_mm_onemore(struct movement
*mm
)
131 if (mm
->kind
== MM_WORDEND
|| mm
->kind
== MM_EOL
)
135 static GtkTextBuffer
*vi_buffer(struct vi
*vi
)
137 return gtk_text_view_get_buffer(GTK_TEXT_VIEW(vi
->view
));
140 static void insert_mode(struct vi
*vi
);
142 static void perform_move_command(
143 struct vi
*vi
, struct movement
*mm
,
144 void (*perform
)(struct vi
*vi
, GtkTextIter
*iter
,
147 GtkTextIter start
, iter
;
148 cursor_get(GTK_TEXT_VIEW(vi
->view
), &iter
);
150 moveiter(GTK_TEXT_VIEW(vi
->view
), mm
, &iter
, &start
);
151 perform(vi
, &iter
, &start
);
152 cursor_place(GTK_TEXT_VIEW(vi
->view
), &iter
);
155 static void dodel(struct vi
*vi
, GtkTextIter
*iter
, GtkTextIter
*start
)
157 gtk_text_buffer_delete(vi_buffer(vi
), start
, iter
);
158 cursor_place(GTK_TEXT_VIEW(vi
->view
), iter
);
161 static void domove(struct vi
*vi
, GtkTextIter
*iter
, GtkTextIter
*start
)
163 cursor_place(GTK_TEXT_VIEW(vi
->view
), iter
);
166 static void dochange(struct vi
*vi
, GtkTextIter
*iter
, GtkTextIter
*start
)
168 gtk_text_buffer_delete(vi_buffer(vi
), start
, iter
);
172 static int delctx(struct vi
*vi
, GdkEventKey
*event
)
174 if (!read_movement_key(vi
, event
)) {
177 set_mm_onemore(&vi
->mm
);
178 perform_move_command(vi
, &vi
->mm
, dodel
);
183 static int changectx(struct vi
*vi
, GdkEventKey
*event
)
185 if (!read_movement_key(vi
, event
)) {
188 set_mm_onemore(&vi
->mm
);
189 perform_move_command(vi
, &vi
->mm
, dochange
);
194 static int scrollctx(struct vi
*vi
, GdkEventKey
*event
)
198 cursor_get(GTK_TEXT_VIEW(vi
->view
), &iter
);
199 switch(event
->keyval
) {
212 gtk_text_iter_set_line_offset(&iter
, 0);
213 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(vi
->view
), &iter
,
214 0.0, TRUE
, 0, align
);
218 static int replacectx(struct vi
*vi
, GdkEventKey
*event
)
220 GtkTextIter start
, end
;
221 GtkTextBuffer
*buffer
= vi_buffer(vi
);
223 int key
= event
->keyval
;
224 int mod
= event
->state
& gtk_accelerator_get_default_mod_mask();
225 if (mod
== GDK_CONTROL_MASK
)
227 cursor_get(GTK_TEXT_VIEW(vi
->view
), &start
);
229 gtk_text_iter_forward_char(&end
);
230 gtk_text_buffer_delete(buffer
, &start
, &end
);
231 if (vi
->im
&& (imc
= im_char(vi
->im
, key
))) {
232 gtk_text_buffer_insert(buffer
, &start
, imc
, strlen(imc
));
235 gtk_text_buffer_insert(buffer
, &start
, &c
, 1);
237 cursor_redraw(GTK_TEXT_VIEW(vi
->view
));
241 static int markctx(struct vi
*vi
, GdkEventKey
*event
)
244 GtkTextBuffer
*buffer
= vi_buffer(vi
);
245 cursor_get(GTK_TEXT_VIEW(vi
->view
), &iter
);
246 if (isprint(event
->keyval
)) {
248 name
[0] = event
->keyval
;
250 gtk_text_buffer_create_mark(buffer
, name
, &iter
, 1);
255 static void move(struct vi
*vi
, struct movement
*mm
)
257 perform_move_command(vi
, mm
, domove
);
260 static void normal_mode(struct vi
*vi
)
263 if (vi
->mode
== EM_INSERT
) {
264 mkmm(&mm
, -1, MM_CHAR
);
267 vi
->mode
= EM_NORMAL
;
268 gtk_widget_grab_focus(vi
->view
);
271 static void insert_mode(struct vi
*vi
)
273 vi
->mode
= EM_INSERT
;
274 gtk_widget_grab_focus(vi
->view
);
277 static void ex_mode(struct vi
*vi
)
280 gtk_widget_grab_focus(vi
->entry
);
283 static void command_line_mode(struct vi
*vi
, char *init
)
286 gtk_entry_set_text(GTK_ENTRY(vi
->entry
), init
);
287 gtk_editable_set_position(GTK_EDITABLE(vi
->entry
), -1);
290 static void move_page(GtkTextView
*view
, int count
)
294 GtkTextBuffer
*buffer
;
296 int yalign
= count
> 0 ? 0.0 : 1.0;
297 buffer
= gtk_text_view_get_buffer(view
);
298 gtk_text_view_get_visible_rect(view
, &rect
);
299 y
= rect
.y
+ (count
> 0 ? count
: count
+ 1) * rect
.height
;
300 gtk_text_view_get_iter_at_location(view
, &iter
, 0, y
);
301 cursor_place(view
, &iter
);
302 gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(view
), &iter
,
303 0.0, TRUE
, 0, yalign
);
306 static void openline(struct vi
*vi
, int n
)
309 GtkTextBuffer
*buffer
= vi_buffer(vi
);
310 cursor_get(GTK_TEXT_VIEW(vi
->view
), &iter
);
312 gtk_text_iter_forward_to_line_end(&iter
);
314 gtk_text_iter_set_line_offset(&iter
, 0);
315 gtk_text_iter_backward_char(&iter
);
317 gtk_text_buffer_insert(buffer
, &iter
, "\n", 1);
318 cursor_place(GTK_TEXT_VIEW(vi
->view
), &iter
);
322 static void rmchar(struct vi
*vi
, int n
)
324 GtkTextIter start
, end
;
325 GtkTextBuffer
*buffer
= vi_buffer(vi
);
326 cursor_get(GTK_TEXT_VIEW(vi
->view
), &start
);
329 gtk_text_iter_forward_char(&end
);
331 gtk_text_iter_backward_char(&start
);
332 gtk_text_buffer_delete(buffer
, &start
, &end
);
333 cursor_redraw(GTK_TEXT_VIEW(vi
->view
));
336 static void join(struct vi
*vi
, int n
)
338 GtkTextIter start
, end
;
339 GtkTextBuffer
*buffer
= vi_buffer(vi
);
340 cursor_get(GTK_TEXT_VIEW(vi
->view
), &start
);
341 if (!gtk_text_iter_ends_line(&start
))
342 gtk_text_iter_forward_to_line_end(&start
);
344 gtk_text_iter_forward_char(&end
);
345 gtk_text_buffer_delete(buffer
, &start
, &end
);
346 cursor_place(GTK_TEXT_VIEW(vi
->view
), &end
);
349 static void del_till_eol(struct vi
*vi
, int change
)
351 GtkTextIter start
, end
;
352 GtkTextBuffer
*buffer
= vi_buffer(vi
);
353 cursor_get(GTK_TEXT_VIEW(vi
->view
), &start
);
355 if (!gtk_text_iter_ends_line(&end
))
356 gtk_text_iter_forward_to_line_end(&end
);
357 gtk_text_buffer_delete(buffer
, &start
, &end
);
360 } else if (!gtk_text_iter_starts_line(&start
)) {
361 gtk_text_iter_backward_char(&start
);
362 cursor_place(GTK_TEXT_VIEW(vi
->view
), &start
);
366 static int im_insert(struct vi
*vi
, int c
)
369 GtkTextBuffer
*buffer
= vi_buffer(vi
);
370 s
= im_char(vi
->im
, c
);
372 gtk_text_buffer_insert_at_cursor(buffer
, s
, strlen(s
));
378 int ex_ctx(struct vi
*vi
, GdkEventKey
*event
)
380 int key
= event
->keyval
;
381 int mod
= event
->state
& gtk_accelerator_get_default_mod_mask();
382 if (key
== GDK_Escape
) {
386 /* execute command */
387 if (key
== GDK_Return
) {
388 char cmd
[MAX_COMMAND_LENGTH
];
389 strncpy(cmd
, gtk_entry_get_text(GTK_ENTRY(vi
->entry
)),
391 cmd
[sizeof(cmd
) - 1] = '\0';
398 /* insert normal keys */
399 if (mod
!= GDK_CONTROL_MASK
)
402 case GDK_bracketleft
:
411 static int rootctx_insert(struct vi
*vi
, GdkEventKey
*event
)
413 int key
= event
->keyval
;
414 int mod
= event
->state
& gtk_accelerator_get_default_mod_mask();
415 if (key
== GDK_Escape
) {
419 if (mod
!= GDK_CONTROL_MASK
)
420 return vi
->im
&& !im_insert(vi
, key
);
422 case GDK_bracketleft
:
438 static int real_key(int c
)
440 return c
< 256 || c
== GDK_Return
;
443 int rootctx(struct vi
*vi
, GdkEventKey
*event
)
445 int mod
= event
->state
& gtk_accelerator_get_default_mod_mask();
447 if (!real_key(event
->keyval
))
449 if (vi
->mode
== EM_INSERT
)
450 return rootctx_insert(vi
, event
);
451 /* handle normal mode binding */
452 if (vi
->mm
.pending
) {
453 if (!read_movement_key(vi
, event
))
454 perform_move_command(vi
, &vi
->mm
, domove
);
457 if (mod
== GDK_CONTROL_MASK
) {
458 switch (event
->keyval
) {
460 move_page(GTK_TEXT_VIEW(vi
->view
), 1);
463 move_page(GTK_TEXT_VIEW(vi
->view
), -1);
470 switch (event
->keyval
) {
475 mkmm_noeolfix(&mm
, 1, MM_CHAR
);
480 mkmm_noeolfix(&mm
, 1, MM_EOL
);
485 mkmm_noeolfix(&mm
, 1, MM_FIRSTNB
);
490 command_line_mode(vi
, ":");
517 vi
->ctx
= replacectx
;
529 if (!read_movement_key(vi
, event
)) {
532 perform_move_command(vi
, &vi
->mm
, domove
);