4coder » Forums » [Solved] Need help implementing shift based selection
Croepha
David Butler
66 posts
1 project

I love pretty much anything technical, whether it be programming, networking, hacking or electronics.

#12221 [Solved] Need help implementing shift based selection
5 months, 3 weeks ago Edited by David Butler on June 18, 2017, 11:20 p.m.

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 :)


404 Signature not found
Croepha
David Butler
66 posts
1 project

I love pretty much anything technical, whether it be programming, networking, hacking or electronics.

#12222 Need help implementing shift based selection
5 months, 3 weeks ago

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

404 Signature not found
Croepha
David Butler
66 posts
1 project

I love pretty much anything technical, whether it be programming, networking, hacking or electronics.

#12223 Need help implementing shift based selection
5 months, 3 weeks ago

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); }

404 Signature not found
Mr4thDimention
Allen Webster
289 posts
2 projects

Heyo

#12224 Need help implementing shift based selection
5 months, 3 weeks ago

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]
Croepha
David Butler
66 posts
1 project

I love pretty much anything technical, whether it be programming, networking, hacking or electronics.

#12251 Need help implementing shift based selection
5 months, 3 weeks ago

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 :)

404 Signature not found