[Solved] Need help implementing shift based selection

I am trying to implement Shift based selection that is common in most applications...

This is what I got so far:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
bool cro_selection_active = false;
CUSTOM_COMMAND_SIG(cro_clear_selection) {
    View_Summary view = get_active_view(app, AccessProtected);
    view_set_highlight(app, &view, 0, 0, false);
    cro_selection_active = false;
}
CUSTOM_COMMAND_SIG(cro_cont_selection) {
    if (!cro_selection_active) {
      cro_selection_active = true;
      set_mark(app);
    }
    View_Summary view = get_active_view(app, AccessProtected);
    Range range = get_range(&view);
    printf("range.min:%d, range.max:%d \n", range.min, range.max);
    view_set_highlight(app, &view, range.min, range.max, true);
}

// move_left move_right move_up move_down seek_end_of_line seek_beginning_of_line  page_up  page_down  
CUSTOM_COMMAND_SIG(cro_move_left)              { cro_clear_selection(app); move_left(app); }
CUSTOM_COMMAND_SIG(cro_move_right)             { cro_clear_selection(app); move_right(app); }
CUSTOM_COMMAND_SIG(cro_move_up)                { cro_clear_selection(app); move_up(app); }
CUSTOM_COMMAND_SIG(cro_move_down)              { cro_clear_selection(app); move_down(app); }
CUSTOM_COMMAND_SIG(cro_seek_end_of_line)       { cro_clear_selection(app); seek_end_of_line(app); }
CUSTOM_COMMAND_SIG(cro_seek_beginning_of_line) { cro_clear_selection(app); seek_beginning_of_line(app); }
CUSTOM_COMMAND_SIG(cro_page_up)                { cro_clear_selection(app); page_up(app); }
CUSTOM_COMMAND_SIG(cro_page_down)              { cro_clear_selection(app); page_down(app); }

CUSTOM_COMMAND_SIG(cro_smove_left)              { cro_cont_selection(app); move_left(app); }
CUSTOM_COMMAND_SIG(cro_smove_right)             { cro_cont_selection(app); move_right(app); }
CUSTOM_COMMAND_SIG(cro_smove_up)                { cro_cont_selection(app); move_up(app); }
CUSTOM_COMMAND_SIG(cro_smove_down)              { cro_cont_selection(app); move_down(app); }
CUSTOM_COMMAND_SIG(cro_sseek_end_of_line)       { cro_cont_selection(app); seek_end_of_line(app); }
CUSTOM_COMMAND_SIG(cro_sseek_beginning_of_line) { cro_cont_selection(app); seek_beginning_of_line(app); }
CUSTOM_COMMAND_SIG(cro_spage_up)                { cro_cont_selection(app); page_up(app); }
CUSTOM_COMMAND_SIG(cro_spage_down)              { cro_cont_selection(app); page_down(app); }


And my bindings:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    bind(context, key_left, MDFR_NONE, cro_move_left);
    bind(context, key_right, MDFR_NONE, cro_move_right);
    bind(context, key_up, MDFR_NONE, cro_move_up);
    bind(context, key_down, MDFR_NONE, cro_move_down);
    bind(context, key_end, MDFR_NONE, cro_seek_end_of_line);
    bind(context, key_home, MDFR_NONE, cro_seek_beginning_of_line);
    bind(context, key_page_up, MDFR_NONE, cro_page_up);
    bind(context, key_page_down, MDFR_NONE, cro_page_down);

    bind(context, key_left, MDFR_SHIFT, cro_smove_left);
    bind(context, key_right, MDFR_SHIFT, cro_smove_right);
    bind(context, key_up, MDFR_SHIFT, cro_smove_up);
    bind(context, key_down, MDFR_SHIFT, cro_smove_down);
    bind(context, key_end, MDFR_SHIFT, cro_sseek_end_of_line);
    bind(context, key_home, MDFR_SHIFT, cro_sseek_beginning_of_line);
    bind(context, key_page_up, MDFR_SHIFT, cro_spage_up);
    bind(context, key_page_down, MDFR_SHIFT, cro_spage_down);


I have it almost working well, but I'm running into a couple issues:
  1. When I shift left in the middle of text for the first time, its like it is skipping the first key press
  2. If I go back right after moving left, its like it keeps going left for a keystroke
  3. I can't right of my starting cursor...

Also, it would be nice if there was like a "cursor_moved" hook, also maybe a way to poll whether or not the shift key is down, i think something like that would make this a bit simpler...

I am probably missing something basic with the API, still trying to figure it out. Thanks in advance :)


Edited by David Butler on
Ok, oops, I figured out the strange behavior with the seemingly missing keystrokes, I needed to call cro_cont_selection(app); after moving the cursor :) but still having trouble going right of the starting position
Never mind, I figured it out:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
bool cro_selection_active = false;
CUSTOM_COMMAND_SIG(cro_clear_selection) {
    View_Summary view = get_active_view(app, AccessProtected);
    view_set_highlight(app, &view, 0, 0, false);
    cro_selection_active = false;
}
// Application_Links Custom_Command_Function
void cro_cont_selection(Application_Links* app, Custom_Command_Function wrapped_func) {
    bool was_active = cro_selection_active;
    if (!cro_selection_active) {
      cro_selection_active = true;
      set_mark(app);
    }
    wrapped_func(app);
    View_Summary view = get_active_view(app, AccessProtected);
    Range range = get_range(&view);
    printf("range.min:%d, range.max:%d cro_selection_active:%d \n", range.min, range.max, was_active);
    int32_t pos = view.cursor.character_pos;
    view_set_highlight(app, &view, range.min, range.max, true);
    view_set_cursor(app, &view, seek_character_pos(pos), 1);
}
// move_left move_right move_up move_down seek_end_of_line seek_beginning_of_line  page_up  page_down  
CUSTOM_COMMAND_SIG(cro_move_left)              { cro_clear_selection(app); move_left(app); }
CUSTOM_COMMAND_SIG(cro_move_right)             { cro_clear_selection(app); move_right(app); }
CUSTOM_COMMAND_SIG(cro_move_up)                { cro_clear_selection(app); move_up(app); }
CUSTOM_COMMAND_SIG(cro_move_down)              { cro_clear_selection(app); move_down(app); }
CUSTOM_COMMAND_SIG(cro_seek_end_of_line)       { cro_clear_selection(app); seek_end_of_line(app); }
CUSTOM_COMMAND_SIG(cro_seek_beginning_of_line) { cro_clear_selection(app); seek_beginning_of_line(app); }
CUSTOM_COMMAND_SIG(cro_page_up)                { cro_clear_selection(app); page_up(app); }
CUSTOM_COMMAND_SIG(cro_page_down)              { cro_clear_selection(app); page_down(app); }

CUSTOM_COMMAND_SIG(cro_smove_left)              { cro_cont_selection(app, move_left);   }
CUSTOM_COMMAND_SIG(cro_smove_right)             { cro_cont_selection(app, move_right);  }
CUSTOM_COMMAND_SIG(cro_smove_up)                { cro_cont_selection(app, move_up); }
CUSTOM_COMMAND_SIG(cro_smove_down)              { cro_cont_selection(app, move_down); }
CUSTOM_COMMAND_SIG(cro_sseek_end_of_line)       { cro_cont_selection(app, seek_end_of_line); }
CUSTOM_COMMAND_SIG(cro_sseek_beginning_of_line) { cro_cont_selection(app, seek_beginning_of_line); }
CUSTOM_COMMAND_SIG(cro_spage_up)                { cro_cont_selection(app, page_up); }
CUSTOM_COMMAND_SIG(cro_spage_down)              { cro_cont_selection(app, page_down); }
Sorry I didn't catch any of your posts when I could actually be helpful!

This looks really neat. At some point I will be making an official system like this, so it's very helpful to have a look at what worked for you. So thanks for sharing!

If you have any suggestions for what would allow you to make your solution better or what would have made it easier, please let me know at [email protected]
Btw, here is my complete (probably?) version:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
bool cro_selection_active = false;
CUSTOM_COMMAND_SIG(cro_selection_abort) {
    View_Summary view = get_active_view(app, AccessProtected);
    view_set_highlight(app, &view, 0, 0, false);
    cro_selection_active = false;
}
void cro_selection_cont(Application_Links* app, Custom_Command_Function wrapped_func) {
    bool was_active = cro_selection_active;
    if (!cro_selection_active) {
        cro_selection_active = true;
        set_mark(app);
    }
    wrapped_func(app);
    View_Summary view = get_active_view(app, AccessProtected);
    Range range = get_range(&view);
    int32_t pos = view.cursor.character_pos;
    view_set_highlight(app, &view, range.min, range.max, true);
    view_set_cursor(app, &view, seek_character_pos(pos), 1);
    center_view(app); /// because for some reason when you select move down the buffer doesn't scroll with your...
    
}
void cro_selection_delete_or_cmd(Application_Links* app, Custom_Command_Function wrapped_func) {
    if (cro_selection_active) {
        View_Summary view = get_active_view(app, AccessProtected);
        Range range = get_range(&view);
        Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
        buffer_replace_range(app, &buffer, range.min, range.max, 0, 0);
        cro_selection_abort(app);
    } else {
        if (wrapped_func) wrapped_func(app);
    }
}
CUSTOM_COMMAND_SIG(cro_selection_write_character){
    uint32_t access = AccessOpen;
    View_Summary view = get_active_view(app, access);
    
    User_Input in = get_command_input(app);
    
    uint8_t character[4];
    uint32_t length = to_writable_character(in, character);
    if (length != 0){
        Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
        int32_t pos = view.cursor.pos;
        
        Marker next_cursor_marker = {0};
        next_cursor_marker.pos = character_pos_to_pos(app, &view, &buffer, view.cursor.character_pos);
        next_cursor_marker.lean_right = true;
        
        Marker_Handle handle = buffer_add_markers(app, &buffer, 1);
        buffer_set_markers(app, &buffer, handle, 0, 1, &next_cursor_marker);
        
        if(cro_selection_active) {
            Range range = get_range(&view);
            buffer_replace_range(app, &buffer, range.min, range.max,  (char*)character, length);
            cro_selection_abort(app);
        } else {
            buffer_replace_range(app, &buffer, pos, pos, (char*)character, length);
        }
        
        buffer_get_markers(app, &buffer, handle, 0, 1, &next_cursor_marker);
        buffer_remove_markers(app, &buffer, handle);
        
        view_set_cursor(app, &view, seek_pos(next_cursor_marker.pos), true);
    }
}

....

    bind_vanilla_keys(context, cro_selection_write_character);
....
    
#define __(_k, _m, _f) \
    bind(context, _k, _m|MDFR_SHIFT, [](Application_Links* app){cro_selection_cont(app, _f);}); \
    bind(context, _k, _m, [](Application_Links* app){cro_selection_abort(app); _f(app);})
    __(key_left,      MDFR_NONE, move_left);
    __(key_right,     MDFR_NONE, move_right);
    __(key_up,        MDFR_NONE, move_up);
    __(key_down,      MDFR_NONE, move_down);
    __(key_end,       MDFR_NONE, seek_end_of_line);
    __(key_home,      MDFR_NONE, seek_beginning_of_line);
    __(key_page_up,   MDFR_NONE, page_up);
    __(key_page_down, MDFR_NONE, page_down);
    __(key_right,     MDFR_CTRL|MDFR_ALT, seek_whitespace_right);
    __(key_left,      MDFR_CTRL|MDFR_ALT, seek_whitespace_left);
    __(key_right,     MDFR_CTRL, seek_token_right); // ?
    __(key_left,      MDFR_CTRL, seek_token_left); // ?
    __(key_right,     MDFR_ALT,  seek_white_or_token_right);
    __(key_left,      MDFR_ALT,  seek_white_or_token_left);
    __(key_up,        MDFR_CTRL, seek_whitespace_up_end_line);
    __(key_down,      MDFR_CTRL, seek_whitespace_down_end_line);
    __(key_up,        MDFR_ALT,  move_up_10);
    __(key_down,      MDFR_ALT,  move_down_10);
#undef __
        
    //    bind(context, key_del, MDFR_SHIFT, delete_char);
    bind(context, key_back, MDFR_NONE, [](Application_Links* app){
         cro_selection_delete_or_cmd(app, backspace_char);
    });
    bind(context, key_del, MDFR_NONE, [](Application_Links* app){
         cro_selection_delete_or_cmd(app, delete_char);
    });
    bind(context, key_esc, MDFR_NONE, cro_selection_abort);         
    bind(context, 'x', MDFR_CTRL, [](Application_Links* app){
         cut(app);
         cro_selection_abort(app);
    });
    bind(context, 'v', MDFR_CTRL, [](Application_Links* app){         
         cro_selection_delete_or_cmd(app, NULL);
         paste_and_indent(app);
    });

....

    bind(context, ' ', MDFR_SHIFT, cro_selection_write_character);


I wouldn't be surprised if there were a better way, but this works for now until we get an official version :)
How do I use the above code? Were do I put it?

I'm new to 4Coder but I am to embarrassed to admit/post that I can't figure out how to copy and paste LOL. As I have already posted another question that I think was to dumb to answer. But if I want to know I guess I need to post.

I'm too used to windows with shift+left/right arrow keys and ctrl c and v to copy and paste.
To copy/cut/past you need to place the mark (ctrl + space by default) where you want the selection to start, move the cursor where you want the selection to end, and then use ctrl + c, ctrl + x, ctrl + v. 4coder default bindings.

To use the above code you need the paid version (4coder super).

You can create a new .h file and paste the code in it, until line 69 (and do not copy the "...").

To set up your bindings if you haven't already done it:
open 4coder_generated/remapping.h and copy the function fill_keys_default (or fill_keys_mac_default if you're on a Mac) in the file you created and rename the function (e.g. fill_keys_custom).

You'll need to merge the bindings from Croepha with the existing bindings. In the function you just copied search for "begin_map(context, mapid_file);". After that line you'll need to remove the lines that bind something that Croepha binds (e.g. remove the line that contains move_left, move_right...). Then paste the rest of the code, starting at line 69 (and do not copy the "...").

In 4coder_default_bindings.cpp you need to include the file you created and in the get_bindings function change the line default_keys(context); to fill_keys_custom(context); (or the name you chose).

Then run buildsuper.bat.
Yes I have 4Coder Super.

But I still can't copy & paste. When I try, I get a greyed out lined square around the first letter of text a want to copy and that's all I can get it to do.

*update*
I can do the copy and paste now. I did not know it was copying as their was no highlight and ctrl v is working now too. (no idea why or why working now)


So I tried posting in the code and run buildsuper.bat as per the post above.
I get these errors:

W:\4coder>W:\4coder\buildsuper.bat
4coder_metadata_generator.cpp
4coder_default_bindings.cpp
w:\4coder\edit.h(10) : error C2220: warning treated as error - no 'object' file generated
w:\4coder\edit.h(10) : warning C4189: 'was_active' : local variable is initialized but not referenced
w:\4coder\edit.h(36) : warning C4550: expression evaluates to a function which is missing an argument list
Could Not Find W:\4coder\*.exp
Could Not Find W:\4coder\*.lib
W:\4coder>

Edited by Zenn on
Could you copy the whole content of the file here ?
w:\4coder\edit.h(10) : warning C4189: 'was_active' : local variable is initialized but not referenced
The was_active variable isn't used. You can remove it from the function.

For the other error we need the code to help you.
Which version of visual studio are you using ?
I am using visual Studio 2017

Here is the file: Edit.h

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
bool cro_selection_active = false;
CUSTOM_COMMAND_SIG(cro_selection_abort)
{
    View_Summary view = get_active_view(app, AccessProtected);
    view_set_highlight(app, &view, 0, 0, false);
    cro_selection_active = false;
}
void cro_selection_cont(Application_Links *app, Custom_Command_Function wrapped_func)
{
    bool was_active = cro_selection_active;
    if (!cro_selection_active)
    {
        cro_selection_active = true;
        set_mark(app);
    }
    wrapped_func(app);
    View_Summary view = get_active_view(app, AccessProtected);
    Range range = get_range(&view);
    int32_t pos = view.cursor.character_pos;
    view_set_highlight(app, &view, range.min, range.max, true);
    view_set_cursor(app, &view, seek_character_pos(pos), 1);
    center_view(app); /// because for some reason when you select move down the buffer doesn't scroll with your...
}
void cro_selection_delete_or_cmd(Application_Links *app, Custom_Command_Function wrapped_func)
{
    if (cro_selection_active)
    {
        View_Summary view = get_active_view(app, AccessProtected);
        Range range = get_range(&view);
        Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen);
        buffer_replace_range(app, &buffer, range.min, range.max, 0, 0);
        cro_selection_abort(app);
    }
    else
    {
        if (wrapped_func)
            wrapped_func(app);
    }
}
CUSTOM_COMMAND_SIG(cro_selection_write_character)
{
    uint32_t access = AccessOpen;
    View_Summary view = get_active_view(app, access);

    User_Input in = get_command_input(app);

    uint8_t character[4];
    uint32_t length = to_writable_character(in, character);
    if (length != 0)
    {
        Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
        int32_t pos = view.cursor.pos;

        Marker next_cursor_marker = {0};
        next_cursor_marker.pos = character_pos_to_pos(app, &view, &buffer, view.cursor.character_pos);
        next_cursor_marker.lean_right = true;

        Marker_Handle handle = buffer_add_markers(app, &buffer, 1);
        buffer_set_markers(app, &buffer, handle, 0, 1, &next_cursor_marker);

        if (cro_selection_active)
        {
            Range range = get_range(&view);
            buffer_replace_range(app, &buffer, range.min, range.max, (char *)character, length);
            cro_selection_abort(app);
        }
        else
        {
            buffer_replace_range(app, &buffer, pos, pos, (char *)character, length);
        }

        buffer_get_markers(app, &buffer, handle, 0, 1, &next_cursor_marker);
        buffer_remove_markers(app, &buffer, handle);

        view_set_cursor(app, &view, seek_pos(next_cursor_marker.pos), true);
    }
}

void fill_keys_custom(Bind_Helper *context)
{
    begin_map(context, mapid_global);
    bind(context, 'p', MDFR_CTRL, open_panel_vsplit);
    bind(context, '_', MDFR_CTRL, open_panel_hsplit);
    bind(context, 'P', MDFR_CTRL, close_panel);
    bind(context, ',', MDFR_CTRL, change_active_panel);
    bind(context, '<', MDFR_CTRL, change_active_panel_backwards);
    bind(context, 'n', MDFR_CTRL, interactive_new);
    bind(context, 'o', MDFR_CTRL, interactive_open_or_new);
    bind(context, 'o', MDFR_ALT, open_in_other);
    bind(context, 'k', MDFR_CTRL, interactive_kill_buffer);
    bind(context, 'i', MDFR_CTRL, interactive_switch_buffer);
    bind(context, 'h', MDFR_CTRL, project_go_to_root_directory);
    bind(context, 'H', MDFR_CTRL, reload_current_project);
    bind(context, 'S', MDFR_CTRL, save_all_dirty_buffers);
    bind(context, 'c', MDFR_ALT, open_color_tweaker);
    bind(context, 'd', MDFR_ALT, open_debug);
    bind(context, '.', MDFR_ALT, change_to_build_panel);
    bind(context, ',', MDFR_ALT, close_build_panel);
    bind(context, 'n', MDFR_ALT, goto_next_jump_no_skips_sticky);
    bind(context, 'N', MDFR_ALT, goto_prev_jump_no_skips_sticky);
    bind(context, 'M', MDFR_ALT, goto_first_jump_sticky);
    bind(context, 'm', MDFR_ALT, build_in_build_panel);
    bind(context, 'z', MDFR_ALT, execute_any_cli);
    bind(context, 'Z', MDFR_ALT, execute_previous_cli);
    bind(context, 'x', MDFR_ALT, execute_arbitrary_command);
    bind(context, 's', MDFR_ALT, show_scrollbar);
    bind(context, 'w', MDFR_ALT, hide_scrollbar);
    bind(context, 'b', MDFR_ALT, toggle_filebar);
    bind(context, '@', MDFR_ALT, toggle_mouse);
    bind(context, key_page_up, MDFR_CTRL, toggle_fullscreen);
    bind(context, 'E', MDFR_ALT, exit_4coder);
    bind(context, '+', MDFR_CTRL, increase_face_size);
    bind(context, '-', MDFR_CTRL, decrease_face_size);
    bind(context, key_f1, MDFR_NONE, project_fkey_command);
    bind(context, key_f2, MDFR_NONE, project_fkey_command);
    bind(context, key_f3, MDFR_NONE, project_fkey_command);
    bind(context, key_f4, MDFR_NONE, project_fkey_command);
    bind(context, key_f5, MDFR_NONE, project_fkey_command);
    bind(context, key_f6, MDFR_NONE, project_fkey_command);
    bind(context, key_f7, MDFR_NONE, project_fkey_command);
    bind(context, key_f8, MDFR_NONE, project_fkey_command);
    bind(context, key_f9, MDFR_NONE, project_fkey_command);
    bind(context, key_f10, MDFR_NONE, project_fkey_command);
    bind(context, key_f11, MDFR_NONE, project_fkey_command);
    bind(context, key_f12, MDFR_NONE, project_fkey_command);
    bind(context, key_f13, MDFR_NONE, project_fkey_command);
    bind(context, key_f14, MDFR_NONE, project_fkey_command);
    bind(context, key_f15, MDFR_NONE, project_fkey_command);
    bind(context, key_f16, MDFR_NONE, project_fkey_command);
    end_map(context);
    begin_map(context, mapid_file);
    bind_vanilla_keys(context, write_character);
    bind(context, key_mouse_left, MDFR_NONE, click_set_cursor);
    bind(context, key_mouse_left_release, MDFR_NONE, click_set_mark);
    bind(context, key_mouse_right, MDFR_NONE, click_set_mark);
//    bind(context, key_del, MDFR_NONE, delete_char);
    bind(context, key_del, MDFR_SHIFT, delete_char);
//    bind(context, key_back, MDFR_NONE, backspace_char);
    bind(context, key_back, MDFR_SHIFT, backspace_char);
    bind(context, key_up, MDFR_ALT, move_line_up);
    bind(context, key_down, MDFR_ALT, move_line_down);
    bind(context, key_back, MDFR_CTRL, backspace_word);
    bind(context, key_del, MDFR_CTRL, delete_word);
    bind(context, key_back, MDFR_ALT, snipe_token_or_word);
    bind(context, key_del, MDFR_ALT, snipe_token_or_word_right);
        bind_vanilla_keys(context, cro_selection_write_character);
    
#define __(_k, _m, _f) \
    bind(context, _k, _m|MDFR_SHIFT, [](Application_Links* app){cro_selection_cont(app, _f);}); \
    bind(context, _k, _m, [](Application_Links* app){cro_selection_abort(app); _f(app);})
    __(key_left,      MDFR_NONE, move_left);
    __(key_right,     MDFR_NONE, move_right);
    __(key_up,        MDFR_NONE, move_up);
    __(key_down,      MDFR_NONE, move_down);
    __(key_end,       MDFR_NONE, seek_end_of_line);
    __(key_home,      MDFR_NONE, seek_beginning_of_line);
    __(key_page_up,   MDFR_NONE, page_up);
    __(key_page_down, MDFR_NONE, page_down);
    __(key_right,     MDFR_CTRL|MDFR_ALT, seek_whitespace_right);
    __(key_left,      MDFR_CTRL|MDFR_ALT, seek_whitespace_left);
    __(key_right,     MDFR_CTRL, seek_token_right); // ?
    __(key_left,      MDFR_CTRL, seek_token_left); // ?
    __(key_right,     MDFR_ALT,  seek_white_or_token_right);
    __(key_left,      MDFR_ALT,  seek_white_or_token_left);
    __(key_up,        MDFR_CTRL, seek_whitespace_up_end_line);
    __(key_down,      MDFR_CTRL, seek_whitespace_down_end_line);
    __(key_up,        MDFR_ALT,  move_up_10);
    __(key_down,      MDFR_ALT,  move_down_10);
#undef __
        
    //    bind(context, key_del, MDFR_SHIFT, delete_char);
    bind(context, key_back, MDFR_NONE, [](Application_Links* app){
         cro_selection_delete_or_cmd(app, backspace_char);
    });
    bind(context, key_del, MDFR_NONE, [](Application_Links* app){
         cro_selection_delete_or_cmd(app, delete_char);
    });
    bind(context, key_esc, MDFR_NONE, cro_selection_abort);         
    bind(context, 'x', MDFR_CTRL, [](Application_Links* app){
         cut(app);
         cro_selection_abort(app);
    });
    bind(context, 'v', MDFR_CTRL, [](Application_Links* app){         
         cro_selection_delete_or_cmd(app, NULL);
         paste_and_indent(app);
    });

    bind(context, ' ', MDFR_SHIFT, cro_selection_write_character);

    bind(context, ' ', MDFR_CTRL, set_mark);
    bind(context, 'a', MDFR_CTRL, replace_in_range);
    bind(context, 'c', MDFR_CTRL, copy);
    bind(context, 'd', MDFR_CTRL, delete_range);
    bind(context, 'D', MDFR_CTRL, delete_line);
    bind(context, 'e', MDFR_CTRL, center_view);
    bind(context, 'E', MDFR_CTRL, left_adjust_view);
    bind(context, 'f', MDFR_CTRL, search);
    bind(context, 'F', MDFR_CTRL, list_all_locations);
    bind(context, 'F', MDFR_ALT, list_all_substring_locations_case_insensitive);
    bind(context, 'g', MDFR_CTRL, goto_line);
    bind(context, 'G', MDFR_CTRL, list_all_locations_of_selection);
    bind(context, 'j', MDFR_CTRL, to_lowercase);
    bind(context, 'K', MDFR_CTRL, kill_buffer);
    bind(context, 'l', MDFR_CTRL, toggle_line_wrap);
    bind(context, 'L', MDFR_CTRL, duplicate_line);
    bind(context, 'm', MDFR_CTRL, cursor_mark_swap);
    bind(context, 'O', MDFR_CTRL, reopen);
    bind(context, 'q', MDFR_CTRL, query_replace);
    bind(context, 'Q', MDFR_CTRL, query_replace_identifier);
    bind(context, 'q', MDFR_ALT, query_replace_selection);
    bind(context, 'r', MDFR_CTRL, reverse_search);
    bind(context, 's', MDFR_CTRL, save);
    bind(context, 't', MDFR_CTRL, search_identifier);
    bind(context, 'T', MDFR_CTRL, list_all_locations_of_identifier);
    bind(context, 'u', MDFR_CTRL, to_uppercase);
    bind(context, 'v', MDFR_CTRL, paste_and_indent);
    bind(context, 'v', MDFR_ALT, toggle_virtual_whitespace);
    bind(context, 'V', MDFR_CTRL, paste_next_and_indent);
    bind(context, 'x', MDFR_CTRL, cut);
    bind(context, 'y', MDFR_CTRL, redo);
    bind(context, 'z', MDFR_CTRL, undo);
    bind(context, '1', MDFR_CTRL, view_buffer_other_panel);
    bind(context, '2', MDFR_CTRL, swap_buffers_between_panels);
    bind(context, '?', MDFR_CTRL, toggle_show_whitespace);
    bind(context, '~', MDFR_CTRL, clean_all_lines);
    bind(context, '\n', MDFR_NONE, newline_or_goto_position_sticky);
    bind(context, '\n', MDFR_SHIFT, newline_or_goto_position_same_panel_sticky);
    bind(context, ' ', MDFR_SHIFT, write_character);
    end_map(context);
    begin_map(context, default_code_map);
    inherit_map(context, mapid_file);
    bind(context, key_right, MDFR_CTRL, seek_alphanumeric_or_camel_right);
    bind(context, key_left, MDFR_CTRL, seek_alphanumeric_or_camel_left);
    bind(context, '\n', MDFR_NONE, write_and_auto_tab);
    bind(context, '\n', MDFR_SHIFT, write_and_auto_tab);
    bind(context, '}', MDFR_NONE, write_and_auto_tab);
    bind(context, ')', MDFR_NONE, write_and_auto_tab);
    bind(context, ']', MDFR_NONE, write_and_auto_tab);
    bind(context, ';', MDFR_NONE, write_and_auto_tab);
    bind(context, '#', MDFR_NONE, write_and_auto_tab);
    bind(context, '\t', MDFR_NONE, word_complete);
    bind(context, '\t', MDFR_CTRL, auto_tab_range);
    bind(context, '\t', MDFR_SHIFT, auto_tab_line_at_cursor);
    bind(context, 'h', MDFR_ALT, write_hack);
    bind(context, 'r', MDFR_ALT, write_block);
    bind(context, 't', MDFR_ALT, write_todo);
    bind(context, 'y', MDFR_ALT, write_note);
    bind(context, 'D', MDFR_ALT, list_all_locations_of_type_definition);
    bind(context, 'T', MDFR_ALT, list_all_locations_of_type_definition_of_identifier);
    bind(context, '[', MDFR_CTRL, open_long_braces);
    bind(context, '{', MDFR_CTRL, open_long_braces_semicolon);
    bind(context, '}', MDFR_CTRL, open_long_braces_break);
    bind(context, '[', MDFR_ALT, highlight_surrounding_scope);
    bind(context, ']', MDFR_ALT, highlight_prev_scope_absolute);
    bind(context, '\'', MDFR_ALT, highlight_next_scope_absolute);
    bind(context, '/', MDFR_ALT, place_in_scope);
    bind(context, '-', MDFR_ALT, delete_current_scope);
    bind(context, 'j', MDFR_ALT, scope_absorb_down);
    bind(context, 'i', MDFR_ALT, if0_off);
    bind(context, '1', MDFR_ALT, open_file_in_quotes);
    bind(context, '2', MDFR_ALT, open_matching_file_cpp);
    bind(context, '0', MDFR_CTRL, write_zero_struct);
    bind(context, 'I', MDFR_CTRL, list_all_functions_current_buffer);
    end_map(context);
}


should it be in the same folder as 4ed.exe or some other sub folder?

Edited by Zenn on
You can put it anywhere as long as the include path points to it.

For the first error, you can remove the line
1
bool was_active = cro_selection_active;

For the second error, replace the line
1
if (wrapped_func)

by
1
if (wrapped_func != 0)