4 static Mode
*mode_get(Vis
*vis
, enum VisMode mode
) {
5 if (mode
< LENGTH(vis_modes
))
6 return &vis_modes
[mode
];
10 void mode_set(Vis
*vis
, Mode
*new_mode
) {
11 if (vis
->mode
== new_mode
)
14 vis
->mode
->leave(vis
, new_mode
);
15 if (vis
->mode
!= &vis_modes
[VIS_MODE_OPERATOR_PENDING
])
16 vis
->mode_prev
= vis
->mode
;
19 new_mode
->enter(vis
, vis
->mode_prev
);
20 vis
->win
->ui
->draw_status(vis
->win
->ui
);
23 void vis_mode_switch(Vis
*vis
, enum VisMode mode
) {
24 mode_set(vis
, &vis_modes
[mode
]);
27 static bool mode_map(Mode
*mode
, const char *key
, const KeyBinding
*binding
) {
30 if (!mode
->bindings
) {
31 mode
->bindings
= map_new();
35 return map_put(mode
->bindings
, key
, binding
);
38 bool vis_mode_map(Vis
*vis
, enum VisMode id
, const char *key
, const KeyBinding
*binding
) {
39 return id
< LENGTH(vis_modes
) && mode_map(&vis_modes
[id
], key
, binding
);
42 bool vis_window_mode_map(Win
*win
, enum VisMode id
, const char *key
, const KeyBinding
*binding
) {
43 return id
< LENGTH(win
->modes
) && mode_map(&win
->modes
[id
], key
, binding
);
46 static bool mode_unmap(Mode
*mode
, const char *key
) {
47 return mode
&& mode
->bindings
&& map_delete(mode
->bindings
, key
);
50 bool vis_mode_unmap(Vis
*vis
, enum VisMode id
, const char *key
) {
51 return id
< LENGTH(vis_modes
) && mode_unmap(&vis_modes
[id
], key
);
54 bool vis_window_mode_unmap(Win
*win
, enum VisMode id
, const char *key
) {
55 return id
< LENGTH(win
->modes
) && mode_unmap(&win
->modes
[id
], key
);
58 /** mode switching event handlers */
60 static void vis_mode_operator_input(Vis
*vis
, const char *str
, size_t len
) {
61 /* invalid operator */
63 mode_set(vis
, vis
->mode_prev
);
66 static void vis_mode_visual_enter(Vis
*vis
, Mode
*old
) {
68 for (Cursor
*c
= view_cursors(vis
->win
->view
); c
; c
= view_cursors_next(c
))
69 view_cursors_selection_start(c
);
73 static void vis_mode_visual_line_enter(Vis
*vis
, Mode
*old
) {
75 for (Cursor
*c
= view_cursors(vis
->win
->view
); c
; c
= view_cursors_next(c
))
76 view_cursors_selection_start(c
);
78 vis_motion(vis
, VIS_MOVE_NOP
);
81 static void vis_mode_visual_line_leave(Vis
*vis
, Mode
*new) {
83 window_selection_save(vis
->win
);
84 view_selections_clear(vis
->win
->view
);
86 view_cursor_to(vis
->win
->view
, view_cursor_get(vis
->win
->view
));
90 static void vis_mode_visual_leave(Vis
*vis
, Mode
*new) {
92 window_selection_save(vis
->win
);
93 view_selections_clear(vis
->win
->view
);
97 static void vis_mode_insert_enter(Vis
*vis
, Mode
*old
) {
98 if (!vis
->macro_operator
) {
99 macro_operator_record(vis
);
100 action_reset(&vis
->action_prev
);
101 vis
->action_prev
.macro
= vis
->macro_operator
;
102 vis
->action_prev
.op
= &vis_operators
[VIS_OP_INSERT
];
106 static void vis_mode_insert_leave(Vis
*vis
, Mode
*new) {
107 /* make sure we can recover the current state after an editing operation */
108 text_snapshot(vis
->win
->file
->text
);
109 if (new == mode_get(vis
, VIS_MODE_NORMAL
))
110 macro_operator_stop(vis
);
113 static void vis_mode_insert_idle(Vis
*vis
) {
114 text_snapshot(vis
->win
->file
->text
);
117 static void vis_mode_insert_input(Vis
*vis
, const char *str
, size_t len
) {
118 vis_insert_key(vis
, str
, len
);
121 static void vis_mode_replace_enter(Vis
*vis
, Mode
*old
) {
122 if (!vis
->macro_operator
) {
123 macro_operator_record(vis
);
124 action_reset(&vis
->action_prev
);
125 vis
->action_prev
.macro
= vis
->macro_operator
;
126 vis
->action_prev
.op
= &vis_operators
[VIS_OP_REPLACE
];
130 static void vis_mode_replace_leave(Vis
*vis
, Mode
*new) {
131 /* make sure we can recover the current state after an editing operation */
132 text_snapshot(vis
->win
->file
->text
);
133 if (new == mode_get(vis
, VIS_MODE_NORMAL
))
134 macro_operator_stop(vis
);
137 static void vis_mode_replace_input(Vis
*vis
, const char *str
, size_t len
) {
138 vis_replace_key(vis
, str
, len
);
142 [VIS_MODE_OPERATOR_PENDING
] = {
143 .id
= VIS_MODE_OPERATOR_PENDING
,
144 .name
= "OPERATOR-PENDING",
145 .input
= vis_mode_operator_input
,
148 [VIS_MODE_NORMAL
] = {
149 .id
= VIS_MODE_NORMAL
,
154 [VIS_MODE_VISUAL
] = {
155 .id
= VIS_MODE_VISUAL
,
157 .status
= "--VISUAL--",
159 .enter
= vis_mode_visual_enter
,
160 .leave
= vis_mode_visual_leave
,
163 [VIS_MODE_VISUAL_LINE
] = {
164 .id
= VIS_MODE_VISUAL_LINE
,
165 .name
= "VISUAL LINE",
166 .parent
= &vis_modes
[VIS_MODE_VISUAL
],
167 .status
= "--VISUAL LINE--",
169 .enter
= vis_mode_visual_line_enter
,
170 .leave
= vis_mode_visual_line_leave
,
173 [VIS_MODE_INSERT
] = {
174 .id
= VIS_MODE_INSERT
,
176 .status
= "--INSERT--",
178 .enter
= vis_mode_insert_enter
,
179 .leave
= vis_mode_insert_leave
,
180 .input
= vis_mode_insert_input
,
181 .idle
= vis_mode_insert_idle
,
184 [VIS_MODE_REPLACE
] = {
185 .id
= VIS_MODE_REPLACE
,
187 .parent
= &vis_modes
[VIS_MODE_INSERT
],
188 .status
= "--REPLACE--",
190 .enter
= vis_mode_replace_enter
,
191 .leave
= vis_mode_replace_leave
,
192 .input
= vis_mode_replace_input
,
193 .idle
= vis_mode_insert_idle
,