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 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
);
81 vis_motion(vis
, VIS_MOVE_NOP
);
84 static void vis_mode_visual_line_leave(Vis
*vis
, Mode
*new) {
86 window_selection_save(vis
->win
);
87 view_selections_clear(vis
->win
->view
);
89 view_cursor_to(vis
->win
->view
, view_cursor_get(vis
->win
->view
));
93 static void vis_mode_visual_leave(Vis
*vis
, Mode
*new) {
95 window_selection_save(vis
->win
);
96 view_selections_clear(vis
->win
->view
);
100 static void vis_mode_insert_enter(Vis
*vis
, Mode
*old
) {
101 if (!vis
->macro_operator
) {
102 macro_operator_record(vis
);
103 action_reset(&vis
->action_prev
);
104 vis
->action_prev
.macro
= vis
->macro_operator
;
105 vis
->action_prev
.op
= &vis_operators
[VIS_OP_INSERT
];
109 static void vis_mode_insert_leave(Vis
*vis
, Mode
*new) {
110 /* make sure we can recover the current state after an editing operation */
111 text_snapshot(vis
->win
->file
->text
);
112 if (new == mode_get(vis
, VIS_MODE_NORMAL
))
113 macro_operator_stop(vis
);
116 static void vis_mode_insert_idle(Vis
*vis
) {
117 text_snapshot(vis
->win
->file
->text
);
120 static void vis_mode_insert_input(Vis
*vis
, const char *str
, size_t len
) {
121 vis_insert_key(vis
, str
, len
);
124 static void vis_mode_replace_enter(Vis
*vis
, Mode
*old
) {
125 if (!vis
->macro_operator
) {
126 macro_operator_record(vis
);
127 action_reset(&vis
->action_prev
);
128 vis
->action_prev
.macro
= vis
->macro_operator
;
129 vis
->action_prev
.op
= &vis_operators
[VIS_OP_REPLACE
];
133 static void vis_mode_replace_leave(Vis
*vis
, Mode
*new) {
134 /* make sure we can recover the current state after an editing operation */
135 text_snapshot(vis
->win
->file
->text
);
136 if (new == mode_get(vis
, VIS_MODE_NORMAL
))
137 macro_operator_stop(vis
);
140 static void vis_mode_replace_input(Vis
*vis
, const char *str
, size_t len
) {
141 vis_replace_key(vis
, str
, len
);
145 [VIS_MODE_OPERATOR_PENDING
] = {
146 .id
= VIS_MODE_OPERATOR_PENDING
,
147 .name
= "OPERATOR-PENDING",
148 .input
= vis_mode_operator_input
,
151 [VIS_MODE_NORMAL
] = {
152 .id
= VIS_MODE_NORMAL
,
157 [VIS_MODE_VISUAL
] = {
158 .id
= VIS_MODE_VISUAL
,
160 .status
= "--VISUAL--",
162 .enter
= vis_mode_visual_enter
,
163 .leave
= vis_mode_visual_leave
,
166 [VIS_MODE_VISUAL_LINE
] = {
167 .id
= VIS_MODE_VISUAL_LINE
,
168 .name
= "VISUAL LINE",
169 .parent
= &vis_modes
[VIS_MODE_VISUAL
],
170 .status
= "--VISUAL LINE--",
172 .enter
= vis_mode_visual_line_enter
,
173 .leave
= vis_mode_visual_line_leave
,
176 [VIS_MODE_INSERT
] = {
177 .id
= VIS_MODE_INSERT
,
179 .status
= "--INSERT--",
181 .enter
= vis_mode_insert_enter
,
182 .leave
= vis_mode_insert_leave
,
183 .input
= vis_mode_insert_input
,
184 .idle
= vis_mode_insert_idle
,
187 [VIS_MODE_REPLACE
] = {
188 .id
= VIS_MODE_REPLACE
,
190 .parent
= &vis_modes
[VIS_MODE_INSERT
],
191 .status
= "--REPLACE--",
193 .enter
= vis_mode_replace_enter
,
194 .leave
= vis_mode_replace_leave
,
195 .input
= vis_mode_replace_input
,
196 .idle
= vis_mode_insert_idle
,