5 static Mode
*mode_get(Vis
*vis
, enum VisMode mode
) {
6 if (mode
< LENGTH(vis_modes
))
7 return &vis_modes
[mode
];
11 void mode_set(Vis
*vis
, Mode
*new_mode
) {
12 if (vis
->mode
== new_mode
)
15 vis
->mode
->leave(vis
, new_mode
);
16 if (vis
->mode
!= &vis_modes
[VIS_MODE_OPERATOR_PENDING
])
17 vis
->mode_prev
= vis
->mode
;
20 new_mode
->enter(vis
, vis
->mode_prev
);
21 vis
->win
->ui
->draw_status(vis
->win
->ui
);
24 void vis_mode_switch(Vis
*vis
, enum VisMode mode
) {
25 mode_set(vis
, &vis_modes
[mode
]);
28 static bool mode_map(Mode
*mode
, const char *key
, const KeyBinding
*binding
) {
31 if (binding
->alias
&& key
[0] != '<' && strncmp(key
, binding
->alias
, strlen(key
)) == 0)
33 if (!mode
->bindings
) {
34 mode
->bindings
= map_new();
38 return (strcmp(key
, "<") == 0 || !map_contains(mode
->bindings
, key
)) && map_put(mode
->bindings
, key
, binding
);
41 bool vis_mode_map(Vis
*vis
, enum VisMode id
, const char *key
, const KeyBinding
*binding
) {
42 return id
< LENGTH(vis_modes
) && mode_map(&vis_modes
[id
], key
, binding
);
45 bool vis_window_mode_map(Win
*win
, enum VisMode id
, const char *key
, const KeyBinding
*binding
) {
46 return id
< LENGTH(win
->modes
) && mode_map(&win
->modes
[id
], key
, binding
);
49 static bool mode_unmap(Mode
*mode
, const char *key
) {
50 return mode
&& mode
->bindings
&& map_delete(mode
->bindings
, key
);
53 bool vis_mode_unmap(Vis
*vis
, enum VisMode id
, const char *key
) {
54 return id
< LENGTH(vis_modes
) && mode_unmap(&vis_modes
[id
], key
);
57 bool vis_window_mode_unmap(Win
*win
, enum VisMode id
, const char *key
) {
58 return id
< LENGTH(win
->modes
) && mode_unmap(&win
->modes
[id
], key
);
61 /** mode switching event handlers */
63 static void vis_mode_operator_input(Vis
*vis
, const char *str
, size_t len
) {
64 /* invalid operator */
66 mode_set(vis
, vis
->mode_prev
);
69 static void vis_mode_visual_enter(Vis
*vis
, Mode
*old
) {
71 for (Cursor
*c
= view_cursors(vis
->win
->view
); c
; c
= view_cursors_next(c
))
72 view_cursors_selection_start(c
);
76 static void vis_mode_visual_line_enter(Vis
*vis
, Mode
*old
) {
78 for (Cursor
*c
= view_cursors(vis
->win
->view
); c
; c
= view_cursors_next(c
))
79 view_cursors_selection_start(c
);
82 vis_motion(vis
, VIS_MOVE_NOP
);
85 static void vis_mode_visual_line_leave(Vis
*vis
, Mode
*new) {
87 window_selection_save(vis
->win
);
88 view_selections_clear(vis
->win
->view
);
90 view_cursor_to(vis
->win
->view
, view_cursor_get(vis
->win
->view
));
94 static void vis_mode_visual_leave(Vis
*vis
, Mode
*new) {
96 window_selection_save(vis
->win
);
97 view_selections_clear(vis
->win
->view
);
101 static void vis_mode_insert_enter(Vis
*vis
, Mode
*old
) {
102 if (!vis
->macro_operator
) {
103 macro_operator_record(vis
);
104 action_reset(&vis
->action_prev
);
105 vis
->action_prev
.macro
= vis
->macro_operator
;
106 vis
->action_prev
.op
= &vis_operators
[VIS_OP_INSERT
];
110 static void vis_mode_insert_leave(Vis
*vis
, Mode
*new) {
111 /* make sure we can recover the current state after an editing operation */
112 text_snapshot(vis
->win
->file
->text
);
113 if (new == mode_get(vis
, VIS_MODE_NORMAL
))
114 macro_operator_stop(vis
);
117 static void vis_mode_insert_idle(Vis
*vis
) {
118 text_snapshot(vis
->win
->file
->text
);
121 static void vis_mode_insert_input(Vis
*vis
, const char *str
, size_t len
) {
122 vis_insert_key(vis
, str
, len
);
125 static void vis_mode_replace_enter(Vis
*vis
, Mode
*old
) {
126 if (!vis
->macro_operator
) {
127 macro_operator_record(vis
);
128 action_reset(&vis
->action_prev
);
129 vis
->action_prev
.macro
= vis
->macro_operator
;
130 vis
->action_prev
.op
= &vis_operators
[VIS_OP_REPLACE
];
134 static void vis_mode_replace_leave(Vis
*vis
, Mode
*new) {
135 /* make sure we can recover the current state after an editing operation */
136 text_snapshot(vis
->win
->file
->text
);
137 if (new == mode_get(vis
, VIS_MODE_NORMAL
))
138 macro_operator_stop(vis
);
141 static void vis_mode_replace_input(Vis
*vis
, const char *str
, size_t len
) {
142 vis_replace_key(vis
, str
, len
);
146 [VIS_MODE_OPERATOR_PENDING
] = {
147 .id
= VIS_MODE_OPERATOR_PENDING
,
148 .name
= "OPERATOR-PENDING",
149 .input
= vis_mode_operator_input
,
152 [VIS_MODE_NORMAL
] = {
153 .id
= VIS_MODE_NORMAL
,
158 [VIS_MODE_VISUAL
] = {
159 .id
= VIS_MODE_VISUAL
,
161 .status
= "--VISUAL--",
163 .enter
= vis_mode_visual_enter
,
164 .leave
= vis_mode_visual_leave
,
167 [VIS_MODE_VISUAL_LINE
] = {
168 .id
= VIS_MODE_VISUAL_LINE
,
169 .name
= "VISUAL LINE",
170 .parent
= &vis_modes
[VIS_MODE_VISUAL
],
171 .status
= "--VISUAL LINE--",
173 .enter
= vis_mode_visual_line_enter
,
174 .leave
= vis_mode_visual_line_leave
,
177 [VIS_MODE_INSERT
] = {
178 .id
= VIS_MODE_INSERT
,
180 .status
= "--INSERT--",
182 .enter
= vis_mode_insert_enter
,
183 .leave
= vis_mode_insert_leave
,
184 .input
= vis_mode_insert_input
,
185 .idle
= vis_mode_insert_idle
,
188 [VIS_MODE_REPLACE
] = {
189 .id
= VIS_MODE_REPLACE
,
191 .parent
= &vis_modes
[VIS_MODE_INSERT
],
192 .status
= "--REPLACE--",
194 .enter
= vis_mode_replace_enter
,
195 .leave
= vis_mode_replace_leave
,
196 .input
= vis_mode_replace_input
,
197 .idle
= vis_mode_insert_idle
,