The end of 4coder_helper as a folder, all helpers grouped with main helper file or other appropriate code. End of power as a folder, all power code preserved at same level as normal code
							parent
							
								
									a9f30adbe7
								
							
						
					
					
						commit
						9181371be7
					
				|  | @ -576,7 +576,7 @@ STRUCT Buffer_Summary{ | |||
|     /*DOC(If this is not a null summary, this field contains flags describing the protection status of the buffer.)*/ | ||||
|     Access_Flag lock_flags; | ||||
|      | ||||
|     /* DOC(If this is not a null summary, this field specifies the size of the text in the buffer.) */ | ||||
|     /* DOC(If this is not a null summary, this field specifies the number of bytes in the buffer.) */ | ||||
|     int32_t size; | ||||
|     /* DOC(If this is not a null summary, this field specifies the number of lines in the buffer.) */ | ||||
|     int32_t line_count; | ||||
|  |  | |||
|  | @ -5,10 +5,6 @@ moving the cursor, which work even without the default 4coder framework. | |||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| //
 | ||||
| // Fundamental Editing Commands
 | ||||
| //
 | ||||
| 
 | ||||
| static void | ||||
| write_character_parameter(Application_Links *app, uint8_t *character, uint32_t length){ | ||||
|     if (length != 0){ | ||||
|  | @ -119,9 +115,7 @@ CUSTOM_DOC("Deletes the text in the range between the cursor and the mark.") | |||
|     buffer_replace_range(app, &buffer, range.min, range.max, 0, 0); | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // Basic Navigation Commands
 | ||||
| //
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(center_view) | ||||
| CUSTOM_DOC("Centers the view vertically on the line on which the cursor sits.") | ||||
|  | @ -203,6 +197,8 @@ CUSTOM_DOC("Sets the mark position to the mouse position.") | |||
|     } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| inline void | ||||
| move_vertical(Application_Links *app, float line_multiplier){ | ||||
|     uint32_t access = AccessProtected; | ||||
|  | @ -229,6 +225,22 @@ move_vertical(Application_Links *app, float line_multiplier){ | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static float | ||||
| get_page_jump(View_Summary *view){ | ||||
|     i32_Rect region = view->file_region; | ||||
|     float page_jump = 1.f; | ||||
|     if (view->line_height > 0.f){ | ||||
|         int32_t height = region.y1 - region.y0; | ||||
|         float line_count = (float)(height)/view->line_height; | ||||
|         int32_t line_count_rounded = (int32_t)line_count; | ||||
|         page_jump = (float)line_count_rounded - 3.f; | ||||
|         if (page_jump <= 1.f){ | ||||
|             page_jump = 1.f; | ||||
|         } | ||||
|     } | ||||
|     return(page_jump); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(move_up) | ||||
| CUSTOM_DOC("Moves the cursor up one line.") | ||||
| { | ||||
|  | @ -253,20 +265,15 @@ CUSTOM_DOC("Moves the cursor down ten lines.") | |||
|     move_vertical(app, 10.f); | ||||
| } | ||||
| 
 | ||||
| static float | ||||
| get_page_jump(View_Summary *view){ | ||||
|     i32_Rect region = view->file_region; | ||||
|     float page_jump = 1; | ||||
|      | ||||
|     if (view->line_height > 0){ | ||||
|         page_jump = (float)(region.y1 - region.y0) / view->line_height; | ||||
|         page_jump -= 3.f; | ||||
|         if (page_jump <= 0){ | ||||
|             page_jump = 1.f; | ||||
|         } | ||||
| CUSTOM_COMMAND_SIG(move_down_textual) | ||||
| CUSTOM_DOC("Moves down to the next line of actual text, regardless of line wrapping.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     if (!view.exists){ | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     return(page_jump); | ||||
|     int32_t next_line = view.cursor.line + 1; | ||||
|     view_set_cursor(app, &view, seek_line_char(next_line, 1), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(page_up) | ||||
|  | @ -287,6 +294,7 @@ CUSTOM_DOC("Scrolls the view down one view height and moves the cursor down one | |||
|     move_vertical(app, page_jump); | ||||
| } | ||||
| 
 | ||||
| ////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(move_left) | ||||
| CUSTOM_DOC("Moves the cursor one character to the left.") | ||||
|  | @ -311,116 +319,11 @@ CUSTOM_DOC("Puts the cursor at the top of the file, and the mark at the bottom o | |||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); | ||||
|     view_set_cursor(app, &view, seek_character_pos(0), true); | ||||
|     view_set_mark(app, &view, seek_character_pos(buffer.size)); | ||||
|     view_set_cursor(app, &view, seek_pos(0), true); | ||||
|     view_set_mark(app, &view, seek_pos(buffer.size)); | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // Long Seeks
 | ||||
| //
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_up) | ||||
| CUSTOM_DOC("Seeks the cursor up to the next blank line.") | ||||
| { | ||||
|     uint32_t access = AccessProtected; | ||||
|     View_Summary view = get_active_view(app, access); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, access); | ||||
|      | ||||
|     int32_t new_pos = buffer_seek_whitespace_up(app, &buffer, view.cursor.pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_down) | ||||
| CUSTOM_DOC("Seeks the cursor down to the next blank line.") | ||||
| { | ||||
|     uint32_t access = AccessProtected; | ||||
|     View_Summary view = get_active_view(app, access); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, access); | ||||
|      | ||||
|     int32_t new_pos = buffer_seek_whitespace_down(app, &buffer, view.cursor.pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_beginning_of_textual_line) | ||||
| CUSTOM_DOC("Seeks the cursor to the beginning of the line across all text.") | ||||
| { | ||||
|     uint32_t access = AccessProtected; | ||||
|     View_Summary view = get_active_view(app, access); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, access); | ||||
|      | ||||
|     int32_t new_pos = seek_line_beginning(app, &buffer, view.cursor.pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_end_of_textual_line) | ||||
| CUSTOM_DOC("Seeks the cursor to the end of the line across all text.") | ||||
| { | ||||
|     uint32_t access = AccessProtected; | ||||
|     View_Summary view = get_active_view(app, access); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, access); | ||||
|      | ||||
|     int32_t new_pos = seek_line_end(app, &buffer, view.cursor.pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_beginning_of_line) | ||||
| CUSTOM_DOC("Seeks the cursor to the beginning of the visual line.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|      | ||||
|     float y = view.cursor.wrapped_y; | ||||
|     if (view.unwrapped_lines){ | ||||
|         y = view.cursor.unwrapped_y; | ||||
|     } | ||||
|      | ||||
|     view_set_cursor(app, &view, seek_xy(0, y, 1, view.unwrapped_lines), 1); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_end_of_line) | ||||
| CUSTOM_DOC("Seeks the cursor to the end of the visual line.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|      | ||||
|     float y = view.cursor.wrapped_y; | ||||
|     if (view.unwrapped_lines){ | ||||
|         y = view.cursor.unwrapped_y; | ||||
|     } | ||||
|      | ||||
|     view_set_cursor(app, &view, seek_xy(max_f32, y, 1, view.unwrapped_lines), 1); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_up_end_line) | ||||
| CUSTOM_DOC("Seeks the cursor up to the next blank line and places it at the end of the line.") | ||||
| { | ||||
|     exec_command(app, seek_whitespace_up); | ||||
|     exec_command(app, seek_end_of_line); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_down_end_line) | ||||
| CUSTOM_DOC("Seeks the cursor down to the next blank line and places it at the end of the line.") | ||||
| { | ||||
|     exec_command(app, seek_whitespace_down); | ||||
|     exec_command(app, seek_end_of_line); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(goto_beginning_of_file) | ||||
| CUSTOM_DOC("Sets the cursor to the beginning of the file.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     view_set_cursor(app, &view, seek_pos(0), 1); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(goto_end_of_file) | ||||
| CUSTOM_DOC("Sets the cursor to the end of the file.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); | ||||
|     view_set_cursor(app, &view, seek_pos(buffer.size), 1); | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // Fancy Editing
 | ||||
| //
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(to_uppercase) | ||||
| CUSTOM_DOC("Converts all ascii text in the range between the cursor and the mark to uppercase.") | ||||
|  | @ -525,10 +428,7 @@ CUSTOM_DOC("Removes trailing whitespace from all lines in the current buffer.") | |||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //
 | ||||
| // Basic Panel Management
 | ||||
| //
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(basic_change_active_panel) | ||||
| CUSTOM_DOC("Change the currently active panel, moving to the panel with the next highest view_id.  Will not skipe the build panel if it is open.") | ||||
|  | @ -545,10 +445,7 @@ CUSTOM_DOC("Closes the currently active panel if it is not the only panel open." | |||
|     close_view(app, &view); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //
 | ||||
| // Common Settings Commands
 | ||||
| //
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(show_scrollbar) | ||||
| CUSTOM_DOC("Sets the current view to show it's scrollbar.") | ||||
|  | @ -683,9 +580,7 @@ CUSTOM_DOC("Attempts to close 4coder.") | |||
|     send_exit_signal(app); | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // Interactive Commands
 | ||||
| //
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(goto_line) | ||||
| CUSTOM_DOC("Queries the user for a number, and jumps the cursor to the corresponding line.") | ||||
|  | @ -1061,9 +956,7 @@ CUSTOM_DOC("Queries the user for a string, and incrementally replace every occur | |||
|     end_temp_memory(temp); | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // File Handling Commands
 | ||||
| //
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(save_all_dirty_buffers) | ||||
| CUSTOM_DOC("Saves all buffers marked dirty (showing the '*' indicator).") | ||||
|  | @ -1239,9 +1132,144 @@ CUSTOM_DOC("Queries the user for a name and creates a new directory with the giv | |||
|     } | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // cmdid wrappers
 | ||||
| //
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(move_line_up) | ||||
| CUSTOM_DOC("Swaps the line under the cursor with the line above it, and moves the cursor up with it.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|      | ||||
|     if (view.cursor.line <= 1){ | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|     if (!buffer.exists){ | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     Full_Cursor prev_line_cursor = {0}; | ||||
|     Full_Cursor this_line_cursor = {0}; | ||||
|     Full_Cursor next_line_cursor = {0}; | ||||
|      | ||||
|     int32_t this_line = view.cursor.line; | ||||
|     int32_t prev_line = this_line - 1; | ||||
|     int32_t next_line = this_line +1; | ||||
|      | ||||
|     if (view_compute_cursor(app, &view, seek_line_char(prev_line, 1), &prev_line_cursor) && | ||||
|         view_compute_cursor(app, &view, seek_line_char(this_line, 1), &this_line_cursor) && | ||||
|         view_compute_cursor(app, &view, seek_line_char(next_line, 1), &next_line_cursor)){ | ||||
|          | ||||
|         int32_t prev_line_pos = prev_line_cursor.pos; | ||||
|         int32_t this_line_pos = this_line_cursor.pos; | ||||
|         int32_t next_line_pos = next_line_cursor.pos; | ||||
|          | ||||
|         Partition *part = &global_part; | ||||
|         Temp_Memory temp = begin_temp_memory(part); | ||||
|          | ||||
|         int32_t length = next_line_pos - prev_line_pos; | ||||
|         char *swap = push_array(part, char, length + 1); | ||||
|         int32_t first_len = next_line_pos - this_line_pos; | ||||
|          | ||||
|         if (buffer_read_range(app, &buffer, this_line_pos, next_line_pos, swap)){ | ||||
|             bool32 second_line_didnt_have_newline = true; | ||||
|             for (int32_t i = first_len - 1; i >= 0; --i){ | ||||
|                 if (swap[i] == '\n'){ | ||||
|                     second_line_didnt_have_newline = false; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             if (second_line_didnt_have_newline){ | ||||
|                 swap[first_len] = '\n'; | ||||
|                 first_len += 1; | ||||
|                 // NOTE(allen): Don't increase "length" because then we will be including
 | ||||
|                 // the original newline and addignt this new one, making the file longer
 | ||||
|                 // which shouldn't be possible for this command!
 | ||||
|             } | ||||
|              | ||||
|             if (buffer_read_range(app, &buffer, prev_line_pos, this_line_pos, swap + first_len)){ | ||||
|                 buffer_replace_range(app, &buffer, prev_line_pos, next_line_pos, swap, length); | ||||
|                 view_set_cursor(app, &view, seek_line_char(prev_line, 1), true); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         end_temp_memory(temp); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(move_line_down) | ||||
| CUSTOM_DOC("Swaps the line under the cursor with the line below it, and moves the cursor down with it.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     if (!view.exists){ | ||||
|         return; | ||||
|     } | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|     if (!buffer.exists){ | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     int32_t next_line = view.cursor.line + 1; | ||||
|     Full_Cursor new_cursor = {0}; | ||||
|     if (view_compute_cursor(app, &view, seek_line_char(next_line, 1), &new_cursor)){ | ||||
|         if (new_cursor.line == next_line){ | ||||
|             view_set_cursor(app, &view, seek_pos(new_cursor.pos), true); | ||||
|             move_line_up(app); | ||||
|             move_down_textual(app); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(duplicate_line) | ||||
| CUSTOM_DOC("Create a copy of the line on which the cursor sits.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|      | ||||
|     Partition *part = &global_part; | ||||
|      | ||||
|     Temp_Memory temp = begin_temp_memory(part); | ||||
|     String line_string = {0}; | ||||
|     char *before_line = push_array(part, char, 1); | ||||
|     if (read_line(app, part, &buffer, view.cursor.line, &line_string)){ | ||||
|         *before_line = '\n'; | ||||
|         line_string.str = before_line; | ||||
|         line_string.size += 1; | ||||
|          | ||||
|         int32_t pos = buffer_get_line_end(app, &buffer, view.cursor.line); | ||||
|         buffer_replace_range(app, &buffer, pos, pos, line_string.str, line_string.size); | ||||
|     } | ||||
|     end_temp_memory(temp); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(delete_line) | ||||
| CUSTOM_DOC("Delete the line the on which the cursor sits.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|      | ||||
|     Partition *part = &global_part; | ||||
|      | ||||
|     Temp_Memory temp = begin_temp_memory(part); | ||||
|     int32_t start = buffer_get_line_start(app, &buffer, view.cursor.line); | ||||
|     int32_t end = buffer_get_line_end(app, &buffer, view.cursor.line) + 1; | ||||
|     if (end > buffer.size){ | ||||
|         end = buffer.size; | ||||
|     } | ||||
|     if (start == end || buffer_get_char(app, &buffer, end - 1) != '\n'){ | ||||
|         start -= 1; | ||||
|         if (start < 0){ | ||||
|             start = 0; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     buffer_replace_range(app, &buffer, start, end, 0, 0); | ||||
|      | ||||
|     end_temp_memory(temp); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(undo) | ||||
| CUSTOM_DOC("Advances backwards through the undo history.") | ||||
|  |  | |||
|  | @ -1,17 +1,9 @@ | |||
| /* 
 | ||||
|  * Mr. 4th Dimention - Allen Webster | ||||
|  *  | ||||
|  * 23.02.2016 | ||||
|  *  | ||||
|  * Types shared by custom and application | ||||
|  *  | ||||
|  * Buffer seek descriptor constructors. | ||||
|  */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| #if !defined(FRED_BUFFER_TYPES_H) | ||||
| #define FRED_BUFFER_TYPES_H | ||||
| 
 | ||||
| static Buffer_Seek | ||||
| seek_pos(int32_t pos){ | ||||
|     Buffer_Seek result; | ||||
|  | @ -67,7 +59,5 @@ seek_line_char(int32_t line, int32_t character){ | |||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  | @ -125,5 +125,19 @@ CUSTOM_DOC("If the previous command was paste or paste_next, replaces the paste | |||
|     } | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(paste_and_indent) | ||||
| CUSTOM_DOC("Paste from the top of clipboard and run auto-indent on the newly pasted text.") | ||||
| { | ||||
|     paste(app); | ||||
|     auto_tab_range(app); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(paste_next_and_indent) | ||||
| CUSTOM_DOC("Paste the next item on the clipboard and run auto-indent on the newly pasted text.") | ||||
| { | ||||
|     paste_next(app); | ||||
|     auto_tab_range(app); | ||||
| } | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,10 +7,6 @@ | |||
| #if !defined(FCODER_DEFAULT_FRAMEWORK_H) | ||||
| #define FCODER_DEFAULT_FRAMEWORK_H | ||||
| 
 | ||||
| #include "4coder_helper/4coder_helper.h" | ||||
| #include "4coder_lib/4coder_mem.h" | ||||
| #include "4coder_lib/4cpp_lexer.h" | ||||
| 
 | ||||
| enum Default_Maps{ | ||||
|     default_code_map, | ||||
|     default_maps_count, | ||||
|  |  | |||
|  | @ -4,11 +4,6 @@ | |||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| #if !defined(FCODER_DEFAULT_HOOKS_CPP) | ||||
| #define FCODER_DEFAULT_HOOKS_CPP | ||||
| 
 | ||||
| #include "4coder_helper/4coder_bind_helper.h" | ||||
| 
 | ||||
| #include "languages/4coder_language_cpp.h" | ||||
| #include "languages/4coder_language_rust.h" | ||||
| #include "languages/4coder_language_cs.h" | ||||
|  | @ -474,7 +469,5 @@ set_all_default_hooks(Bind_Helper *context){ | |||
|     set_buffer_name_resolver(context, default_buffer_name_resolution); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,17 +20,11 @@ | |||
| #include "4coder_lib/4coder_utf8.h" | ||||
| #include "4coder_lib/4cpp_lexer.h" | ||||
| 
 | ||||
| #include "4coder_helper/4coder_bind_helper.h" | ||||
| #include "4coder_helper/4coder_helper.h" | ||||
| 
 | ||||
| #include "4coder_helper/4coder_bind_helper.cpp" | ||||
| #include "4coder_helper/4coder_helper.cpp" | ||||
| 
 | ||||
| #include "4coder_helper/4coder_streaming.h" | ||||
| #include "4coder_helper/4coder_long_seek.h" | ||||
| 
 | ||||
| #include "4coder_helper.h" | ||||
| #include "4coder_default_framework.h" | ||||
| #include "4coder_seek.h" | ||||
| #include "4coder_auto_indent.h" | ||||
| #include "4coder_search.h" | ||||
| #include "4coder_build_commands.h" | ||||
| #include "4coder_jumping.h" | ||||
| #include "4coder_jump_sticky.h" | ||||
|  | @ -38,9 +32,11 @@ | |||
| #include "4coder_function_list.h" | ||||
| #include "4coder_scope_commands.h" | ||||
| 
 | ||||
| #include "4coder_buffer_seek_constructors.cpp" | ||||
| #include "4coder_helper.cpp" | ||||
| #include "4coder_default_framework.cpp" | ||||
| #include "4coder_seek.cpp" | ||||
| #include "4coder_base_commands.cpp" | ||||
| #include "4coder_seek_commands.cpp" | ||||
| #include "4coder_auto_indent.cpp" | ||||
| #include "4coder_search.cpp" | ||||
| #include "4coder_jumping.cpp" | ||||
|  | @ -55,176 +51,6 @@ | |||
| 
 | ||||
| #include "4coder_default_hooks.cpp" | ||||
| 
 | ||||
| //
 | ||||
| // Line Manipulation
 | ||||
| //
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(move_line_up) | ||||
| CUSTOM_DOC("Swaps the line under the cursor with the line above it, and moves the cursor up with it.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|      | ||||
|     if (view.cursor.line <= 1){ | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|     if (!buffer.exists){ | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     Full_Cursor prev_line_cursor = {0}; | ||||
|     Full_Cursor this_line_cursor = {0}; | ||||
|     Full_Cursor next_line_cursor = {0}; | ||||
|      | ||||
|     int32_t this_line = view.cursor.line; | ||||
|     int32_t prev_line = this_line - 1; | ||||
|     int32_t next_line = this_line +1; | ||||
|      | ||||
|     if (view_compute_cursor(app, &view, seek_line_char(prev_line, 1), &prev_line_cursor) && | ||||
|         view_compute_cursor(app, &view, seek_line_char(this_line, 1), &this_line_cursor) && | ||||
|         view_compute_cursor(app, &view, seek_line_char(next_line, 1), &next_line_cursor)){ | ||||
|          | ||||
|         int32_t prev_line_pos = prev_line_cursor.pos; | ||||
|         int32_t this_line_pos = this_line_cursor.pos; | ||||
|         int32_t next_line_pos = next_line_cursor.pos; | ||||
|          | ||||
|         Partition *part = &global_part; | ||||
|         Temp_Memory temp = begin_temp_memory(part); | ||||
|          | ||||
|         int32_t length = next_line_pos - prev_line_pos; | ||||
|         char *swap = push_array(part, char, length + 1); | ||||
|         int32_t first_len = next_line_pos - this_line_pos; | ||||
|          | ||||
|         if (buffer_read_range(app, &buffer, this_line_pos, next_line_pos, swap)){ | ||||
|             bool32 second_line_didnt_have_newline = true; | ||||
|             for (int32_t i = first_len - 1; i >= 0; --i){ | ||||
|                 if (swap[i] == '\n'){ | ||||
|                     second_line_didnt_have_newline = false; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             if (second_line_didnt_have_newline){ | ||||
|                 swap[first_len] = '\n'; | ||||
|                 first_len += 1; | ||||
|                 // NOTE(allen): Don't increase "length" because then we will be including
 | ||||
|                 // the original newline and addignt this new one, making the file longer
 | ||||
|                 // which shouldn't be possible for this command!
 | ||||
|             } | ||||
|              | ||||
|             if (buffer_read_range(app, &buffer, prev_line_pos, this_line_pos, swap + first_len)){ | ||||
|                 buffer_replace_range(app, &buffer, prev_line_pos, next_line_pos, swap, length); | ||||
|                 view_set_cursor(app, &view, seek_line_char(prev_line, 1), true); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         end_temp_memory(temp); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(move_down_textual) | ||||
| CUSTOM_DOC("Moves down to the next line of actual text, regardless of line wrapping.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     if (!view.exists){ | ||||
|         return; | ||||
|     } | ||||
|     int32_t next_line = view.cursor.line + 1; | ||||
|     view_set_cursor(app, &view, seek_line_char(next_line, 1), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(move_line_down) | ||||
| CUSTOM_DOC("Swaps the line under the cursor with the line below it, and moves the cursor down with it.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     if (!view.exists){ | ||||
|         return; | ||||
|     } | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|     if (!buffer.exists){ | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     int32_t next_line = view.cursor.line + 1; | ||||
|     Full_Cursor new_cursor = {0}; | ||||
|     if (view_compute_cursor(app, &view, seek_line_char(next_line, 1), &new_cursor)){ | ||||
|         if (new_cursor.line == next_line){ | ||||
|             view_set_cursor(app, &view, seek_pos(new_cursor.pos), true); | ||||
|             move_line_up(app); | ||||
|             move_down_textual(app); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(duplicate_line) | ||||
| CUSTOM_DOC("Create a copy of the line on which the cursor sits.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|      | ||||
|     Partition *part = &global_part; | ||||
|      | ||||
|     Temp_Memory temp = begin_temp_memory(part); | ||||
|     String line_string = {0}; | ||||
|     char *before_line = push_array(part, char, 1); | ||||
|     if (read_line(app, part, &buffer, view.cursor.line, &line_string)){ | ||||
|         *before_line = '\n'; | ||||
|         line_string.str = before_line; | ||||
|         line_string.size += 1; | ||||
|          | ||||
|         int32_t pos = buffer_get_line_end(app, &buffer, view.cursor.line); | ||||
|         buffer_replace_range(app, &buffer, pos, pos, line_string.str, line_string.size); | ||||
|     } | ||||
|     end_temp_memory(temp); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(delete_line) | ||||
| CUSTOM_DOC("Delete the line the on which the cursor sits.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|      | ||||
|     Partition *part = &global_part; | ||||
|      | ||||
|     Temp_Memory temp = begin_temp_memory(part); | ||||
|     int32_t start = buffer_get_line_start(app, &buffer, view.cursor.line); | ||||
|     int32_t end = buffer_get_line_end(app, &buffer, view.cursor.line) + 1; | ||||
|     if (end > buffer.size){ | ||||
|         end = buffer.size; | ||||
|     } | ||||
|     if (start == end || buffer_get_char(app, &buffer, end - 1) != '\n'){ | ||||
|         start -= 1; | ||||
|         if (start < 0){ | ||||
|             start = 0; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     buffer_replace_range(app, &buffer, start, end, 0, 0); | ||||
|      | ||||
|     end_temp_memory(temp); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //
 | ||||
| // Clipboard + Indent Combo Command
 | ||||
| //
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(paste_and_indent) | ||||
| CUSTOM_DOC("Paste from the top of clipboard and run auto-indent on the newly pasted text.") | ||||
| { | ||||
|     exec_command(app, paste); | ||||
|     exec_command(app, auto_tab_range); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(paste_next_and_indent) | ||||
| CUSTOM_DOC("Paste the next item on the clipboard and run auto-indent on the newly pasted text.") | ||||
| { | ||||
|     exec_command(app, paste_next); | ||||
|     exec_command(app, auto_tab_range); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //
 | ||||
| // Approximate Definition Search
 | ||||
| //
 | ||||
|  |  | |||
|  | @ -219,7 +219,7 @@ static Command_Metadata fcoder_metacmd_table[194] = { | |||
| { PROC_LINKS(auto_tab_range, 0), "auto_tab_range", 14,  "Auto-indents the range between the cursor and the mark.", 55, "C:\\work\\4ed\\code\\4coder_auto_indent.cpp", 43, 733 }, | ||||
| { PROC_LINKS(auto_tab_whole_file, 0), "auto_tab_whole_file", 19,  "Audo-indents the entire current buffer.", 39, "C:\\work\\4ed\\code\\4coder_auto_indent.cpp", 43, 712 }, | ||||
| { PROC_LINKS(backspace_char, 0), "backspace_char", 14,  "Deletes the character to the left of the cursor.", 48, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 71 }, | ||||
| { PROC_LINKS(backspace_word, 0), "backspace_word", 14,  "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 160 }, | ||||
| { PROC_LINKS(backspace_word, 0), "backspace_word", 14,  "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1150 }, | ||||
| { PROC_LINKS(basic_change_active_panel, 0), "basic_change_active_panel", 25,  "Change the currently active panel, moving to the panel with the next highest view_id.  Will not skipe the build panel if it is open.", 132, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 533 }, | ||||
| { PROC_LINKS(build_in_build_panel, 0), "build_in_build_panel", 20,  "Looks for a build.bat, build.sh, or makefile in the current and parent directories.  Runs the first that it finds and prints the output to *compilation*.  Puts the *compilation* buffer in a panel at the footer of the current view.", 230, "C:\\work\\4ed\\code\\4coder_build_commands.cpp", 46, 188 }, | ||||
| { PROC_LINKS(build_search, 0), "build_search", 12,  "Looks for a build.bat, build.sh, or makefile in the current and parent directories.  Runs the first that it finds and prints the output to *compilation*.", 153, "C:\\work\\4ed\\code\\4coder_build_commands.cpp", 46, 154 }, | ||||
|  | @ -241,14 +241,14 @@ static Command_Metadata fcoder_metacmd_table[194] = { | |||
| { PROC_LINKS(delete_char, 0), "delete_char", 11,  "Deletes the character to the right of the cursor.", 49, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 53 }, | ||||
| { PROC_LINKS(delete_current_scope, 0), "delete_current_scope", 20,  "Deletes the braces surrounding the currently selected scope.  Leaves the contents within the scope.", 99, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 487 }, | ||||
| { PROC_LINKS(delete_file_query, 0), "delete_file_query", 17,  "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1103 }, | ||||
| { PROC_LINKS(delete_line, 0), "delete_line", 11,  "Delete the line the on which the cursor sits.", 45, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 182 }, | ||||
| { PROC_LINKS(delete_line, 0), "delete_line", 11,  "Delete the line the on which the cursor sits.", 45, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 180 }, | ||||
| { PROC_LINKS(delete_range, 0), "delete_range", 12,  "Deletes the text in the range between the cursor and the mark.", 62, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 111 }, | ||||
| { PROC_LINKS(delete_word, 0), "delete_word", 11,  "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 166 }, | ||||
| { PROC_LINKS(duplicate_line, 0), "duplicate_line", 14,  "Create a copy of the line on which the cursor sits.", 51, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 160 }, | ||||
| { PROC_LINKS(delete_word, 0), "delete_word", 11,  "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1156 }, | ||||
| { PROC_LINKS(duplicate_line, 0), "duplicate_line", 14,  "Create a copy of the line on which the cursor sits.", 51, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 158 }, | ||||
| { PROC_LINKS(eol_dosify, 0), "eol_dosify", 10,  "Puts the buffer in DOS line ending mode.", 40, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 664 }, | ||||
| { PROC_LINKS(eol_nixify, 0), "eol_nixify", 10,  "Puts the buffer in NIX line ending mode.", 40, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 672 }, | ||||
| { PROC_LINKS(execute_any_cli, 0), "execute_any_cli", 15,  "Queries for an output buffer name and system command, runs the system command as a CLI and prints the output to the specified buffer.", 133, "C:\\work\\4ed\\code\\4coder_system_command.cpp", 46, 23 }, | ||||
| { PROC_LINKS(execute_arbitrary_command, 0), "execute_arbitrary_command", 25,  "Execute a 'long form' command.", 30, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 574 }, | ||||
| { PROC_LINKS(execute_arbitrary_command, 0), "execute_arbitrary_command", 25,  "Execute a 'long form' command.", 30, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 572 }, | ||||
| { PROC_LINKS(execute_previous_cli, 0), "execute_previous_cli", 20,  "If the command execute_any_cli has already been used, this will execute a CLI reusing the most recent buffer name and command.", 126, "C:\\work\\4ed\\code\\4coder_system_command.cpp", 46, 7 }, | ||||
| { PROC_LINKS(exit_4coder, 0), "exit_4coder", 11,  "Attempts to close 4coder.", 25, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 680 }, | ||||
| { PROC_LINKS(goto_beginning_of_file, 0), "goto_beginning_of_file", 22,  "Sets the cursor to the beginning of the file.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 406 }, | ||||
|  | @ -274,7 +274,7 @@ static Command_Metadata fcoder_metacmd_table[194] = { | |||
| { PROC_LINKS(highlight_next_scope_absolute, 0), "highlight_next_scope_absolute", 29,  "Finds the first scope started by '{' after the cursor and puts the cursor and mark on the '{' and '}'.", 102, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 363 }, | ||||
| { PROC_LINKS(highlight_prev_scope_absolute, 0), "highlight_prev_scope_absolute", 29,  "Finds the first scope started by '{' before the cursor and puts the cursor and mark on the '{' and '}'.", 103, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 382 }, | ||||
| { PROC_LINKS(highlight_surrounding_scope, 0), "highlight_surrounding_scope", 27,  "Finds the scope enclosed by '{' '}' surrounding the cursor and puts the cursor and mark on the '{' and '}'.", 107, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 341 }, | ||||
| { PROC_LINKS(if0_off, 0), "if0_off", 7,  "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 361 }, | ||||
| { PROC_LINKS(if0_off, 0), "if0_off", 7,  "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 359 }, | ||||
| { PROC_LINKS(increase_face_size, 0), "increase_face_size", 18,  "Increase the size of the face used by the current buffer.", 57, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 622 }, | ||||
| { PROC_LINKS(increase_line_wrap, 0), "increase_line_wrap", 18,  "Increases the current buffer's width for line wrapping.", 55, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 600 }, | ||||
| { PROC_LINKS(interactive_kill_buffer, 0), "interactive_kill_buffer", 23,  "Interactively kill an open buffer.", 34, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1282 }, | ||||
|  | @ -283,37 +283,37 @@ static Command_Metadata fcoder_metacmd_table[194] = { | |||
| { PROC_LINKS(interactive_open_or_new, 0), "interactive_open_or_new", 23,  "Interactively opens or creates a new file.", 42, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1270 }, | ||||
| { PROC_LINKS(interactive_switch_buffer, 0), "interactive_switch_buffer", 25,  "Interactively switch to an open buffer.", 39, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1276 }, | ||||
| { PROC_LINKS(kill_buffer, 0), "kill_buffer", 11,  "Kills the current buffer.", 25, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1300 }, | ||||
| { PROC_LINKS(kill_rect, 0), "kill_rect", 9,  "Delete characters in a rectangular region. Range testing is done by unwrapped-xy coordinates.", 93, "C:\\work\\4ed\\code\\power\\4coder_experiments.cpp", 50, 29 }, | ||||
| { PROC_LINKS(kill_rect, 0), "kill_rect", 9,  "Delete characters in a rectangular region. Range testing is done by unwrapped-xy coordinates.", 93, "C:\\work\\4ed\\code\\4coder_experiments.cpp", 43, 29 }, | ||||
| { PROC_LINKS(left_adjust_view, 0), "left_adjust_view", 16,  "Sets the left size of the view near the x position of the cursor.", 65, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 141 }, | ||||
| { PROC_LINKS(list_all_functions_current_buffer, 0), "list_all_functions_current_buffer", 33,  "Creates a jump list of lines of the current buffer that appear to define or declare functions.", 94, "C:\\work\\4ed\\code\\4coder_function_list.cpp", 45, 318 }, | ||||
| { PROC_LINKS(list_all_locations, 0), "list_all_locations", 18,  "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 698 }, | ||||
| { PROC_LINKS(list_all_locations_case_insensitive, 0), "list_all_locations_case_insensitive", 35,  "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 718 }, | ||||
| { PROC_LINKS(list_all_locations_of_identifier, 0), "list_all_locations_of_identifier", 32,  "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 782 }, | ||||
| { PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), "list_all_locations_of_identifier_case_insensitive", 49,  "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 788 }, | ||||
| { PROC_LINKS(list_all_locations_of_selection, 0), "list_all_locations_of_selection", 31,  "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 830 }, | ||||
| { PROC_LINKS(list_all_locations_of_selection_case_insensitive, 0), "list_all_locations_of_selection_case_insensitive", 48,  "Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.", 104, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 836 }, | ||||
| { PROC_LINKS(list_all_locations_of_type_definition, 0), "list_all_locations_of_type_definition", 37,  "Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.", 121, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 276 }, | ||||
| { PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), "list_all_locations_of_type_definition_of_identifier", 51,  "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 288 }, | ||||
| { PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28,  "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 708 }, | ||||
| { PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45,  "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 728 }, | ||||
| { PROC_LINKS(list_all_locations, 0), "list_all_locations", 18,  "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 675 }, | ||||
| { PROC_LINKS(list_all_locations_case_insensitive, 0), "list_all_locations_case_insensitive", 35,  "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 695 }, | ||||
| { PROC_LINKS(list_all_locations_of_identifier, 0), "list_all_locations_of_identifier", 32,  "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 759 }, | ||||
| { PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), "list_all_locations_of_identifier_case_insensitive", 49,  "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 765 }, | ||||
| { PROC_LINKS(list_all_locations_of_selection, 0), "list_all_locations_of_selection", 31,  "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 807 }, | ||||
| { PROC_LINKS(list_all_locations_of_selection_case_insensitive, 0), "list_all_locations_of_selection_case_insensitive", 48,  "Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.", 104, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 813 }, | ||||
| { PROC_LINKS(list_all_locations_of_type_definition, 0), "list_all_locations_of_type_definition", 37,  "Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.", 121, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 274 }, | ||||
| { PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), "list_all_locations_of_type_definition_of_identifier", 51,  "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 286 }, | ||||
| { PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28,  "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 685 }, | ||||
| { PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45,  "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 705 }, | ||||
| { PROC_LINKS(load_project, 0), "load_project", 12,  "Looks for a project.4coder file in the current directory and tries to load it.  Looks in parent directories until a project file is found or there are no more parents.", 167, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 426 }, | ||||
| { PROC_LINKS(make_directory_query, 0), "make_directory_query", 20,  "Queries the user for a name and creates a new directory with the given name.", 76, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1211 }, | ||||
| { PROC_LINKS(miblo_decrement_basic, 0), "miblo_decrement_basic", 21,  "Decrement an integer under the cursor by one.", 45, "C:\\work\\4ed\\code\\power\\4coder_miblo_numbers.cpp", 52, 117 }, | ||||
| { PROC_LINKS(miblo_decrement_time_stamp, 0), "miblo_decrement_time_stamp", 26,  "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\power\\4coder_miblo_numbers.cpp", 52, 390 }, | ||||
| { PROC_LINKS(miblo_decrement_time_stamp_minute, 0), "miblo_decrement_time_stamp_minute", 33,  "Decrement a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\power\\4coder_miblo_numbers.cpp", 52, 402 }, | ||||
| { PROC_LINKS(miblo_increment_basic, 0), "miblo_increment_basic", 21,  "Increment an integer under the cursor by one.", 45, "C:\\work\\4ed\\code\\power\\4coder_miblo_numbers.cpp", 52, 101 }, | ||||
| { PROC_LINKS(miblo_increment_time_stamp, 0), "miblo_increment_time_stamp", 26,  "Increment a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\power\\4coder_miblo_numbers.cpp", 52, 384 }, | ||||
| { PROC_LINKS(miblo_increment_time_stamp_minute, 0), "miblo_increment_time_stamp_minute", 33,  "Increment a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\power\\4coder_miblo_numbers.cpp", 52, 396 }, | ||||
| { PROC_LINKS(miblo_decrement_basic, 0), "miblo_decrement_basic", 21,  "Decrement an integer under the cursor by one.", 45, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 117 }, | ||||
| { PROC_LINKS(miblo_decrement_time_stamp, 0), "miblo_decrement_time_stamp", 26,  "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 390 }, | ||||
| { PROC_LINKS(miblo_decrement_time_stamp_minute, 0), "miblo_decrement_time_stamp_minute", 33,  "Decrement a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 402 }, | ||||
| { PROC_LINKS(miblo_increment_basic, 0), "miblo_increment_basic", 21,  "Increment an integer under the cursor by one.", 45, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 101 }, | ||||
| { PROC_LINKS(miblo_increment_time_stamp, 0), "miblo_increment_time_stamp", 26,  "Increment a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 384 }, | ||||
| { PROC_LINKS(miblo_increment_time_stamp_minute, 0), "miblo_increment_time_stamp_minute", 33,  "Increment a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 396 }, | ||||
| { PROC_LINKS(move_down, 0), "move_down", 9,  "Moves the cursor down one line.", 31, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 238 }, | ||||
| { PROC_LINKS(move_down_10, 0), "move_down_10", 12,  "Moves the cursor down ten lines.", 32, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 250 }, | ||||
| { PROC_LINKS(move_down_textual, 0), "move_down_textual", 17,  "Moves down to the next line of actual text, regardless of line wrapping.", 72, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 126 }, | ||||
| { PROC_LINKS(move_down_textual, 0), "move_down_textual", 17,  "Moves down to the next line of actual text, regardless of line wrapping.", 72, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 124 }, | ||||
| { PROC_LINKS(move_left, 0), "move_left", 9,  "Moves the cursor one character to the left.", 43, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 291 }, | ||||
| { PROC_LINKS(move_line_down, 0), "move_line_down", 14,  "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 137 }, | ||||
| { PROC_LINKS(move_line_up, 0), "move_line_up", 12,  "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 62 }, | ||||
| { PROC_LINKS(move_line_down, 0), "move_line_down", 14,  "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 135 }, | ||||
| { PROC_LINKS(move_line_up, 0), "move_line_up", 12,  "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 60 }, | ||||
| { PROC_LINKS(move_right, 0), "move_right", 10,  "Moves the cursor one character to the right.", 44, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 300 }, | ||||
| { PROC_LINKS(move_up, 0), "move_up", 7,  "Moves the cursor up one line.", 29, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 232 }, | ||||
| { PROC_LINKS(move_up_10, 0), "move_up_10", 10,  "Moves the cursor up ten lines.", 30, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 244 }, | ||||
| { PROC_LINKS(multi_line_edit, 0), "multi_line_edit", 15,  "Begin multi-line mode.  In multi-line mode characters are inserted at every line between the mark and cursor.  All characters are inserted at the same character offset into the line.  This mode uses line_char coordinates.", 221, "C:\\work\\4ed\\code\\power\\4coder_experiments.cpp", 50, 120 }, | ||||
| { PROC_LINKS(multi_line_edit, 0), "multi_line_edit", 15,  "Begin multi-line mode.  In multi-line mode characters are inserted at every line between the mark and cursor.  All characters are inserted at the same character offset into the line.  This mode uses line_char coordinates.", 221, "C:\\work\\4ed\\code\\4coder_experiments.cpp", 43, 120 }, | ||||
| { PROC_LINKS(newline_or_goto_position_direct, 0), "newline_or_goto_position_direct", 31,  "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "C:\\work\\4ed\\code\\4coder_jump_direct.cpp", 43, 101 }, | ||||
| { PROC_LINKS(newline_or_goto_position_same_panel_direct, 0), "newline_or_goto_position_same_panel_direct", 42,  "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_direct.cpp", 43, 116 }, | ||||
| { PROC_LINKS(newline_or_goto_position_same_panel_sticky, 0), "newline_or_goto_position_same_panel_sticky", 42,  "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_sticky.cpp", 43, 571 }, | ||||
|  | @ -321,20 +321,20 @@ static Command_Metadata fcoder_metacmd_table[194] = { | |||
| { PROC_LINKS(open_all_code, 0), "open_all_code", 13,  "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 410 }, | ||||
| { PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23,  "Works as open_all_code but also runs in all subdirectories.", 59, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 417 }, | ||||
| { PROC_LINKS(open_color_tweaker, 0), "open_color_tweaker", 18,  "Opens the 4coder colors and fonts selector menu.", 48, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1306 }, | ||||
| { PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19,  "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 458 }, | ||||
| { PROC_LINKS(open_in_other, 0), "open_in_other", 13,  "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file, displaying it in the other view.", 127, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 475 }, | ||||
| { PROC_LINKS(open_long_braces, 0), "open_long_braces", 16,  "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 337 }, | ||||
| { PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22,  "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 353 }, | ||||
| { PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26,  "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 345 }, | ||||
| { PROC_LINKS(open_matching_file_cpp, 0), "open_matching_file_cpp", 22,  "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 531 }, | ||||
| { PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19,  "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 456 }, | ||||
| { PROC_LINKS(open_in_other, 0), "open_in_other", 13,  "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file, displaying it in the other view.", 127, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 473 }, | ||||
| { PROC_LINKS(open_long_braces, 0), "open_long_braces", 16,  "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 335 }, | ||||
| { PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22,  "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 351 }, | ||||
| { PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26,  "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 343 }, | ||||
| { PROC_LINKS(open_matching_file_cpp, 0), "open_matching_file_cpp", 22,  "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 529 }, | ||||
| { PROC_LINKS(open_panel_hsplit, 0), "open_panel_hsplit", 17,  "Create a new panel by horizontally splitting the active panel.", 62, "C:\\work\\4ed\\code\\4coder_default_framework.cpp", 49, 192 }, | ||||
| { PROC_LINKS(open_panel_vsplit, 0), "open_panel_vsplit", 17,  "Create a new panel by vertically splitting the active panel.", 60, "C:\\work\\4ed\\code\\4coder_default_framework.cpp", 49, 183 }, | ||||
| { PROC_LINKS(page_down, 0), "page_down", 9,  "Scrolls the view down one view height and moves the cursor down one view height.", 80, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 281 }, | ||||
| { PROC_LINKS(page_up, 0), "page_up", 7,  "Scrolls the view up one view height and moves the cursor up one view height.", 76, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 272 }, | ||||
| { PROC_LINKS(paste, 0), "paste", 5,  "At the cursor, insert the text at the top of the clipboard.", 59, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 46 }, | ||||
| { PROC_LINKS(paste_and_indent, 0), "paste_and_indent", 16,  "Paste from the top of clipboard and run auto-indent on the newly pasted text.", 77, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 213 }, | ||||
| { PROC_LINKS(paste_and_indent, 0), "paste_and_indent", 16,  "Paste from the top of clipboard and run auto-indent on the newly pasted text.", 77, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 211 }, | ||||
| { PROC_LINKS(paste_next, 0), "paste_next", 10,  "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 84 }, | ||||
| { PROC_LINKS(paste_next_and_indent, 0), "paste_next_and_indent", 21,  "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 220 }, | ||||
| { PROC_LINKS(paste_next_and_indent, 0), "paste_next_and_indent", 21,  "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 218 }, | ||||
| { PROC_LINKS(place_in_scope, 0), "place_in_scope", 14,  "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 481 }, | ||||
| { PROC_LINKS(project_fkey_command, 0), "project_fkey_command", 20,  "Run an 'fkey command' configured in a project.4coder file.  Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 497 }, | ||||
| { PROC_LINKS(project_go_to_root_directory, 0), "project_go_to_root_directory", 28,  "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 522 }, | ||||
|  | @ -345,9 +345,9 @@ static Command_Metadata fcoder_metacmd_table[194] = { | |||
| { PROC_LINKS(reload_current_project, 0), "reload_current_project", 22,  "If a project file has already been loaded, reloads the same file.  Useful for when the project configuration is changed.", 120, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 465 }, | ||||
| { PROC_LINKS(remap_interactive, 0), "remap_interactive", 17,  "Switch to a named key binding map.", 34, "C:\\work\\4ed\\code\\4coder_default_framework.cpp", 49, 578 }, | ||||
| { PROC_LINKS(rename_file_query, 0), "rename_file_query", 17,  "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1169 }, | ||||
| { PROC_LINKS(rename_parameter, 0), "rename_parameter", 16,  "If the cursor is found to be on the name of a function parameter in the signature of a function definition, all occurences within the scope of the function will be replaced with a new provided string.", 200, "C:\\work\\4ed\\code\\power\\4coder_experiments.cpp", 50, 385 }, | ||||
| { PROC_LINKS(rename_parameter, 0), "rename_parameter", 16,  "If the cursor is found to be on the name of a function parameter in the signature of a function definition, all occurences within the scope of the function will be replaced with a new provided string.", 200, "C:\\work\\4ed\\code\\4coder_experiments.cpp", 43, 385 }, | ||||
| { PROC_LINKS(reopen, 0), "reopen", 6,  "Reopen the current buffer from the hard drive.", 46, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1288 }, | ||||
| { PROC_LINKS(replace_all_occurrences, 0), "replace_all_occurrences", 23,  "Queries the user for two strings, and replaces all occurrences of the first string with the second string in all open buffers.", 126, "C:\\work\\4ed\\code\\power\\4coder_experiments.cpp", 50, 771 }, | ||||
| { PROC_LINKS(replace_all_occurrences, 0), "replace_all_occurrences", 23,  "Queries the user for two strings, and replaces all occurrences of the first string with the second string in all open buffers.", 126, "C:\\work\\4ed\\code\\4coder_experiments.cpp", 43, 771 }, | ||||
| { PROC_LINKS(replace_in_range, 0), "replace_in_range", 16,  "Queries the user for two strings, and replaces all occurences of the first string in the range between the cursor and the mark with the second string.", 150, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 899 }, | ||||
| { PROC_LINKS(reverse_search, 0), "reverse_search", 14,  "Begins an incremental search up through the current buffer for a user specified string.", 87, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 870 }, | ||||
| { PROC_LINKS(reverse_search_identifier, 0), "reverse_search_identifier", 25,  "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 888 }, | ||||
|  | @ -357,22 +357,22 @@ static Command_Metadata fcoder_metacmd_table[194] = { | |||
| { PROC_LINKS(scope_absorb_down, 0), "scope_absorb_down", 17,  "If a scope is currently selected, and a statement or block statement is present below the current scope, the statement is moved into the scope.", 143, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 738 }, | ||||
| { PROC_LINKS(search, 0), "search", 6,  "Begins an incremental search down through the current buffer for a user specified string.", 89, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 863 }, | ||||
| { PROC_LINKS(search_identifier, 0), "search_identifier", 17,  "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 877 }, | ||||
| { PROC_LINKS(seek_alphanumeric_left, 0), "seek_alphanumeric_left", 22,  "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 140 }, | ||||
| { PROC_LINKS(seek_alphanumeric_or_camel_left, 0), "seek_alphanumeric_or_camel_left", 31,  "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 152 }, | ||||
| { PROC_LINKS(seek_alphanumeric_or_camel_right, 0), "seek_alphanumeric_or_camel_right", 32,  "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 146 }, | ||||
| { PROC_LINKS(seek_alphanumeric_right, 0), "seek_alphanumeric_right", 23,  "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 134 }, | ||||
| { PROC_LINKS(seek_alphanumeric_left, 0), "seek_alphanumeric_left", 22,  "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1130 }, | ||||
| { PROC_LINKS(seek_alphanumeric_or_camel_left, 0), "seek_alphanumeric_or_camel_left", 31,  "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1142 }, | ||||
| { PROC_LINKS(seek_alphanumeric_or_camel_right, 0), "seek_alphanumeric_or_camel_right", 32,  "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1136 }, | ||||
| { PROC_LINKS(seek_alphanumeric_right, 0), "seek_alphanumeric_right", 23,  "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1124 }, | ||||
| { PROC_LINKS(seek_beginning_of_line, 0), "seek_beginning_of_line", 22,  "Seeks the cursor to the beginning of the visual line.", 53, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 366 }, | ||||
| { PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30,  "Seeks the cursor to the beginning of the line across all text.", 62, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 344 }, | ||||
| { PROC_LINKS(seek_end_of_line, 0), "seek_end_of_line", 16,  "Seeks the cursor to the end of the visual line.", 47, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 379 }, | ||||
| { PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24,  "Seeks the cursor to the end of the line across all text.", 56, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 355 }, | ||||
| { PROC_LINKS(seek_token_left, 0), "seek_token_left", 15,  "Seek left for the next beginning of a token.", 44, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 116 }, | ||||
| { PROC_LINKS(seek_token_right, 0), "seek_token_right", 16,  "Seek right for the next end of a token.", 39, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 110 }, | ||||
| { PROC_LINKS(seek_white_or_token_left, 0), "seek_white_or_token_left", 24,  "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 128 }, | ||||
| { PROC_LINKS(seek_white_or_token_right, 0), "seek_white_or_token_right", 25,  "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 122 }, | ||||
| { PROC_LINKS(seek_token_left, 0), "seek_token_left", 15,  "Seek left for the next beginning of a token.", 44, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1106 }, | ||||
| { PROC_LINKS(seek_token_right, 0), "seek_token_right", 16,  "Seek right for the next end of a token.", 39, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1100 }, | ||||
| { PROC_LINKS(seek_white_or_token_left, 0), "seek_white_or_token_left", 24,  "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1118 }, | ||||
| { PROC_LINKS(seek_white_or_token_right, 0), "seek_white_or_token_right", 25,  "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1112 }, | ||||
| { PROC_LINKS(seek_whitespace_down, 0), "seek_whitespace_down", 20,  "Seeks the cursor down to the next blank line.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 333 }, | ||||
| { PROC_LINKS(seek_whitespace_down_end_line, 0), "seek_whitespace_down_end_line", 29,  "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 399 }, | ||||
| { PROC_LINKS(seek_whitespace_left, 0), "seek_whitespace_left", 20,  "Seek left for the next boundary between whitespace and non-whitespace.", 70, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 104 }, | ||||
| { PROC_LINKS(seek_whitespace_right, 0), "seek_whitespace_right", 21,  "Seek right for the next boundary between whitespace and non-whitespace.", 71, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 98 }, | ||||
| { PROC_LINKS(seek_whitespace_left, 0), "seek_whitespace_left", 20,  "Seek left for the next boundary between whitespace and non-whitespace.", 70, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1094 }, | ||||
| { PROC_LINKS(seek_whitespace_right, 0), "seek_whitespace_right", 21,  "Seek right for the next boundary between whitespace and non-whitespace.", 71, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1088 }, | ||||
| { PROC_LINKS(seek_whitespace_up, 0), "seek_whitespace_up", 18,  "Seeks the cursor up to the next blank line.", 43, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 322 }, | ||||
| { PROC_LINKS(seek_whitespace_up_end_line, 0), "seek_whitespace_up_end_line", 27,  "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 392 }, | ||||
| { PROC_LINKS(select_all, 0), "select_all", 10,  "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 309 }, | ||||
|  | @ -383,10 +383,10 @@ static Command_Metadata fcoder_metacmd_table[194] = { | |||
| { PROC_LINKS(setup_new_project, 0), "setup_new_project", 17,  "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 569 }, | ||||
| { PROC_LINKS(show_filebar, 0), "show_filebar", 12,  "Sets the current view to show it's filebar.", 43, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 567 }, | ||||
| { PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14,  "Sets the current view to show it's scrollbar.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 553 }, | ||||
| { PROC_LINKS(snipe_token_or_word, 0), "snipe_token_or_word", 19,  "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 172 }, | ||||
| { PROC_LINKS(snipe_token_or_word_right, 0), "snipe_token_or_word_right", 25,  "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "C:\\work\\4ed\\code\\4coder_seek_commands.cpp", 45, 178 }, | ||||
| { PROC_LINKS(snipe_token_or_word, 0), "snipe_token_or_word", 19,  "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1162 }, | ||||
| { PROC_LINKS(snipe_token_or_word_right, 0), "snipe_token_or_word_right", 25,  "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1168 }, | ||||
| { PROC_LINKS(suppress_mouse, 0), "suppress_mouse", 14,  "Hides the mouse and causes all mosue input (clicks, position, wheel) to be ignored.", 83, "C:\\work\\4ed\\code\\4coder_default_framework.cpp", 49, 215 }, | ||||
| { PROC_LINKS(swap_buffers_between_panels, 0), "swap_buffers_between_panels", 27,  "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 555 }, | ||||
| { PROC_LINKS(swap_buffers_between_panels, 0), "swap_buffers_between_panels", 27,  "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 553 }, | ||||
| { PROC_LINKS(to_lowercase, 0), "to_lowercase", 12,  "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 445 }, | ||||
| { PROC_LINKS(to_uppercase, 0), "to_uppercase", 12,  "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 425 }, | ||||
| { PROC_LINKS(toggle_filebar, 0), "toggle_filebar", 14,  "Toggles the visibility status of the current view's filebar.", 60, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 581 }, | ||||
|  | @ -396,18 +396,18 @@ static Command_Metadata fcoder_metacmd_table[194] = { | |||
| { PROC_LINKS(toggle_show_whitespace, 0), "toggle_show_whitespace", 22,  "Toggles the current buffer's whitespace visibility status.", 58, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 657 }, | ||||
| { PROC_LINKS(toggle_virtual_whitespace, 0), "toggle_virtual_whitespace", 25,  "Toggles the current buffer's virtual whitespace status.", 55, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 646 }, | ||||
| { PROC_LINKS(undo, 0), "undo", 4,  "Advances backwards through the undo history.", 44, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1246 }, | ||||
| { PROC_LINKS(view_buffer_other_panel, 0), "view_buffer_other_panel", 23,  "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 545 }, | ||||
| { PROC_LINKS(word_complete, 0), "word_complete", 13,  "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 859 }, | ||||
| { PROC_LINKS(view_buffer_other_panel, 0), "view_buffer_other_panel", 23,  "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 543 }, | ||||
| { PROC_LINKS(word_complete, 0), "word_complete", 13,  "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 826 }, | ||||
| { PROC_LINKS(write_and_auto_tab, 0), "write_and_auto_tab", 18,  "Inserts a character and auto-indents the line on which the cursor sits.", 71, "C:\\work\\4ed\\code\\4coder_auto_indent.cpp", 43, 745 }, | ||||
| { PROC_LINKS(write_block, 0), "write_block", 11,  "At the cursor, insert a block comment.", 38, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 408 }, | ||||
| { PROC_LINKS(write_block, 0), "write_block", 11,  "At the cursor, insert a block comment.", 38, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 406 }, | ||||
| { PROC_LINKS(write_character, 0), "write_character", 15,  "Inserts whatever character was used to trigger this command.", 60, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 37 }, | ||||
| { PROC_LINKS(write_explicit_enum_flags, 0), "write_explicit_enum_flags", 25,  "If the cursor is found to be on the '{' of an enum definition, the values of the enum will be filled in to give each a unique power of 2 value, starting from 1.  Existing values are overwritten.", 194, "C:\\work\\4ed\\code\\power\\4coder_experiments.cpp", 50, 707 }, | ||||
| { PROC_LINKS(write_explicit_enum_values, 0), "write_explicit_enum_values", 26,  "If the cursor is found to be on the '{' of an enum definition, the values of the enum will be filled in sequentially starting from zero.  Existing values are overwritten.", 170, "C:\\work\\4ed\\code\\power\\4coder_experiments.cpp", 50, 701 }, | ||||
| { PROC_LINKS(write_hack, 0), "write_hack", 10,  "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 396 }, | ||||
| { PROC_LINKS(write_note, 0), "write_note", 10,  "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 402 }, | ||||
| { PROC_LINKS(write_todo, 0), "write_todo", 10,  "At the cursor, insert a '// TODO' comment, includes user name if it was specified in config.4coder.", 99, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 390 }, | ||||
| { PROC_LINKS(write_explicit_enum_flags, 0), "write_explicit_enum_flags", 25,  "If the cursor is found to be on the '{' of an enum definition, the values of the enum will be filled in to give each a unique power of 2 value, starting from 1.  Existing values are overwritten.", 194, "C:\\work\\4ed\\code\\4coder_experiments.cpp", 43, 707 }, | ||||
| { PROC_LINKS(write_explicit_enum_values, 0), "write_explicit_enum_values", 26,  "If the cursor is found to be on the '{' of an enum definition, the values of the enum will be filled in sequentially starting from zero.  Existing values are overwritten.", 170, "C:\\work\\4ed\\code\\4coder_experiments.cpp", 43, 701 }, | ||||
| { PROC_LINKS(write_hack, 0), "write_hack", 10,  "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 394 }, | ||||
| { PROC_LINKS(write_note, 0), "write_note", 10,  "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 400 }, | ||||
| { PROC_LINKS(write_todo, 0), "write_todo", 10,  "At the cursor, insert a '// TODO' comment, includes user name if it was specified in config.4coder.", 99, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 388 }, | ||||
| { PROC_LINKS(write_underscore, 0), "write_underscore", 16,  "Inserts an underscore.", 22, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 46 }, | ||||
| { PROC_LINKS(write_zero_struct, 0), "write_zero_struct", 17,  "At the cursor, insert a ' = {0};'.", 34, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 414 }, | ||||
| { PROC_LINKS(write_zero_struct, 0), "write_zero_struct", 17,  "At the cursor, insert a ' = {0};'.", 34, "C:\\work\\4ed\\code\\4coder_default_include.cpp", 47, 412 }, | ||||
| }; | ||||
| static int32_t fcoder_metacmd_ID_allow_mouse = 0; | ||||
| static int32_t fcoder_metacmd_ID_auto_tab_line_at_cursor = 1; | ||||
|  |  | |||
|  | @ -0,0 +1,977 @@ | |||
| /*
 | ||||
|  * Miscellaneous helpers for common operations. | ||||
|  */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| inline Binding_Unit* | ||||
| write_unit(Bind_Helper *helper, Binding_Unit unit){ | ||||
|     Binding_Unit *p = 0; | ||||
|     helper->write_total += sizeof(*p); | ||||
|     if (helper->error == 0 && helper->cursor != helper->end){ | ||||
|         p = helper->cursor++; | ||||
|         *p = unit; | ||||
|     } | ||||
|     return p; | ||||
| } | ||||
| 
 | ||||
| inline Bind_Helper | ||||
| begin_bind_helper(void *data, int32_t size){ | ||||
|     Bind_Helper result = {0}; | ||||
|     result.cursor = (Binding_Unit*)data; | ||||
|     result.start = result.cursor; | ||||
|     result.end = result.start + size / sizeof(*result.cursor); | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_header; | ||||
|     unit.header.total_size = sizeof(*result.header); | ||||
|     result.header = write_unit(&result, unit); | ||||
|     result.header->header.user_map_count = 0; | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| begin_map(Bind_Helper *helper, int32_t mapid, bool32 replace){ | ||||
|     if (helper->group != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END; | ||||
|     if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count; | ||||
|      | ||||
|     Binding_Unit unit; | ||||
|     unit.type = unit_map_begin; | ||||
|     unit.map_begin.mapid = mapid; | ||||
|     unit.map_begin.replace = replace; | ||||
|     helper->group = write_unit(helper, unit); | ||||
|     helper->group->map_begin.bind_count = 0; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| begin_map(Bind_Helper *helper, int32_t mapid){ | ||||
|     begin_map(helper, mapid, false); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| restart_map(Bind_Helper *helper, int32_t mapid){ | ||||
|     begin_map(helper, mapid, true); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| end_map(Bind_Helper *helper){ | ||||
|     if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; | ||||
|     helper->group = 0; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind(Bind_Helper *helper, Key_Code code, uint8_t modifiers, Command_ID cmdid){ | ||||
|     if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; | ||||
|     if (!helper->error) ++helper->group->map_begin.bind_count; | ||||
|      | ||||
|     Binding_Unit unit; | ||||
|     unit.type = unit_binding; | ||||
|     unit.binding.command_id = cmdid; | ||||
|     unit.binding.code = code; | ||||
|     unit.binding.modifiers = modifiers; | ||||
|      | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind(Bind_Helper *helper, Key_Code code, uint8_t modifiers, Custom_Command_Function *func){ | ||||
|     if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; | ||||
|     if (!helper->error) ++helper->group->map_begin.bind_count; | ||||
|      | ||||
|     Binding_Unit unit; | ||||
|     unit.type = unit_callback; | ||||
|     unit.callback.func = func; | ||||
|     unit.callback.code = code; | ||||
|     unit.callback.modifiers = modifiers; | ||||
|      | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind(Bind_Helper *helper, Key_Code code, uint8_t modifiers, Generic_Command cmd){ | ||||
|     if (cmd.cmdid < cmdid_count){ | ||||
|         bind(helper, code, modifiers, cmd.cmdid); | ||||
|     } | ||||
|     else{ | ||||
|         bind(helper, code, modifiers, cmd.command); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind_vanilla_keys(Bind_Helper *helper, int32_t cmdid){ | ||||
|     bind(helper, 0, 0, cmdid); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind_vanilla_keys(Bind_Helper *helper, Custom_Command_Function *func){ | ||||
|     bind(helper, 0, 0, func); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, int32_t cmdid){ | ||||
|     bind(helper, 0, modifiers, cmdid); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, Custom_Command_Function *func){ | ||||
|     bind(helper, 0, modifiers, func); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| inherit_map(Bind_Helper *helper, int32_t mapid){ | ||||
|     if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; | ||||
|     if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count; | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_inherit; | ||||
|     unit.map_inherit.mapid = mapid; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_hook(Bind_Helper *helper, int32_t hook_id, Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = hook_id; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_scroll_rule(Bind_Helper *helper, Scroll_Rule_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_scroll_rule; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_buffer_name_resolver(Bind_Helper *helper, Buffer_Name_Resolver_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_buffer_name_resolver; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_new_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_new_file; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_start_hook(Bind_Helper *helper, Start_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_start; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_open_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_open_file; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_save_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_save_file; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_end_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_end_file; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_command_caller(Bind_Helper *helper, Command_Caller_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_command_caller; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_input_filter(Bind_Helper *helper, Input_Filter_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_input_filter; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline int32_t | ||||
| end_bind_helper(Bind_Helper *helper){ | ||||
|     if (helper->header){ | ||||
|         helper->header->header.total_size = (int32_t)(helper->cursor - helper->start); | ||||
|         helper->header->header.error = helper->error; | ||||
|     } | ||||
|     int32_t result = helper->write_total; | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| inline Bind_Buffer | ||||
| end_bind_helper_get_buffer(Bind_Helper *helper){ | ||||
|     int32_t size = end_bind_helper(helper); | ||||
|     Bind_Buffer result = {0}; | ||||
|     result.data = helper->start; | ||||
|     result.size = size; | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static u32_4tech | ||||
| get_key_code(char *buffer){ | ||||
|     u32_4tech ignore; | ||||
|     u32_4tech result = utf8_to_u32_length_unchecked((u8_4tech*)buffer, &ignore); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| static int32_t | ||||
| round_down(int32_t x, int32_t b){ | ||||
|     int32_t r = 0; | ||||
|     if (x >= 0){ | ||||
|         r = x - (x % b); | ||||
|     } | ||||
|     return(r); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| round_up(int32_t x, int32_t b){ | ||||
|     int32_t r = 0; | ||||
|     if (x >= 0){ | ||||
|         r = x + b - (x % b); | ||||
|     } | ||||
|     return(r); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| exec_command(Application_Links *app, Custom_Command_Function *func){ | ||||
|     func(app); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| exec_command(Application_Links *app, Generic_Command cmd){ | ||||
|     if (cmd.cmdid < cmdid_count){ | ||||
|         exec_command(app, cmd.cmdid); | ||||
|     } | ||||
|     else{ | ||||
|         exec_command(app, cmd.command); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| key_is_unmodified(Key_Event_Data *key){ | ||||
|     int8_t *mods = key->modifiers; | ||||
|     int32_t unmodified = (!mods[MDFR_CONTROL_INDEX] && !mods[MDFR_ALT_INDEX]); | ||||
|     return(unmodified); | ||||
| } | ||||
| 
 | ||||
| static uint32_t | ||||
| to_writable_character(User_Input in, uint8_t *character){ | ||||
|     uint32_t result = 0; | ||||
|     if (in.type == UserInputKey){ | ||||
|         if (in.key.character != 0){ | ||||
|             u32_to_utf8_unchecked(in.key.character, character, &result); | ||||
|         } | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static uint32_t | ||||
| to_writable_character(Key_Event_Data key, uint8_t *character){ | ||||
|     uint32_t result = 0; | ||||
|     if (key.character != 0){ | ||||
|         u32_to_utf8_unchecked(key.character, character, &result); | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| backspace_utf8(String *str){ | ||||
|     bool32 result = false; | ||||
|     uint8_t *s = (uint8_t*)str->str; | ||||
|     if (str->size > 0){ | ||||
|         uint32_t i = str->size-1; | ||||
|         for (; i > 0; --i){ | ||||
|             if (s[i] <= 0x7F || s[i] >= 0xC0){ | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         str->size = i; | ||||
|         result = true; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| query_user_general(Application_Links *app, Query_Bar *bar, bool32 force_number){ | ||||
|     bool32 success = true; | ||||
|      | ||||
|     // NOTE(allen|a3.4.4): It will not cause an *error* if we continue on after failing to.
 | ||||
|     // start a query bar, but it will be unusual behavior from the point of view of the
 | ||||
|     // user, if this command starts intercepting input even though no prompt is shown.
 | ||||
|     // This will only happen if you have a lot of bars open already or if the current view
 | ||||
|     // doesn't support query bars.
 | ||||
|     if (start_query_bar(app, bar, 0) == 0) return 0; | ||||
|      | ||||
|     for (;;){ | ||||
|         // NOTE(allen|a3.4.4): This call will block until the user does one of the input
 | ||||
|         // types specified in the flags.  The first set of flags are inputs you'd like to intercept
 | ||||
|         // that you don't want to abort on.  The second set are inputs that you'd like to cause
 | ||||
|         // the command to abort.  If an event satisfies both flags, it is treated as an abort.
 | ||||
|         User_Input in = get_user_input(app, EventOnAnyKey, EventOnEsc | EventOnButton); | ||||
|          | ||||
|         // NOTE(allen|a3.4.4): The responsible thing to do on abort is to end the command
 | ||||
|         // without waiting on get_user_input again.
 | ||||
|         if (in.abort){ | ||||
|             success = false; | ||||
|             break; | ||||
|         } | ||||
|          | ||||
|         uint8_t character[4]; | ||||
|         uint32_t length = 0; | ||||
|         bool32 good_character = false; | ||||
|         if (key_is_unmodified(&in.key)){ | ||||
|             if (force_number){ | ||||
|                 if (in.key.character >= '0' && in.key.character <= '9'){ | ||||
|                     good_character = true; | ||||
|                     length = to_writable_character(in, character); | ||||
|                 } | ||||
|             } | ||||
|             else{ | ||||
|                 length = to_writable_character(in, character); | ||||
|                 if (length != 0){ | ||||
|                     good_character = true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         // NOTE(allen|a3.4.4): All we have to do to update the query bar is edit our
 | ||||
|         // local Query_Bar struct!  This is handy because it means our Query_Bar
 | ||||
|         // is always correct for typical use without extra work updating the bar.
 | ||||
|         if (in.type == UserInputKey){ | ||||
|             if (in.key.keycode == '\n' || in.key.keycode == '\t'){ | ||||
|                 break; | ||||
|             } | ||||
|             else if (in.key.keycode == key_back){ | ||||
|                 backspace_utf8(&bar->string); | ||||
|             } | ||||
|             else if (good_character){ | ||||
|                 append_ss(&bar->string, make_string(character, length)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     terminate_with_null(&bar->string); | ||||
|      | ||||
|     return(success); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| query_user_string(Application_Links *app, Query_Bar *bar){ | ||||
|     int32_t success = query_user_general(app, bar, false); | ||||
|     return(success); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| query_user_number(Application_Links *app, Query_Bar *bar){ | ||||
|     int32_t success = query_user_general(app, bar, true); | ||||
|     return(success); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| init_theme_zero(Theme *theme){ | ||||
|     for (int32_t i = 0; i < Stag_COUNT; ++i){ | ||||
|         theme->colors[i] = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static char | ||||
| buffer_get_char(Application_Links *app, Buffer_Summary *buffer, int32_t pos){ | ||||
|     char result = ' '; | ||||
|     *buffer = get_buffer(app, buffer->buffer_id, AccessAll); | ||||
|     if (pos < buffer->size){ | ||||
|         buffer_read_range(app, buffer, pos, pos+1, &result); | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static Buffer_Identifier | ||||
| buffer_identifier(char *str, int32_t len){ | ||||
|     Buffer_Identifier identifier; | ||||
|     identifier.name = str; | ||||
|     identifier.name_len = len; | ||||
|     identifier.id = 0; | ||||
|     return(identifier); | ||||
| } | ||||
| 
 | ||||
| static Buffer_Identifier | ||||
| buffer_identifier(Buffer_ID id){ | ||||
|     Buffer_Identifier identifier; | ||||
|     identifier.name = 0; | ||||
|     identifier.name_len = 0; | ||||
|     identifier.id = id; | ||||
|     return(identifier); | ||||
| } | ||||
| 
 | ||||
| static Range | ||||
| make_range(int32_t p1, int32_t p2){ | ||||
|     Range range; | ||||
|     if (p1 < p2){ | ||||
|         range.min = p1; | ||||
|         range.max = p2; | ||||
|     } | ||||
|     else{ | ||||
|         range.min = p2; | ||||
|         range.max = p1; | ||||
|     } | ||||
|     return(range); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| adjust_all_buffer_wrap_widths(Application_Links *app, int32_t wrap_width, int32_t min_base_width){ | ||||
|     for (Buffer_Summary buffer = get_buffer_first(app, AccessAll); | ||||
|          buffer.exists; | ||||
|          get_buffer_next(app, &buffer, AccessAll)){ | ||||
|         buffer_set_setting(app, &buffer, BufferSetting_WrapPosition, wrap_width); | ||||
|         buffer_set_setting(app, &buffer, BufferSetting_MinimumBaseWrapPosition, min_base_width); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static Buffer_Rect | ||||
| get_rect(View_Summary *view){ | ||||
|     Buffer_Rect rect = {0}; | ||||
|      | ||||
|     rect.char0 = view->mark.character; | ||||
|     rect.line0 = view->mark.line; | ||||
|      | ||||
|     rect.char1 = view->cursor.character; | ||||
|     rect.line1 = view->cursor.line; | ||||
|      | ||||
|     if (rect.line0 > rect.line1){ | ||||
|         Swap(int32_t, rect.line0, rect.line1); | ||||
|     } | ||||
|     if (rect.char0 > rect.char1){ | ||||
|         Swap(int32_t, rect.char0, rect.char1); | ||||
|     } | ||||
|      | ||||
|     return(rect); | ||||
| } | ||||
| 
 | ||||
| static i32_Rect | ||||
| get_line_x_rect(View_Summary *view){ | ||||
|     i32_Rect rect = {0}; | ||||
|      | ||||
|     if (view->unwrapped_lines){ | ||||
|         rect.x0 = (int32_t)view->mark.unwrapped_x; | ||||
|         rect.x1 = (int32_t)view->cursor.unwrapped_x; | ||||
|     } | ||||
|     else{ | ||||
|         rect.x0 = (int32_t)view->mark.wrapped_x; | ||||
|         rect.x1 = (int32_t)view->cursor.wrapped_x; | ||||
|     } | ||||
|     rect.y0 = view->mark.line; | ||||
|     rect.y1 = view->cursor.line; | ||||
|      | ||||
|     if (rect.y0 > rect.y1){ | ||||
|         Swap(int32_t, rect.y0, rect.y1); | ||||
|     } | ||||
|     if (rect.x0 > rect.x1){ | ||||
|         Swap(int32_t, rect.x0, rect.x1); | ||||
|     } | ||||
|      | ||||
|     return(rect); | ||||
| } | ||||
| 
 | ||||
| static View_Summary | ||||
| get_first_view_with_buffer(Application_Links *app, int32_t buffer_id){ | ||||
|     View_Summary result = {0}; | ||||
|     View_Summary test = {0}; | ||||
|      | ||||
|     if (buffer_id != 0){ | ||||
|         uint32_t access = AccessAll; | ||||
|         for(test = get_view_first(app, access); | ||||
|             test.exists; | ||||
|             get_view_next(app, &test, access)){ | ||||
|              | ||||
|             Buffer_Summary buffer = get_buffer(app, test.buffer_id, access); | ||||
|              | ||||
|             if(buffer.buffer_id == buffer_id){ | ||||
|                 result = test; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| open_file(Application_Links *app, Buffer_Summary *buffer_out, char *filename, int32_t filename_len, bool32 background, bool32 never_new){ | ||||
|     bool32 result = false; | ||||
|     Buffer_Summary buffer = get_buffer_by_name(app, filename, filename_len, AccessProtected|AccessHidden); | ||||
|      | ||||
|     if (buffer.exists){ | ||||
|         if (buffer_out){ | ||||
|             *buffer_out = buffer; | ||||
|         } | ||||
|         result = true; | ||||
|     } | ||||
|     else{ | ||||
|         Buffer_Create_Flag flags = 0; | ||||
|         if (background){ | ||||
|             flags |= BufferCreate_Background; | ||||
|         } | ||||
|         if (never_new){ | ||||
|             flags |= BufferCreate_NeverNew; | ||||
|         } | ||||
|         buffer = create_buffer(app, filename, filename_len, flags); | ||||
|         if (buffer.exists){ | ||||
|             if (buffer_out){ | ||||
|                 *buffer_out = buffer; | ||||
|             } | ||||
|             result = true; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static Buffer_ID | ||||
| buffer_identifier_to_id(Application_Links *app, Buffer_Identifier identifier){ | ||||
|     Buffer_ID id = 0; | ||||
|     if (identifier.id != 0){ | ||||
|         id = identifier.id; | ||||
|     } | ||||
|     else{ | ||||
|         Buffer_Summary buffer = get_buffer_by_name(app, identifier.name, identifier.name_len, AccessAll); | ||||
|         id = buffer.buffer_id; | ||||
|         if (id == 0){ | ||||
|             buffer = get_buffer_by_file_name(app, identifier.name, identifier.name_len, AccessAll); | ||||
|             id = buffer.buffer_id; | ||||
|         } | ||||
|     } | ||||
|     return(id); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| view_open_file(Application_Links *app, View_Summary *view, char *filename, int32_t filename_len, bool32 never_new){ | ||||
|     bool32 result = false; | ||||
|      | ||||
|     if (view != 0){ | ||||
|         Buffer_Summary buffer = {0}; | ||||
|         if (open_file(app, &buffer, filename, filename_len, false, never_new)){ | ||||
|             view_set_buffer(app, view, buffer.buffer_id, 0); | ||||
|             result = true; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| get_view_prev(Application_Links *app, View_Summary *view, uint32_t access){ | ||||
|     if (view->exists){ | ||||
|         View_ID original_id = view->view_id; | ||||
|         View_ID check_id = original_id; | ||||
|          | ||||
|         View_Summary new_view = {0}; | ||||
|          | ||||
|         for (;;){ | ||||
|             --check_id; | ||||
|             if (check_id <= 0){ | ||||
|                 check_id = 16; | ||||
|             } | ||||
|             if (check_id == original_id){ | ||||
|                 new_view = *view; | ||||
|                 break; | ||||
|             } | ||||
|             new_view = get_view(app, check_id, access); | ||||
|             if (new_view.exists){ | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         *view = new_view; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static View_Summary | ||||
| get_view_last(Application_Links *app, uint32_t access){ | ||||
|     View_Summary view = {0}; | ||||
|     view.exists = true; | ||||
|     get_view_prev(app, &view, access); | ||||
|     if (view.view_id < 1 || view.view_id > 16){ | ||||
|         view = null_view_summary; | ||||
|     } | ||||
|     return(view); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| get_view_next_looped(Application_Links *app, View_Summary *view, uint32_t access){ | ||||
|     get_view_next(app, view, access); | ||||
|     if (!view->exists){ | ||||
|         *view = get_view_first(app, access); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| get_view_prev_looped(Application_Links *app, View_Summary *view, uint32_t access){ | ||||
|     get_view_prev(app, view, access); | ||||
|     if (!view->exists){ | ||||
|         *view = get_view_last(app, access); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| refresh_buffer(Application_Links *app, Buffer_Summary *buffer){ | ||||
|     *buffer = get_buffer(app, buffer->buffer_id, AccessAll); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| refresh_view(Application_Links *app, View_Summary *view){ | ||||
|     *view = get_view(app, view->view_id, AccessAll); | ||||
| } | ||||
| 
 | ||||
| // TODO(allen): Setup buffer seeking to do character_pos and get View_Summary out of this parameter list.
 | ||||
| static int32_t | ||||
| character_pos_to_pos(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, int32_t character_pos){ | ||||
|     int32_t result = 0; | ||||
|     Full_Cursor cursor = {0}; | ||||
|     if (view_compute_cursor(app, view, seek_character_pos(character_pos), &cursor)){ | ||||
|         result = cursor.pos; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static float | ||||
| get_view_y(View_Summary *view){ | ||||
|     float y = view->cursor.wrapped_y; | ||||
|     if (view->unwrapped_lines){ | ||||
|         y = view->cursor.unwrapped_y; | ||||
|     } | ||||
|     return(y); | ||||
| } | ||||
| 
 | ||||
| static float | ||||
| get_view_x(View_Summary *view){ | ||||
|     float x = view->cursor.wrapped_x; | ||||
|     if (view->unwrapped_lines){ | ||||
|         x = view->cursor.unwrapped_x; | ||||
|     } | ||||
|     return(x); | ||||
| } | ||||
| 
 | ||||
| static Range | ||||
| get_view_range(View_Summary *view){ | ||||
|     return(make_range(view->cursor.pos, view->mark.pos)); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| read_line(Application_Links *app, Partition *part, Buffer_Summary *buffer, int32_t line, String *str){ | ||||
|     Partial_Cursor begin = {0}; | ||||
|     Partial_Cursor end = {0}; | ||||
|      | ||||
|     bool32 success = false; | ||||
|     if (buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &begin)){ | ||||
|         if (buffer_compute_cursor(app, buffer, seek_line_char(line, -1), &end)){ | ||||
|             if (begin.line == line){ | ||||
|                 if (0 <= begin.pos && begin.pos <= end.pos && end.pos <= buffer->size){ | ||||
|                     int32_t size = (end.pos - begin.pos); | ||||
|                     int32_t alloc_size = size + 1; | ||||
|                     char *memory = push_array(part, char, alloc_size); | ||||
|                     if (memory != 0){ | ||||
|                         *str = make_string(memory, 0, alloc_size); | ||||
|                         success = true; | ||||
|                         buffer_read_range(app, buffer, begin.pos, end.pos, str->str); | ||||
|                         str->size = size; | ||||
|                         terminate_with_null(str); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(success); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_get_line_start(Application_Links *app, Buffer_Summary *buffer, int32_t line){ | ||||
|     int32_t result = buffer->size; | ||||
|     if (line <= buffer->line_count){ | ||||
|         Partial_Cursor partial_cursor = {0}; | ||||
|         buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &partial_cursor); | ||||
|         result = partial_cursor.pos; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_get_line_end(Application_Links *app, Buffer_Summary *buffer, int32_t line){ | ||||
|     int32_t result = buffer->size; | ||||
|     if (line <= buffer->line_count){ | ||||
|         Partial_Cursor partial_cursor = {0}; | ||||
|         buffer_compute_cursor(app, buffer, seek_line_char(line, -1), &partial_cursor); | ||||
|         result = partial_cursor.pos; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_get_line_number(Application_Links *app, Buffer_Summary *buffer, int32_t pos){ | ||||
|     Partial_Cursor partial_cursor = {0}; | ||||
|     buffer_compute_cursor(app, buffer, seek_pos(pos), &partial_cursor); | ||||
|     return(partial_cursor.line); | ||||
| } | ||||
| 
 | ||||
| static Cpp_Token* | ||||
| get_first_token_at_line(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line, int32_t *line_start_out = 0){ | ||||
|     int32_t line_start = buffer_get_line_start(app, buffer, line); | ||||
|     Cpp_Get_Token_Result get_token = cpp_get_token(tokens, line_start); | ||||
|      | ||||
|     if (get_token.in_whitespace){ | ||||
|         get_token.token_index += 1; | ||||
|     } | ||||
|      | ||||
|     if (line_start_out){ | ||||
|         *line_start_out = line_start; | ||||
|     } | ||||
|      | ||||
|     Cpp_Token *result = 0; | ||||
|     if (get_token.token_index < tokens.count){ | ||||
|         result = &tokens.tokens[get_token.token_index]; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| static bool32 | ||||
| init_stream_chunk(Stream_Chunk *chunk, Application_Links *app, Buffer_Summary *buffer, | ||||
|                   int32_t pos, char *data, uint32_t size){ | ||||
|     bool32 result = false; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (0 <= pos && pos < buffer->size && size > 0){ | ||||
|         chunk->app = app; | ||||
|         chunk->buffer = buffer; | ||||
|         chunk->base_data = data; | ||||
|         chunk->data_size = size; | ||||
|         chunk->start = round_down(pos, size); | ||||
|         chunk->end = round_up(pos, size); | ||||
|          | ||||
|         if (chunk->max_end > buffer->size || chunk->max_end == 0){ | ||||
|             chunk->max_end = buffer->size; | ||||
|         } | ||||
|          | ||||
|         if (chunk->max_end && chunk->max_end < chunk->end){ | ||||
|             chunk->end = chunk->max_end; | ||||
|         } | ||||
|         if (chunk->min_start && chunk->min_start > chunk->start){ | ||||
|             chunk->start = chunk->min_start; | ||||
|         } | ||||
|          | ||||
|         if (chunk->start < chunk->end){ | ||||
|             buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data); | ||||
|             chunk->data = chunk->base_data - chunk->start; | ||||
|             result = true; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| forward_stream_chunk(Stream_Chunk *chunk){ | ||||
|     Application_Links *app = chunk->app; | ||||
|     Buffer_Summary *buffer = chunk->buffer; | ||||
|     bool32 result = 0; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (chunk->end < buffer->size){ | ||||
|         chunk->start = chunk->end; | ||||
|         chunk->end += chunk->data_size; | ||||
|          | ||||
|         if (chunk->max_end && chunk->max_end < chunk->end){ | ||||
|             chunk->end = chunk->max_end; | ||||
|         } | ||||
|         if (chunk->min_start && chunk->min_start > chunk->start){ | ||||
|             chunk->start = chunk->min_start; | ||||
|         } | ||||
|          | ||||
|         if (chunk->start < chunk->end){ | ||||
|             buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data); | ||||
|             chunk->data = chunk->base_data - chunk->start; | ||||
|             result = 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     else if (chunk->add_null && chunk->end + 1 < buffer->size){ | ||||
|         chunk->start = buffer->size; | ||||
|         chunk->end = buffer->size + 1; | ||||
|         chunk->base_data[0] = 0; | ||||
|         chunk->data = chunk->base_data - chunk->start; | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| backward_stream_chunk(Stream_Chunk *chunk){ | ||||
|     Application_Links *app = chunk->app; | ||||
|     Buffer_Summary *buffer = chunk->buffer; | ||||
|     bool32 result = 0; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (chunk->start > 0){ | ||||
|         chunk->end = chunk->start; | ||||
|         chunk->start -= chunk->data_size; | ||||
|          | ||||
|         if (chunk->max_end && chunk->max_end < chunk->end){ | ||||
|             chunk->end = chunk->max_end; | ||||
|         } | ||||
|         if (chunk->min_start && chunk->min_start > chunk->start){ | ||||
|             chunk->start = chunk->min_start; | ||||
|         } | ||||
|          | ||||
|         if (chunk->start < chunk->end){ | ||||
|             buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data); | ||||
|             chunk->data = chunk->base_data - chunk->start; | ||||
|             result = 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     else if (chunk->add_null && chunk->start > -1){ | ||||
|         chunk->start = -1; | ||||
|         chunk->end = 0; | ||||
|         chunk->base_data[0] = 0; | ||||
|         chunk->data = chunk->base_data - chunk->start; | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| static bool32 | ||||
| init_stream_tokens(Stream_Tokens *stream, Application_Links *app, Buffer_Summary *buffer, | ||||
|                    int32_t pos, Cpp_Token *data, int32_t count){ | ||||
|     bool32 result = false; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|      | ||||
|     int32_t token_count = buffer_token_count(app, buffer); | ||||
|     if (buffer->tokens_are_ready && pos >= 0 && pos < token_count && count > 0){ | ||||
|         stream->app = app; | ||||
|         stream->buffer = buffer; | ||||
|         stream->base_tokens = data; | ||||
|         stream->count = count; | ||||
|         stream->start = round_down(pos, count); | ||||
|         stream->end = round_up(pos, count); | ||||
|         stream->token_count = token_count; | ||||
|          | ||||
|         if (stream->start < 0){ | ||||
|             stream->start = 0; | ||||
|         } | ||||
|         if (stream->end > stream->token_count){ | ||||
|             stream->end = stream->token_count; | ||||
|         } | ||||
|          | ||||
|         buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens); | ||||
|         stream->tokens = stream->base_tokens - stream->start; | ||||
|         result = true; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static Stream_Tokens | ||||
| begin_temp_stream_token(Stream_Tokens *stream){ | ||||
|     return(*stream); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| end_temp_stream_token(Stream_Tokens *stream, Stream_Tokens temp){ | ||||
|     if (stream->start != temp.start || stream->end != temp.end){ | ||||
|         Application_Links *app = stream->app; | ||||
|         buffer_read_tokens(app, temp.buffer, temp.start, temp.end, temp.base_tokens); | ||||
|         stream->tokens = stream->base_tokens - temp.start; | ||||
|         stream->start = temp.start; | ||||
|         stream->end = temp.end; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| forward_stream_tokens(Stream_Tokens *stream){ | ||||
|     Application_Links *app = stream->app; | ||||
|     Buffer_Summary *buffer = stream->buffer; | ||||
|     bool32 result = false; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (stream->end < stream->token_count){ | ||||
|         stream->start = stream->end; | ||||
|         stream->end += stream->count; | ||||
|          | ||||
|         if (stream->end > stream->token_count){ | ||||
|             stream->end = stream->token_count; | ||||
|         } | ||||
|          | ||||
|         if (stream->start < stream->end){ | ||||
|             buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens); | ||||
|             stream->tokens = stream->base_tokens - stream->start; | ||||
|             result = true; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| backward_stream_tokens(Stream_Tokens *stream){ | ||||
|     Application_Links *app = stream->app; | ||||
|     Buffer_Summary *buffer = stream->buffer; | ||||
|     bool32 result = false; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (stream->start > 0){ | ||||
|         stream->end = stream->start; | ||||
|         stream->start -= stream->count; | ||||
|          | ||||
|         if (0 > stream->start){ | ||||
|             stream->start = 0; | ||||
|         } | ||||
|          | ||||
|         if (stream->start < stream->end){ | ||||
|             buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens); | ||||
|             stream->tokens = stream->base_tokens - stream->start; | ||||
|             result = true; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  | @ -0,0 +1,100 @@ | |||
| /*
 | ||||
|  * Miscellaneous helpers for common operations. | ||||
|  */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| #if !defined(FCODER_HELPER_H) | ||||
| #define FCODER_HELPER_H | ||||
| 
 | ||||
| struct Bind_Helper{ | ||||
|     Binding_Unit *cursor, *start, *end; | ||||
|     Binding_Unit *header, *group; | ||||
|     int32_t write_total; | ||||
|     int32_t error; | ||||
| }; | ||||
| 
 | ||||
| #define BH_ERR_NONE 0 | ||||
| #define BH_ERR_MISSING_END 1 | ||||
| #define BH_ERR_MISSING_BEGIN 2 | ||||
| #define BH_ERR_OUT_OF_MEMORY 3 | ||||
| 
 | ||||
| struct Bind_Buffer{ | ||||
|     void *data; | ||||
|     int32_t size; | ||||
| }; | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| #define dll_remove(n)        (n)->next->prev=(n)->prev,(n)->prev->next=(n)->next | ||||
| 
 | ||||
| #define zdll_push_back_(f,l,n) if(f==0){n->next=n->prev=0;f=l=n;}else{n->prev=l;n->next=0;l->next=n;l=n;} | ||||
| #define zdll_push_back(f,l,n) do{ zdll_push_back_((f),(l),(n)) }while(0) | ||||
| #define zdll_remove_front_(f,l,n) if(f==l){f=l=0;}else{f=f->next;f->prev=0;} | ||||
| #define zdll_remove_back_(f,l,n) if(f==l){f=l=0;}else{l=l->prev;l->next=0;} | ||||
| #define zdll_remove_(f,l,n) if(f==n){zdll_remove_front_(f,l,n);}else if(l==n){zdll_remove_back_(f,l,n);}else{dll_remove(n);} | ||||
| #define zdll_remove(f,l,n) do{ zdll_remove_((f),(l),(n)) }while(0) | ||||
| 
 | ||||
| #if !defined(Member) | ||||
| # define Member(S,m) (((S*)0)->m) | ||||
| #endif | ||||
| #define PtrDif(a,b) ((uint8_t*)(a) - (uint8_t*)(b)) | ||||
| #define PtrAsInt(a) PtrDif(a,0) | ||||
| #define OffsetOfMember(S,m) PtrAsInt(&Member(S,m)) | ||||
| #define CastFromMember(S,m,ptr) (S*)( (uint8_t*)(ptr) - OffsetOfMember(S,m) ) | ||||
| 
 | ||||
| #if !defined(max_f32) | ||||
| inline float | ||||
| max_f32_proc(void){ | ||||
|     union{ | ||||
|         uint32_t x; | ||||
|         float f; | ||||
|     } c; | ||||
|     c.x = 0x7f800000; | ||||
|     return(c.f); | ||||
| } | ||||
| 
 | ||||
| #define max_f32 max_f32_proc() | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(ArrayCount) | ||||
| # define ArrayCount(a) (sizeof(a)/sizeof(a[0])) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef Swap | ||||
| # define Swap(T,a,b) do{ T t = a; a = b; b = t; } while(0) | ||||
| #endif | ||||
| 
 | ||||
| struct Buffer_Rect{ | ||||
|     int32_t char0, line0; | ||||
|     int32_t char1, line1; | ||||
| }; | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| struct Stream_Chunk{ | ||||
|     Application_Links *app; | ||||
|     Buffer_Summary *buffer; | ||||
|      | ||||
|     char *base_data; | ||||
|     int32_t start, end; | ||||
|     int32_t min_start, max_end; | ||||
|     bool32 add_null; | ||||
|     uint32_t data_size; | ||||
|      | ||||
|     char *data; | ||||
| }; | ||||
| 
 | ||||
| struct Stream_Tokens{ | ||||
|     Application_Links *app; | ||||
|     Buffer_Summary *buffer; | ||||
|      | ||||
|     Cpp_Token *base_tokens; | ||||
|     Cpp_Token *tokens; | ||||
|     int32_t start, end; | ||||
|     int32_t count, token_count; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // BOTTOM
 | ||||
|  | @ -1,254 +0,0 @@ | |||
| /*
 | ||||
| * Helpers for setting bindings. | ||||
| */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| inline Binding_Unit* | ||||
| write_unit(Bind_Helper *helper, Binding_Unit unit){ | ||||
|     Binding_Unit *p = 0; | ||||
|     helper->write_total += sizeof(*p); | ||||
|     if (helper->error == 0 && helper->cursor != helper->end){ | ||||
|         p = helper->cursor++; | ||||
|         *p = unit; | ||||
|     } | ||||
|     return p; | ||||
| } | ||||
| 
 | ||||
| inline Bind_Helper | ||||
| begin_bind_helper(void *data, int32_t size){ | ||||
|     Bind_Helper result; | ||||
|      | ||||
|     result.header = 0; | ||||
|     result.group = 0; | ||||
|     result.write_total = 0; | ||||
|     result.error = 0; | ||||
|      | ||||
|     result.cursor = (Binding_Unit*)data; | ||||
|     result.start = result.cursor; | ||||
|     result.end = result.start + size / sizeof(*result.cursor); | ||||
|      | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_header; | ||||
|     unit.header.total_size = sizeof(*result.header); | ||||
|     result.header = write_unit(&result, unit); | ||||
|     result.header->header.user_map_count = 0; | ||||
|      | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| begin_map_(Bind_Helper *helper, int32_t mapid, int32_t replace){ | ||||
|     if (helper->group != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END; | ||||
|     if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count; | ||||
|      | ||||
|     Binding_Unit unit; | ||||
|     unit.type = unit_map_begin; | ||||
|     unit.map_begin.mapid = mapid; | ||||
|     unit.map_begin.replace = replace; | ||||
|     helper->group = write_unit(helper, unit); | ||||
|     helper->group->map_begin.bind_count = 0; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| begin_map(Bind_Helper *helper, int32_t mapid){ | ||||
|     begin_map_(helper, mapid, 0); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| restart_map(Bind_Helper *helper, int32_t mapid){ | ||||
|     begin_map_(helper, mapid, 1); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| end_map(Bind_Helper *helper){ | ||||
|     if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; | ||||
|     helper->group = 0; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind(Bind_Helper *helper, Key_Code code, uint8_t modifiers, Command_ID cmdid){ | ||||
|     if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; | ||||
|     if (!helper->error) ++helper->group->map_begin.bind_count; | ||||
|      | ||||
|     Binding_Unit unit; | ||||
|     unit.type = unit_binding; | ||||
|     unit.binding.command_id = cmdid; | ||||
|     unit.binding.code = code; | ||||
|     unit.binding.modifiers = modifiers; | ||||
|      | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind(Bind_Helper *helper, Key_Code code, uint8_t modifiers, Custom_Command_Function *func){ | ||||
|     if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; | ||||
|     if (!helper->error) ++helper->group->map_begin.bind_count; | ||||
|      | ||||
|     Binding_Unit unit; | ||||
|     unit.type = unit_callback; | ||||
|     unit.callback.func = func; | ||||
|     unit.callback.code = code; | ||||
|     unit.callback.modifiers = modifiers; | ||||
|      | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind(Bind_Helper *helper, Key_Code code, uint8_t modifiers, Generic_Command cmd){ | ||||
|     if (cmd.cmdid < cmdid_count){ | ||||
|         bind(helper, code, modifiers, cmd.cmdid); | ||||
|     } | ||||
|     else{ | ||||
|         bind(helper, code, modifiers, cmd.command); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind_vanilla_keys(Bind_Helper *helper, int32_t cmdid){ | ||||
|     bind(helper, 0, 0, cmdid); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind_vanilla_keys(Bind_Helper *helper, Custom_Command_Function *func){ | ||||
|     bind(helper, 0, 0, func); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, int32_t cmdid){ | ||||
|     bind(helper, 0, modifiers, cmdid); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, Custom_Command_Function *func){ | ||||
|     bind(helper, 0, modifiers, func); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| inherit_map(Bind_Helper *helper, int32_t mapid){ | ||||
|     if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN; | ||||
|     if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count; | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_inherit; | ||||
|     unit.map_inherit.mapid = mapid; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_hook(Bind_Helper *helper, int32_t hook_id, Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = hook_id; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_scroll_rule(Bind_Helper *helper, Scroll_Rule_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_scroll_rule; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_buffer_name_resolver(Bind_Helper *helper, Buffer_Name_Resolver_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_buffer_name_resolver; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_new_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_new_file; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_start_hook(Bind_Helper *helper, Start_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_start; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_open_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_open_file; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_save_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_save_file; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_end_file_hook(Bind_Helper *helper, Open_File_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_end_file; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_command_caller(Bind_Helper *helper, Command_Caller_Hook_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_command_caller; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| set_input_filter(Bind_Helper *helper, Input_Filter_Function *func){ | ||||
|     Binding_Unit unit = {0}; | ||||
|     unit.type = unit_hook; | ||||
|     unit.hook.hook_id = special_hook_input_filter; | ||||
|     unit.hook.func = (void*)func; | ||||
|     write_unit(helper, unit); | ||||
| } | ||||
| 
 | ||||
| inline int32_t | ||||
| end_bind_helper(Bind_Helper *helper){ | ||||
|     if (helper->header){ | ||||
|         helper->header->header.total_size = (int32_t)(helper->cursor - helper->start); | ||||
|         helper->header->header.error = helper->error; | ||||
|     } | ||||
|     int32_t result = helper->write_total; | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| inline Bind_Buffer | ||||
| end_bind_helper_get_buffer(Bind_Helper *helper){ | ||||
|     int32_t size = end_bind_helper(helper); | ||||
|     Bind_Buffer result = {0}; | ||||
|     result.data = helper->start; | ||||
|     result.size = size; | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static u32_4tech | ||||
| get_key_code(char *buffer){ | ||||
|     u32_4tech ignore; | ||||
|     u32_4tech result = utf8_to_u32_length_unchecked((u8_4tech*)buffer, &ignore); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  | @ -1,30 +0,0 @@ | |||
| /*
 | ||||
| * Helpers for setting bindings. | ||||
| */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| #if !defined(FCODER_BIND_HELPER_H) | ||||
| #define FCODER_BIND_HELPER_H | ||||
| 
 | ||||
| struct Bind_Helper{ | ||||
|     Binding_Unit *cursor, *start, *end; | ||||
|     Binding_Unit *header, *group; | ||||
|     int32_t write_total; | ||||
|     int32_t error; | ||||
| }; | ||||
| 
 | ||||
| #define BH_ERR_NONE 0 | ||||
| #define BH_ERR_MISSING_END 1 | ||||
| #define BH_ERR_MISSING_BEGIN 2 | ||||
| #define BH_ERR_OUT_OF_MEMORY 3 | ||||
| 
 | ||||
| struct Bind_Buffer{ | ||||
|     void *data; | ||||
|     int32_t size; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  | @ -1,238 +0,0 @@ | |||
| /*
 | ||||
|  * Miscellaneous helpers for common operations. | ||||
|  */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| static void | ||||
| exec_command(Application_Links *app, Custom_Command_Function *func){ | ||||
|     func(app); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| exec_command(Application_Links *app, Generic_Command cmd){ | ||||
|     if (cmd.cmdid < cmdid_count){ | ||||
|         exec_command(app, cmd.cmdid); | ||||
|     } | ||||
|     else{ | ||||
|         exec_command(app, cmd.command); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| key_is_unmodified(Key_Event_Data *key){ | ||||
|     int8_t *mods = key->modifiers; | ||||
|     int32_t unmodified = (!mods[MDFR_CONTROL_INDEX] && !mods[MDFR_ALT_INDEX]); | ||||
|     return(unmodified); | ||||
| } | ||||
| 
 | ||||
| static uint32_t | ||||
| to_writable_character(User_Input in, uint8_t *character){ | ||||
|     uint32_t result = 0; | ||||
|     if (in.type == UserInputKey){ | ||||
|         if (in.key.character != 0){ | ||||
|             u32_to_utf8_unchecked(in.key.character, character, &result); | ||||
|         } | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static uint32_t | ||||
| to_writable_character(Key_Event_Data key, uint8_t *character){ | ||||
|     uint32_t result = 0; | ||||
|     if (key.character != 0){ | ||||
|         u32_to_utf8_unchecked(key.character, character, &result); | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| backspace_utf8(String *str){ | ||||
|     bool32 result = false; | ||||
|     uint8_t *s = (uint8_t*)str->str; | ||||
|     if (str->size > 0){ | ||||
|         uint32_t i = str->size-1; | ||||
|         for (; i > 0; --i){ | ||||
|             if (s[i] <= 0x7F || s[i] >= 0xC0){ | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         str->size = i; | ||||
|         result = true; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| query_user_general(Application_Links *app, Query_Bar *bar, bool32 force_number){ | ||||
|     bool32 success = true; | ||||
|      | ||||
|     // NOTE(allen|a3.4.4): It will not cause an *error* if we continue on after failing to.
 | ||||
|     // start a query bar, but it will be unusual behavior from the point of view of the
 | ||||
|     // user, if this command starts intercepting input even though no prompt is shown.
 | ||||
|     // This will only happen if you have a lot of bars open already or if the current view
 | ||||
|     // doesn't support query bars.
 | ||||
|     if (start_query_bar(app, bar, 0) == 0) return 0; | ||||
|      | ||||
|     for (;;){ | ||||
|         // NOTE(allen|a3.4.4): This call will block until the user does one of the input
 | ||||
|         // types specified in the flags.  The first set of flags are inputs you'd like to intercept
 | ||||
|         // that you don't want to abort on.  The second set are inputs that you'd like to cause
 | ||||
|         // the command to abort.  If an event satisfies both flags, it is treated as an abort.
 | ||||
|         User_Input in = get_user_input(app, EventOnAnyKey, EventOnEsc | EventOnButton); | ||||
|          | ||||
|         // NOTE(allen|a3.4.4): The responsible thing to do on abort is to end the command
 | ||||
|         // without waiting on get_user_input again.
 | ||||
|         if (in.abort){ | ||||
|             success = false; | ||||
|             break; | ||||
|         } | ||||
|          | ||||
|         uint8_t character[4]; | ||||
|         uint32_t length = 0; | ||||
|         bool32 good_character = false; | ||||
|         if (key_is_unmodified(&in.key)){ | ||||
|             if (force_number){ | ||||
|                 if (in.key.character >= '0' && in.key.character <= '9'){ | ||||
|                     good_character = true; | ||||
|                     length = to_writable_character(in, character); | ||||
|                 } | ||||
|             } | ||||
|             else{ | ||||
|                 length = to_writable_character(in, character); | ||||
|                 if (length != 0){ | ||||
|                     good_character = true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         // NOTE(allen|a3.4.4): All we have to do to update the query bar is edit our
 | ||||
|         // local Query_Bar struct!  This is handy because it means our Query_Bar
 | ||||
|         // is always correct for typical use without extra work updating the bar.
 | ||||
|         if (in.type == UserInputKey){ | ||||
|             if (in.key.keycode == '\n' || in.key.keycode == '\t'){ | ||||
|                 break; | ||||
|             } | ||||
|             else if (in.key.keycode == key_back){ | ||||
|                 backspace_utf8(&bar->string); | ||||
|             } | ||||
|             else if (good_character){ | ||||
|                 append_ss(&bar->string, make_string(character, length)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     terminate_with_null(&bar->string); | ||||
|      | ||||
|     return(success); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| query_user_string(Application_Links *app, Query_Bar *bar){ | ||||
|     int32_t success = query_user_general(app, bar, false); | ||||
|     return(success); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| query_user_number(Application_Links *app, Query_Bar *bar){ | ||||
|     int32_t success = query_user_general(app, bar, true); | ||||
|     return(success); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| init_theme_zero(Theme *theme){ | ||||
|     for (int32_t i = 0; i < Stag_COUNT; ++i){ | ||||
|         theme->colors[i] = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static char | ||||
| buffer_get_char(Application_Links *app, Buffer_Summary *buffer, int32_t pos){ | ||||
|     char result = ' '; | ||||
|     *buffer = get_buffer(app, buffer->buffer_id, AccessAll); | ||||
|     if (pos < buffer->size){ | ||||
|         buffer_read_range(app, buffer, pos, pos+1, &result); | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static Buffer_Identifier | ||||
| buffer_identifier(char *str, int32_t len){ | ||||
|     Buffer_Identifier identifier; | ||||
|     identifier.name = str; | ||||
|     identifier.name_len = len; | ||||
|     identifier.id = 0; | ||||
|     return(identifier); | ||||
| } | ||||
| 
 | ||||
| static Buffer_Identifier | ||||
| buffer_identifier(Buffer_ID id){ | ||||
|     Buffer_Identifier identifier; | ||||
|     identifier.name = 0; | ||||
|     identifier.name_len = 0; | ||||
|     identifier.id = id; | ||||
|     return(identifier); | ||||
| } | ||||
| 
 | ||||
| static Range | ||||
| make_range(int32_t p1, int32_t p2){ | ||||
|     Range range; | ||||
|     if (p1 < p2){ | ||||
|         range.min = p1; | ||||
|         range.max = p2; | ||||
|     } | ||||
|     else{ | ||||
|         range.min = p2; | ||||
|         range.max = p1; | ||||
|     } | ||||
|     return(range); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| adjust_all_buffer_wrap_widths(Application_Links *app, int32_t wrap_width, int32_t min_base_width){ | ||||
|     for (Buffer_Summary buffer = get_buffer_first(app, AccessAll); | ||||
|          buffer.exists; | ||||
|          get_buffer_next(app, &buffer, AccessAll)){ | ||||
|         buffer_set_setting(app, &buffer, BufferSetting_WrapPosition, wrap_width); | ||||
|         buffer_set_setting(app, &buffer, BufferSetting_MinimumBaseWrapPosition, min_base_width); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // TODO(allen): Setup buffer seeking to do character_pos and get View_Summary out of this parameter list.
 | ||||
| static int32_t | ||||
| character_pos_to_pos(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, int32_t character_pos){ | ||||
|     int32_t result = 0; | ||||
|     Full_Cursor cursor = {0}; | ||||
|     if (view_compute_cursor(app, view, seek_character_pos(character_pos), &cursor)){ | ||||
|         result = cursor.pos; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static float | ||||
| get_view_y(View_Summary *view){ | ||||
|     float y = view->cursor.wrapped_y; | ||||
|     if (view->unwrapped_lines){ | ||||
|         y = view->cursor.unwrapped_y; | ||||
|     } | ||||
|     return(y); | ||||
| } | ||||
| 
 | ||||
| static float | ||||
| get_view_x(View_Summary *view){ | ||||
|     float x = view->cursor.wrapped_x; | ||||
|     if (view->unwrapped_lines){ | ||||
|         x = view->cursor.unwrapped_x; | ||||
|     } | ||||
|     return(x); | ||||
| } | ||||
| 
 | ||||
| static Range | ||||
| get_view_range(View_Summary *view){ | ||||
|     return(make_range(view->cursor.pos, view->mark.pos)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  | @ -1,254 +0,0 @@ | |||
| /*
 | ||||
|  * Miscellaneous helpers for common operations. | ||||
|  */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| #if !defined(FCODER_HELPER_H) | ||||
| #define FCODER_HELPER_H | ||||
| 
 | ||||
| #define dll_remove(n)        (n)->next->prev=(n)->prev,(n)->prev->next=(n)->next | ||||
| 
 | ||||
| #define zdll_push_back_(f,l,n) if(f==0){n->next=n->prev=0;f=l=n;}else{n->prev=l;n->next=0;l->next=n;l=n;} | ||||
| #define zdll_push_back(f,l,n) do{ zdll_push_back_((f),(l),(n)) }while(0) | ||||
| #define zdll_remove_front_(f,l,n) if(f==l){f=l=0;}else{f=f->next;f->prev=0;} | ||||
| #define zdll_remove_back_(f,l,n) if(f==l){f=l=0;}else{l=l->prev;l->next=0;} | ||||
| #define zdll_remove_(f,l,n) if(f==n){zdll_remove_front_(f,l,n);}else if(l==n){zdll_remove_back_(f,l,n);}else{dll_remove(n);} | ||||
| #define zdll_remove(f,l,n) do{ zdll_remove_((f),(l),(n)) }while(0) | ||||
| 
 | ||||
| #if !defined(Member) | ||||
| # define Member(S,m) (((S*)0)->m) | ||||
| #endif | ||||
| #define PtrDif(a,b) ((uint8_t*)(a) - (uint8_t*)(b)) | ||||
| #define PtrAsInt(a) PtrDif(a,0) | ||||
| #define OffsetOfMember(S,m) PtrAsInt(&Member(S,m)) | ||||
| #define CastFromMember(S,m,ptr) (S*)( (uint8_t*)(ptr) - OffsetOfMember(S,m) ) | ||||
| 
 | ||||
| #if !defined(max_f32) | ||||
| inline float | ||||
| max_f32_proc(void){ | ||||
|     union{ | ||||
|         uint32_t x; | ||||
|         float f; | ||||
|     } c; | ||||
|     c.x = 0x7f800000; | ||||
|     return(c.f); | ||||
| } | ||||
| 
 | ||||
| #define max_f32 max_f32_proc() | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(ArrayCount) | ||||
| # define ArrayCount(a) (sizeof(a)/sizeof(a[0])) | ||||
| #endif | ||||
| 
 | ||||
| #include "4coder_seek_types.h" | ||||
| #include "4coder_lib/4coder_utf8.h" | ||||
| 
 | ||||
| struct Buffer_Rect{ | ||||
|     int32_t char0, line0; | ||||
|     int32_t char1, line1; | ||||
| }; | ||||
| 
 | ||||
| #ifndef Swap | ||||
| # define Swap(T,a,b) do{ T t = a; a = b; b = t; } while(0) | ||||
| #endif | ||||
| 
 | ||||
| static Buffer_Rect | ||||
| get_rect(View_Summary *view){ | ||||
|     Buffer_Rect rect = {0}; | ||||
|      | ||||
|     rect.char0 = view->mark.character; | ||||
|     rect.line0 = view->mark.line; | ||||
|      | ||||
|     rect.char1 = view->cursor.character; | ||||
|     rect.line1 = view->cursor.line; | ||||
|      | ||||
|     if (rect.line0 > rect.line1){ | ||||
|         Swap(int32_t, rect.line0, rect.line1); | ||||
|     } | ||||
|     if (rect.char0 > rect.char1){ | ||||
|         Swap(int32_t, rect.char0, rect.char1); | ||||
|     } | ||||
|      | ||||
|     return(rect); | ||||
| } | ||||
| 
 | ||||
| static i32_Rect | ||||
| get_line_x_rect(View_Summary *view){ | ||||
|     i32_Rect rect = {0}; | ||||
|      | ||||
|     if (view->unwrapped_lines){ | ||||
|         rect.x0 = (int32_t)view->mark.unwrapped_x; | ||||
|         rect.x1 = (int32_t)view->cursor.unwrapped_x; | ||||
|     } | ||||
|     else{ | ||||
|         rect.x0 = (int32_t)view->mark.wrapped_x; | ||||
|         rect.x1 = (int32_t)view->cursor.wrapped_x; | ||||
|     } | ||||
|     rect.y0 = view->mark.line; | ||||
|     rect.y1 = view->cursor.line; | ||||
|      | ||||
|     if (rect.y0 > rect.y1){ | ||||
|         Swap(int32_t, rect.y0, rect.y1); | ||||
|     } | ||||
|     if (rect.x0 > rect.x1){ | ||||
|         Swap(int32_t, rect.x0, rect.x1); | ||||
|     } | ||||
|      | ||||
|     return(rect); | ||||
| } | ||||
| 
 | ||||
| static View_Summary | ||||
| get_first_view_with_buffer(Application_Links *app, int32_t buffer_id){ | ||||
|     View_Summary result = {0}; | ||||
|     View_Summary test = {0}; | ||||
|      | ||||
|     if (buffer_id != 0){ | ||||
|         uint32_t access = AccessAll; | ||||
|         for(test = get_view_first(app, access); | ||||
|             test.exists; | ||||
|             get_view_next(app, &test, access)){ | ||||
|              | ||||
|             Buffer_Summary buffer = get_buffer(app, test.buffer_id, access); | ||||
|              | ||||
|             if(buffer.buffer_id == buffer_id){ | ||||
|                 result = test; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| open_file(Application_Links *app, Buffer_Summary *buffer_out, char *filename, int32_t filename_len, bool32 background, bool32 never_new){ | ||||
|     bool32 result = false; | ||||
|     Buffer_Summary buffer = get_buffer_by_name(app, filename, filename_len, AccessProtected|AccessHidden); | ||||
|      | ||||
|     if (buffer.exists){ | ||||
|         if (buffer_out){ | ||||
|             *buffer_out = buffer; | ||||
|         } | ||||
|         result = true; | ||||
|     } | ||||
|     else{ | ||||
|         Buffer_Create_Flag flags = 0; | ||||
|         if (background){ | ||||
|             flags |= BufferCreate_Background; | ||||
|         } | ||||
|         if (never_new){ | ||||
|             flags |= BufferCreate_NeverNew; | ||||
|         } | ||||
|         buffer = create_buffer(app, filename, filename_len, flags); | ||||
|         if (buffer.exists){ | ||||
|             if (buffer_out){ | ||||
|                 *buffer_out = buffer; | ||||
|             } | ||||
|             result = true; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static Buffer_ID | ||||
| buffer_identifier_to_id(Application_Links *app, Buffer_Identifier identifier){ | ||||
|     Buffer_ID id = 0; | ||||
|     if (identifier.id != 0){ | ||||
|         id = identifier.id; | ||||
|     } | ||||
|     else{ | ||||
|         Buffer_Summary buffer = get_buffer_by_name(app, identifier.name, identifier.name_len, AccessAll); | ||||
|         id = buffer.buffer_id; | ||||
|         if (id == 0){ | ||||
|             buffer = get_buffer_by_file_name(app, identifier.name, identifier.name_len, AccessAll); | ||||
|             id = buffer.buffer_id; | ||||
|         } | ||||
|     } | ||||
|     return(id); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| view_open_file(Application_Links *app, View_Summary *view, char *filename, int32_t filename_len, bool32 never_new){ | ||||
|     bool32 result = false; | ||||
|      | ||||
|     if (view != 0){ | ||||
|         Buffer_Summary buffer = {0}; | ||||
|         if (open_file(app, &buffer, filename, filename_len, false, never_new)){ | ||||
|             view_set_buffer(app, view, buffer.buffer_id, 0); | ||||
|             result = true; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| get_view_prev(Application_Links *app, View_Summary *view, uint32_t access){ | ||||
|     if (view->exists){ | ||||
|         View_ID original_id = view->view_id; | ||||
|         View_ID check_id = original_id; | ||||
|          | ||||
|         View_Summary new_view = {0}; | ||||
|          | ||||
|         for (;;){ | ||||
|             --check_id; | ||||
|             if (check_id <= 0){ | ||||
|                 check_id = 16; | ||||
|             } | ||||
|             if (check_id == original_id){ | ||||
|                 new_view = *view; | ||||
|                 break; | ||||
|             } | ||||
|             new_view = get_view(app, check_id, access); | ||||
|             if (new_view.exists){ | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         *view = new_view; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static View_Summary | ||||
| get_view_last(Application_Links *app, uint32_t access){ | ||||
|     View_Summary view = {0}; | ||||
|     view.exists = true; | ||||
|     get_view_prev(app, &view, access); | ||||
|     if (view.view_id < 1 || view.view_id > 16){ | ||||
|         view = null_view_summary; | ||||
|     } | ||||
|     return(view); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| get_view_next_looped(Application_Links *app, View_Summary *view, uint32_t access){ | ||||
|     get_view_next(app, view, access); | ||||
|     if (!view->exists){ | ||||
|         *view = get_view_first(app, access); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| get_view_prev_looped(Application_Links *app, View_Summary *view, uint32_t access){ | ||||
|     get_view_prev(app, view, access); | ||||
|     if (!view->exists){ | ||||
|         *view = get_view_last(app, access); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| refresh_buffer(Application_Links *app, Buffer_Summary *buffer){ | ||||
|     *buffer = get_buffer(app, buffer->buffer_id, AccessAll); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| refresh_view(Application_Links *app, View_Summary *view){ | ||||
|     *view = get_view(app, view->view_id, AccessAll); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // BOTTOM
 | ||||
|  | @ -1,259 +0,0 @@ | |||
| /*
 | ||||
|  * Helpers for streaming over buffer data to avoid having to read it all at once. | ||||
|  */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| #if !defined(FCODER_STREAMING_H) | ||||
| #define FCODER_STREAMING_H | ||||
| 
 | ||||
| #include "4coder_helper/4coder_helper.h" | ||||
| 
 | ||||
| struct Stream_Chunk{ | ||||
|     Application_Links *app; | ||||
|     Buffer_Summary *buffer; | ||||
|      | ||||
|     char *base_data; | ||||
|     int32_t start, end; | ||||
|     int32_t min_start, max_end; | ||||
|     bool32 add_null; | ||||
|     uint32_t data_size; | ||||
|      | ||||
|     char *data; | ||||
| }; | ||||
| 
 | ||||
| static int32_t | ||||
| round_down(int32_t x, int32_t b){ | ||||
|     int32_t r = 0; | ||||
|     if (x >= 0){ | ||||
|         r = x - (x % b); | ||||
|     } | ||||
|     return(r); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| round_up(int32_t x, int32_t b){ | ||||
|     int32_t r = 0; | ||||
|     if (x >= 0){ | ||||
|         r = x - (x % b) + b; | ||||
|     } | ||||
|     return(r); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| init_stream_chunk(Stream_Chunk *chunk, Application_Links *app, Buffer_Summary *buffer, | ||||
|                   int32_t pos, char *data, uint32_t size){ | ||||
|     bool32 result = 0; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (pos >= 0 && pos < buffer->size && size > 0){ | ||||
|         chunk->app = app; | ||||
|         chunk->buffer = buffer; | ||||
|         chunk->base_data = data; | ||||
|         chunk->data_size = size; | ||||
|         chunk->start = round_down(pos, size); | ||||
|         chunk->end = round_up(pos, size); | ||||
|          | ||||
|         if (chunk->max_end > buffer->size || chunk->max_end == 0){ | ||||
|             chunk->max_end = buffer->size; | ||||
|         } | ||||
|          | ||||
|         if (chunk->max_end && chunk->max_end < chunk->end){ | ||||
|             chunk->end = chunk->max_end; | ||||
|         } | ||||
|         if (chunk->min_start && chunk->min_start > chunk->start){ | ||||
|             chunk->start = chunk->min_start; | ||||
|         } | ||||
|          | ||||
|         if (chunk->start < chunk->end){ | ||||
|             buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data); | ||||
|             chunk->data = chunk->base_data - chunk->start; | ||||
|             result = 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| forward_stream_chunk(Stream_Chunk *chunk){ | ||||
|     Application_Links *app = chunk->app; | ||||
|     Buffer_Summary *buffer = chunk->buffer; | ||||
|     bool32 result = 0; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (chunk->end < buffer->size){ | ||||
|         chunk->start = chunk->end; | ||||
|         chunk->end += chunk->data_size; | ||||
|          | ||||
|         if (chunk->max_end && chunk->max_end < chunk->end){ | ||||
|             chunk->end = chunk->max_end; | ||||
|         } | ||||
|         if (chunk->min_start && chunk->min_start > chunk->start){ | ||||
|             chunk->start = chunk->min_start; | ||||
|         } | ||||
|          | ||||
|         if (chunk->start < chunk->end){ | ||||
|             buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data); | ||||
|             chunk->data = chunk->base_data - chunk->start; | ||||
|             result = 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     else if (chunk->add_null && chunk->end + 1 < buffer->size){ | ||||
|         chunk->start = buffer->size; | ||||
|         chunk->end = buffer->size + 1; | ||||
|         chunk->base_data[0] = 0; | ||||
|         chunk->data = chunk->base_data - chunk->start; | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| backward_stream_chunk(Stream_Chunk *chunk){ | ||||
|     Application_Links *app = chunk->app; | ||||
|     Buffer_Summary *buffer = chunk->buffer; | ||||
|     bool32 result = 0; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (chunk->start > 0){ | ||||
|         chunk->end = chunk->start; | ||||
|         chunk->start -= chunk->data_size; | ||||
|          | ||||
|         if (chunk->max_end && chunk->max_end < chunk->end){ | ||||
|             chunk->end = chunk->max_end; | ||||
|         } | ||||
|         if (chunk->min_start && chunk->min_start > chunk->start){ | ||||
|             chunk->start = chunk->min_start; | ||||
|         } | ||||
|          | ||||
|         if (chunk->start < chunk->end){ | ||||
|             buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data); | ||||
|             chunk->data = chunk->base_data - chunk->start; | ||||
|             result = 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     else if (chunk->add_null && chunk->start > -1){ | ||||
|         chunk->start = -1; | ||||
|         chunk->end = 0; | ||||
|         chunk->base_data[0] = 0; | ||||
|         chunk->data = chunk->base_data - chunk->start; | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| struct Stream_Tokens{ | ||||
|     Application_Links *app; | ||||
|     Buffer_Summary *buffer; | ||||
|      | ||||
|     Cpp_Token *base_tokens; | ||||
|     Cpp_Token *tokens; | ||||
|     int32_t start, end; | ||||
|     int32_t count, token_count; | ||||
| }; | ||||
| 
 | ||||
| static bool32 | ||||
| init_stream_tokens(Stream_Tokens *stream, Application_Links *app, Buffer_Summary *buffer, int32_t pos, Cpp_Token *data, int32_t count){ | ||||
|     bool32 result = 0; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|      | ||||
|     int32_t token_count = buffer_token_count(app, buffer); | ||||
|     if (buffer->tokens_are_ready && pos >= 0 && pos < token_count && count > 0){ | ||||
|         stream->app = app; | ||||
|         stream->buffer = buffer; | ||||
|         stream->base_tokens = data; | ||||
|         stream->count = count; | ||||
|         stream->start = round_down(pos, count); | ||||
|         stream->end = round_up(pos, count); | ||||
|         stream->token_count = token_count; | ||||
|          | ||||
|         if (stream->start < 0){ | ||||
|             stream->start = 0; | ||||
|         } | ||||
|         if (stream->end > stream->token_count){ | ||||
|             stream->end = stream->token_count; | ||||
|         } | ||||
|          | ||||
|         buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens); | ||||
|         stream->tokens = stream->base_tokens - stream->start; | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static Stream_Tokens | ||||
| begin_temp_stream_token(Stream_Tokens *stream){ | ||||
|     return(*stream); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| end_temp_stream_token(Stream_Tokens *stream, Stream_Tokens temp){ | ||||
|     if (stream->start != temp.start || stream->end != temp.end){ | ||||
|         Application_Links *app = stream->app; | ||||
|         buffer_read_tokens(app, temp.buffer, temp.start, temp.end, temp.base_tokens); | ||||
|         stream->tokens = stream->base_tokens - temp.start; | ||||
|         stream->start = temp.start; | ||||
|         stream->end = temp.end; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| forward_stream_tokens(Stream_Tokens *stream){ | ||||
|     Application_Links *app = stream->app; | ||||
|     Buffer_Summary *buffer = stream->buffer; | ||||
|     bool32 result = 0; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (stream->end < stream->token_count){ | ||||
|         stream->start = stream->end; | ||||
|         stream->end += stream->count; | ||||
|          | ||||
|         if (stream->end > stream->token_count){ | ||||
|             stream->end = stream->token_count; | ||||
|         } | ||||
|          | ||||
|         if (stream->start < stream->end){ | ||||
|             buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens); | ||||
|             stream->tokens = stream->base_tokens - stream->start; | ||||
|             result = 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static bool32 | ||||
| backward_stream_tokens(Stream_Tokens *stream){ | ||||
|     Application_Links *app = stream->app; | ||||
|     Buffer_Summary *buffer = stream->buffer; | ||||
|     bool32 result = 0; | ||||
|      | ||||
|     refresh_buffer(app, buffer); | ||||
|     if (stream->start > 0){ | ||||
|         stream->end = stream->start; | ||||
|         stream->start -= stream->count; | ||||
|          | ||||
|         if (0 > stream->start){ | ||||
|             stream->start = 0; | ||||
|         } | ||||
|          | ||||
|         if (stream->start < stream->end){ | ||||
|             buffer_read_tokens(app, buffer, stream->start, stream->end, stream->base_tokens); | ||||
|             stream->tokens = stream->base_tokens - stream->start; | ||||
|             result = 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // BOTTOM
 | ||||
|  | @ -82,7 +82,7 @@ partition_allocate(Partition *data, i32_4tech size){ | |||
|         ret = data->base + data->pos; | ||||
|         data->pos += size; | ||||
|     } | ||||
|     return ret; | ||||
|     return(ret); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
|  |  | |||
|  | @ -5,17 +5,6 @@ and list all locations. | |||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| #if !defined(FCODER_SEARCH) | ||||
| #define FCODER_SEARCH | ||||
| 
 | ||||
| #include "4coder_search.h" | ||||
| 
 | ||||
| #include "4coder_lib/4coder_table.h" | ||||
| #include "4coder_lib/4coder_mem.h" | ||||
| 
 | ||||
| #include "4coder_helper/4coder_streaming.h" | ||||
| #include "4coder_helper/4coder_long_seek.h" | ||||
| 
 | ||||
| //
 | ||||
| // Search Iteration Systems
 | ||||
| //
 | ||||
|  | @ -165,12 +154,6 @@ search_hit_add(General_Memory *general, Table *hits, String_Space *space, char * | |||
| // Search Key Checking
 | ||||
| //
 | ||||
| 
 | ||||
| typedef uint32_t Seek_Potential_Match_Direction; | ||||
| enum{ | ||||
|     SeekPotentialMatch_Forward, | ||||
|     SeekPotentialMatch_Backward, | ||||
| }; | ||||
| 
 | ||||
| static void | ||||
| seek_potential_match(Application_Links *app, Search_Range *range, Search_Key key, Search_Match *result, Seek_Potential_Match_Direction direction, int32_t start_pos, int32_t end_pos){ | ||||
|     bool32 case_insensitive = ((range->flags & SearchFlag_CaseInsensitive) != 0); | ||||
|  | @ -226,12 +209,6 @@ buffer_seek_alpha_numeric_end(Application_Links *app, Buffer_Summary *buffer, in | |||
|     return(pos); | ||||
| } | ||||
| 
 | ||||
| enum{ | ||||
|     FindResult_None, | ||||
|     FindResult_FoundMatch, | ||||
|     FindResult_PastEnd, | ||||
| }; | ||||
| 
 | ||||
| static int32_t | ||||
| match_check(Application_Links *app, Search_Range *range, int32_t *pos, Search_Match *result_ptr, Search_Key key){ | ||||
|     int32_t result_code = FindResult_None; | ||||
|  | @ -844,16 +821,6 @@ CUSTOM_DOC("Reads the string in the selected range and lists all exact case-inse | |||
| // Word Complete Command
 | ||||
| //
 | ||||
| 
 | ||||
| struct Word_Complete_State{ | ||||
|     Search_Set set; | ||||
|     Search_Iter iter; | ||||
|     Table hits; | ||||
|     String_Space str; | ||||
|     int32_t word_start; | ||||
|     int32_t word_end; | ||||
|     int32_t initialized; | ||||
| }; | ||||
| 
 | ||||
| static Word_Complete_State complete_state = {0}; | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(word_complete) | ||||
|  | @ -1010,7 +977,5 @@ CUSTOM_DOC("Iteratively tries completing the word to the left of the cursor with | |||
|     } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,10 +7,23 @@ | |||
| #if !defined(FCODER_SEARCH_H) | ||||
| #define FCODER_SEARCH_H | ||||
| 
 | ||||
| enum Search_Range_Type{ | ||||
|     SearchRange_FrontToBack, | ||||
|     SearchRange_BackToFront, | ||||
|     SearchRange_Wave, | ||||
| typedef int32_t Seek_Potential_Match_Direction; | ||||
| enum{ | ||||
|     SeekPotentialMatch_Forward = 0, | ||||
|     SeekPotentialMatch_Backward = 1, | ||||
| }; | ||||
| 
 | ||||
| enum{ | ||||
|     FindResult_None, | ||||
|     FindResult_FoundMatch, | ||||
|     FindResult_PastEnd, | ||||
| }; | ||||
| 
 | ||||
| typedef int32_t Search_Range_Type; | ||||
| enum{ | ||||
|     SearchRange_FrontToBack = 0, | ||||
|     SearchRange_BackToFront = 1, | ||||
|     SearchRange_Wave = 2, | ||||
| }; | ||||
| 
 | ||||
| typedef uint32_t Search_Range_Flag; | ||||
|  | @ -62,6 +75,16 @@ struct Search_Match{ | |||
|     int32_t found_match; | ||||
| }; | ||||
| 
 | ||||
| struct Word_Complete_State{ | ||||
|     Search_Set set; | ||||
|     Search_Iter iter; | ||||
|     Table hits; | ||||
|     String_Space str; | ||||
|     int32_t word_start; | ||||
|     int32_t word_end; | ||||
|     int32_t initialized; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // BOTOTM
 | ||||
|  |  | |||
|  | @ -1,20 +1,9 @@ | |||
| /*
 | ||||
|  * Helpers for doing long range seeks. | ||||
|  */ | ||||
| 4coder_seek.cpp - Procedures and commands for jumping through code to useful stop boundaries. | ||||
| */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| #if !defined(FCODER_LONG_SEEK_H) | ||||
| #define FCODER_LONG_SEEK_H | ||||
| 
 | ||||
| #include "4coder_helper/4coder_streaming.h" | ||||
| #include "4coder_lib/4coder_mem.h" | ||||
| #include "4coder_lib/4cpp_lexer.h" | ||||
| 
 | ||||
| //
 | ||||
| // Whitespace Based Seeks
 | ||||
| //
 | ||||
| 
 | ||||
| static int32_t | ||||
| seek_line_end(Application_Links *app, Buffer_Summary *buffer, int32_t pos){ | ||||
|     char chunk[1024]; | ||||
|  | @ -222,6 +211,7 @@ buffer_seek_whitespace_down(Application_Links *app, Buffer_Summary *buffer, int3 | |||
|      | ||||
|     return(pos); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_seek_whitespace_right(Application_Links *app, Buffer_Summary *buffer, int32_t pos){ | ||||
|     char data_chunk[1024]; | ||||
|  | @ -296,10 +286,6 @@ buffer_seek_whitespace_left(Application_Links *app, Buffer_Summary *buffer, int3 | |||
|     return(pos); | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // Boundary Type Seeks
 | ||||
| //
 | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_seek_alphanumeric_right(Application_Links *app, Buffer_Summary *buffer, int32_t pos){ | ||||
|     char data_chunk[1024]; | ||||
|  | @ -681,9 +667,7 @@ DOC_SEE(4coder_Buffer_Positioning_System) | |||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // Character Seeks
 | ||||
| //
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| void | ||||
| buffer_seek_delimiter_forward(Application_Links *app, Buffer_Summary *buffer, int32_t pos, char delim, int32_t *result){ | ||||
|  | @ -739,13 +723,6 @@ buffer_seek_delimiter_backward(Application_Links *app, Buffer_Summary *buffer, i | |||
|     finished:; | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // Buffer Substring Seeks
 | ||||
| //
 | ||||
| 
 | ||||
| // TODO(allen): This duplication is driving me crazy... I've gotta
 | ||||
| // upgrade the meta programming system another level.
 | ||||
| 
 | ||||
| // NOTE(allen): This is limitted to a string size of 512.
 | ||||
| // You can push it up or do something more clever by just
 | ||||
| // replacing char read_buffer[512]; with more memory.
 | ||||
|  | @ -933,11 +910,7 @@ buffer_seek_string_insensitive_backward(Application_Links *app, Buffer_Summary * | |||
|     } | ||||
| } | ||||
| 
 | ||||
| typedef uint32_t Buffer_Seek_String_Flags; | ||||
| enum{ | ||||
|     BufferSeekString_Backward = 1, | ||||
|     BufferSeekString_CaseInsensitive = 2, | ||||
| }; | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| static void | ||||
| buffer_seek_string(Application_Links *app, Buffer_Summary *buffer, int32_t pos, int32_t end, int32_t min, char *str, int32_t size, int32_t *result, Buffer_Seek_String_Flags flags){ | ||||
|  | @ -964,65 +937,13 @@ buffer_seek_string(Application_Links *app, Buffer_Summary *buffer, int32_t pos, | |||
|     } | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // Buffer Line Positioning
 | ||||
| //
 | ||||
| 
 | ||||
| static bool32 | ||||
| read_line(Application_Links *app, Partition *part, Buffer_Summary *buffer, int32_t line, String *str){ | ||||
|     Partial_Cursor begin = {0}; | ||||
|     Partial_Cursor end = {0}; | ||||
|      | ||||
|     bool32 success = false; | ||||
|      | ||||
|     if (buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &begin)){ | ||||
|         if (buffer_compute_cursor(app, buffer, seek_line_char(line, -1), &end)){ | ||||
|             if (begin.line == line){ | ||||
|                 if (0 <= begin.pos && begin.pos <= end.pos && end.pos <= buffer->size){ | ||||
|                     int32_t size = (end.pos - begin.pos); | ||||
|                     int32_t alloc_size = size + 1; | ||||
|                     char *memory = push_array(part, char, alloc_size); | ||||
|                     if (memory != 0){ | ||||
|                         *str = make_string(memory, 0, alloc_size); | ||||
|                         success = true; | ||||
|                         buffer_read_range(app, buffer, begin.pos, end.pos, str->str); | ||||
|                         str->size = size; | ||||
|                         terminate_with_null(str); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(success); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_get_line_start(Application_Links *app, Buffer_Summary *buffer, int32_t line){ | ||||
|     Partial_Cursor partial_cursor; | ||||
|     int32_t result = buffer->size; | ||||
|     if (line <= buffer->line_count){ | ||||
|         buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &partial_cursor); | ||||
|         result = partial_cursor.pos; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_get_line_end(Application_Links *app, Buffer_Summary *buffer, int32_t line){ | ||||
|     Partial_Cursor partial_cursor; | ||||
|     int32_t result = buffer->size; | ||||
|     if (line <= buffer->line_count){ | ||||
|         buffer_compute_cursor(app, buffer, seek_line_char(line, -1), &partial_cursor); | ||||
|         result = partial_cursor.pos; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| static bool32 | ||||
| buffer_line_is_blank(Application_Links *app, Buffer_Summary *buffer, int32_t line){ | ||||
|     Partial_Cursor start, end; | ||||
|     bool32 result = 0; | ||||
|     Partial_Cursor start = {0}; | ||||
|     Partial_Cursor end = {0}; | ||||
|     bool32 result = false; | ||||
|     if (line <= buffer->line_count){ | ||||
|         buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &start); | ||||
|         buffer_compute_cursor(app, buffer, seek_line_char(line, -1), &end); | ||||
|  | @ -1039,7 +960,7 @@ buffer_line_is_blank(Application_Links *app, Buffer_Summary *buffer, int32_t lin | |||
|             do{ | ||||
|                 for (;i < stream.end; ++i){ | ||||
|                     char c = stream.data[i]; | ||||
|                     if (!(c == ' ' || c == '\t' || c == '\r' || c == '\v' || c == '\n')){ | ||||
|                     if (!char_is_whitespace(c)){ | ||||
|                         result = false; | ||||
|                         goto double_break; | ||||
|                     } | ||||
|  | @ -1052,34 +973,6 @@ buffer_line_is_blank(Application_Links *app, Buffer_Summary *buffer, int32_t lin | |||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_get_line_number(Application_Links *app, Buffer_Summary *buffer, int32_t pos){ | ||||
|     Partial_Cursor partial_cursor = {0}; | ||||
|     buffer_compute_cursor(app, buffer, seek_pos(pos), &partial_cursor); | ||||
|     return(partial_cursor.line); | ||||
| } | ||||
| 
 | ||||
| static Cpp_Token* | ||||
| get_first_token_at_line(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line, int32_t *line_start_out = 0){ | ||||
|     int32_t line_start = buffer_get_line_start(app, buffer, line); | ||||
|     Cpp_Get_Token_Result get_token = cpp_get_token(tokens, line_start); | ||||
|      | ||||
|     if (get_token.in_whitespace){ | ||||
|         get_token.token_index += 1; | ||||
|     } | ||||
|      | ||||
|     if (line_start_out){ | ||||
|         *line_start_out = line_start; | ||||
|     } | ||||
|      | ||||
|     Cpp_Token *result = 0; | ||||
|     if (get_token.token_index < tokens.count){ | ||||
|         result = &tokens.tokens[get_token.token_index]; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| static String | ||||
| read_identifier_at_pos(Application_Links *app, Buffer_Summary *buffer, int32_t pos, char *space, int32_t max, Range *range_out){ | ||||
|     String query = {0}; | ||||
|  | @ -1106,7 +999,274 @@ read_identifier_at_pos(Application_Links *app, Buffer_Summary *buffer, int32_t p | |||
|     return(query); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| static int32_t | ||||
| flip_dir(int32_t dir){ | ||||
|     if (dir == DirLeft){ | ||||
|         return(DirRight); | ||||
|     } | ||||
|     else{ | ||||
|         return(DirLeft); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_boundary_seek(Application_Links *app, Buffer_Summary *buffer, | ||||
|                      int32_t start_pos, int32_t dir, Seek_Boundary_Flag flags){ | ||||
|     bool32 forward = (dir == DirRight); | ||||
|     return(buffer_boundary_seek(app, buffer, &global_part, start_pos, forward, flags)); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| view_buffer_boundary_seek_set_pos(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, | ||||
|                                   int32_t dir, uint32_t flags){ | ||||
|     int32_t pos = buffer_boundary_seek(app, buffer, &global_part, view->cursor.pos, dir, flags); | ||||
|     view_set_cursor(app, view, seek_pos(pos), true); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| view_boundary_seek_set_pos(Application_Links *app, View_Summary *view, | ||||
|                            int32_t dir, uint32_t flags){ | ||||
|     Buffer_Summary buffer = get_buffer(app, view->buffer_id, AccessProtected); | ||||
|     view_buffer_boundary_seek_set_pos(app, view, &buffer, dir, flags); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| current_view_boundary_seek_set_pos(Application_Links *app, int32_t dir, uint32_t flags){ | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     view_boundary_seek_set_pos(app, &view, dir, flags); | ||||
| } | ||||
| 
 | ||||
| static Range | ||||
| view_buffer_boundary_range(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, | ||||
|                            int32_t dir, uint32_t flags){ | ||||
|     int32_t pos1 = view->cursor.pos; | ||||
|     int32_t pos2 = buffer_boundary_seek(app, buffer, pos1, dir, flags); | ||||
|     return(make_range(pos1, pos2)); | ||||
| } | ||||
| 
 | ||||
| static Range | ||||
| view_buffer_snipe_range(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, | ||||
|                         int32_t dir, uint32_t flags){ | ||||
|     int32_t pos0 = view->cursor.pos; | ||||
|     int32_t pos1 = buffer_boundary_seek(app, buffer, pos0, dir          , flags); | ||||
|     int32_t pos2 = buffer_boundary_seek(app, buffer, pos1, flip_dir(dir), flags); | ||||
|     if (dir == DirLeft){ | ||||
|         if (pos2 < pos0){ | ||||
|             pos2 = pos0; | ||||
|         } | ||||
|     } | ||||
|     else{ | ||||
|         if (pos2 > pos0){ | ||||
|             pos2 = pos0; | ||||
|         } | ||||
|     } | ||||
|     return(make_range(pos1, pos2)); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| current_view_boundary_delete(Application_Links *app, int32_t dir, uint32_t flags){ | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|     if (buffer.exists){ | ||||
|         Range range = view_buffer_boundary_range(app, &view, &buffer, dir, flags); | ||||
|         buffer_replace_range(app, &buffer, range.min, range.max, 0, 0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| current_view_snipe_delete(Application_Links *app, int32_t dir, uint32_t flags){ | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|     if (buffer.exists){ | ||||
|         Range range = view_buffer_snipe_range(app, &view, &buffer, dir, flags); | ||||
|         buffer_replace_range(app, &buffer, range.min, range.max, 0, 0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_up) | ||||
| CUSTOM_DOC("Seeks the cursor up to the next blank line.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); | ||||
|     int32_t new_pos = buffer_seek_whitespace_up(app, &buffer, view.cursor.pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_down) | ||||
| CUSTOM_DOC("Seeks the cursor down to the next blank line.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); | ||||
|     int32_t new_pos = buffer_seek_whitespace_down(app, &buffer, view.cursor.pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_beginning_of_textual_line) | ||||
| CUSTOM_DOC("Seeks the cursor to the beginning of the line across all text.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); | ||||
|     int32_t new_pos = seek_line_beginning(app, &buffer, view.cursor.pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_end_of_textual_line) | ||||
| CUSTOM_DOC("Seeks the cursor to the end of the line across all text.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); | ||||
|     int32_t new_pos = seek_line_end(app, &buffer, view.cursor.pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_beginning_of_line) | ||||
| CUSTOM_DOC("Seeks the cursor to the beginning of the visual line.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     float y = view.cursor.wrapped_y; | ||||
|     if (view.unwrapped_lines){ | ||||
|         y = view.cursor.unwrapped_y; | ||||
|     } | ||||
|     view_set_cursor(app, &view, seek_xy(0, y, 1, view.unwrapped_lines), 1); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_end_of_line) | ||||
| CUSTOM_DOC("Seeks the cursor to the end of the visual line.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     float y = view.cursor.wrapped_y; | ||||
|     if (view.unwrapped_lines){ | ||||
|         y = view.cursor.unwrapped_y; | ||||
|     } | ||||
|     view_set_cursor(app, &view, seek_xy(max_f32, y, 1, view.unwrapped_lines), 1); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_up_end_line) | ||||
| CUSTOM_DOC("Seeks the cursor up to the next blank line and places it at the end of the line.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); | ||||
|     int32_t new_pos = buffer_seek_whitespace_up(app, &buffer, view.cursor.pos); | ||||
|     new_pos = seek_line_end(app, &buffer, new_pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_down_end_line) | ||||
| CUSTOM_DOC("Seeks the cursor down to the next blank line and places it at the end of the line.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); | ||||
|     int32_t new_pos = buffer_seek_whitespace_down(app, &buffer, view.cursor.pos); | ||||
|     new_pos = seek_line_end(app, &buffer, new_pos); | ||||
|     view_set_cursor(app, &view, seek_pos(new_pos), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(goto_beginning_of_file) | ||||
| CUSTOM_DOC("Sets the cursor to the beginning of the file.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     view_set_cursor(app, &view, seek_pos(0), true); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(goto_end_of_file) | ||||
| CUSTOM_DOC("Sets the cursor to the end of the file.") | ||||
| { | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessProtected); | ||||
|     view_set_cursor(app, &view, seek_pos(buffer.size), true); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_right) | ||||
| CUSTOM_DOC("Seek right for the next boundary between whitespace and non-whitespace.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_left) | ||||
| CUSTOM_DOC("Seek left for the next boundary between whitespace and non-whitespace.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_token_right) | ||||
| CUSTOM_DOC("Seek right for the next end of a token.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryToken); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_token_left) | ||||
| CUSTOM_DOC("Seek left for the next beginning of a token.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryToken); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_white_or_token_right) | ||||
| CUSTOM_DOC("Seek right for the next end of a token or boundary between whitespace and non-whitespace.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryToken|BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_white_or_token_left) | ||||
| CUSTOM_DOC("Seek left for the next end of a token or boundary between whitespace and non-whitespace.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryToken|BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_alphanumeric_right) | ||||
| CUSTOM_DOC("Seek right for boundary between alphanumeric characters and non-alphanumeric characters.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryAlphanumeric); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_alphanumeric_left) | ||||
| CUSTOM_DOC("Seek left for boundary between alphanumeric characters and non-alphanumeric characters.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryAlphanumeric); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_alphanumeric_or_camel_right) | ||||
| CUSTOM_DOC("Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryAlphanumeric|BoundaryCamelCase); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_alphanumeric_or_camel_left) | ||||
| CUSTOM_DOC("Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryAlphanumeric|BoundaryCamelCase); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(backspace_word) | ||||
| CUSTOM_DOC("Delete characters between the cursor position and the first alphanumeric boundary to the left.") | ||||
| { | ||||
|     current_view_boundary_delete(app, DirLeft, BoundaryAlphanumeric); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(delete_word) | ||||
| CUSTOM_DOC("Delete characters between the cursor position and the first alphanumeric boundary to the right.") | ||||
| { | ||||
|     current_view_boundary_delete(app, DirRight, BoundaryAlphanumeric); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(snipe_token_or_word) | ||||
| CUSTOM_DOC("Delete a single, whole token on or to the left of the cursor and post it to the clipboard.") | ||||
| { | ||||
|     current_view_snipe_delete(app, DirLeft, BoundaryToken|BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(snipe_token_or_word_right) | ||||
| CUSTOM_DOC("Delete a single, whole token on or to the right of the cursor and post it to the clipboard.") | ||||
| { | ||||
|     current_view_snipe_delete(app, DirRight, BoundaryToken|BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  | @ -0,0 +1,26 @@ | |||
| /*
 | ||||
| New File | ||||
| */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| #if !defined(FCODER_SEEK_H) | ||||
| #define FCODER_SEEK_H | ||||
| 
 | ||||
| typedef uint32_t Buffer_Seek_String_Flags; | ||||
| enum{ | ||||
|     BufferSeekString_Backward = 1, | ||||
|     BufferSeekString_CaseInsensitive = 2, | ||||
| }; | ||||
| 
 | ||||
| enum{ | ||||
|     DirLeft = 0, | ||||
|     DirRight = 1, | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1,185 +0,0 @@ | |||
| /*
 | ||||
| 4coder_seek_commands.cpp - Commands for jumping through code to useful stop boundaries. | ||||
| */ | ||||
| 
 | ||||
| // TOP
 | ||||
| 
 | ||||
| enum{ | ||||
|     DirLeft = 0, | ||||
|     DirRight = 1, | ||||
| }; | ||||
| 
 | ||||
| static int32_t | ||||
| flip_dir(int32_t dir){ | ||||
|     if (dir == DirLeft){ | ||||
|         return(DirRight); | ||||
|     } | ||||
|     else{ | ||||
|         return(DirLeft); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static int32_t | ||||
| buffer_boundary_seek(Application_Links *app, Buffer_Summary *buffer, | ||||
|                      int32_t start_pos, int32_t dir, Seek_Boundary_Flag flags){ | ||||
|     bool32 forward = (dir == DirRight); | ||||
|     return(buffer_boundary_seek(app, buffer, &global_part, start_pos, forward, flags)); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| view_buffer_boundary_seek_set_pos(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, | ||||
|                                   int32_t dir, uint32_t flags){ | ||||
|     int32_t pos = buffer_boundary_seek(app, buffer, &global_part, view->cursor.pos, dir, flags); | ||||
|     view_set_cursor(app, view, seek_pos(pos), true); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| view_boundary_seek_set_pos(Application_Links *app, View_Summary *view, | ||||
|                            int32_t dir, uint32_t flags){ | ||||
|     Buffer_Summary buffer = get_buffer(app, view->buffer_id, AccessProtected); | ||||
|     view_buffer_boundary_seek_set_pos(app, view, &buffer, dir, flags); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| current_view_boundary_seek_set_pos(Application_Links *app, int32_t dir, uint32_t flags){ | ||||
|     View_Summary view = get_active_view(app, AccessProtected); | ||||
|     view_boundary_seek_set_pos(app, &view, dir, flags); | ||||
| } | ||||
| 
 | ||||
| static Range | ||||
| view_buffer_boundary_range(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, | ||||
|                            int32_t dir, uint32_t flags){ | ||||
|     int32_t pos1 = view->cursor.pos; | ||||
|     int32_t pos2 = buffer_boundary_seek(app, buffer, pos1, dir, flags); | ||||
|     return(make_range(pos1, pos2)); | ||||
| } | ||||
| 
 | ||||
| static Range | ||||
| view_buffer_snipe_range(Application_Links *app, View_Summary *view, Buffer_Summary *buffer, | ||||
|                         int32_t dir, uint32_t flags){ | ||||
|     int32_t pos0 = view->cursor.pos; | ||||
|     int32_t pos1 = buffer_boundary_seek(app, buffer, pos0, dir          , flags); | ||||
|     int32_t pos2 = buffer_boundary_seek(app, buffer, pos1, flip_dir(dir), flags); | ||||
|     if (dir == DirLeft){ | ||||
|         if (pos2 < pos0){ | ||||
|             pos2 = pos0; | ||||
|         } | ||||
|     } | ||||
|     else{ | ||||
|         if (pos2 > pos0){ | ||||
|             pos2 = pos0; | ||||
|         } | ||||
|     } | ||||
|     return(make_range(pos1, pos2)); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| current_view_boundary_delete(Application_Links *app, int32_t dir, uint32_t flags){ | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|     if (buffer.exists){ | ||||
|         Range range = view_buffer_boundary_range(app, &view, &buffer, dir, flags); | ||||
|         buffer_replace_range(app, &buffer, range.min, range.max, 0, 0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| current_view_snipe_delete(Application_Links *app, int32_t dir, uint32_t flags){ | ||||
|     View_Summary view = get_active_view(app, AccessOpen); | ||||
|     Buffer_Summary buffer = get_buffer(app, view.buffer_id, AccessOpen); | ||||
|     if (buffer.exists){ | ||||
|         Range range = view_buffer_snipe_range(app, &view, &buffer, dir, flags); | ||||
|         buffer_replace_range(app, &buffer, range.min, range.max, 0, 0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_right) | ||||
| CUSTOM_DOC("Seek right for the next boundary between whitespace and non-whitespace.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_whitespace_left) | ||||
| CUSTOM_DOC("Seek left for the next boundary between whitespace and non-whitespace.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_token_right) | ||||
| CUSTOM_DOC("Seek right for the next end of a token.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryToken); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_token_left) | ||||
| CUSTOM_DOC("Seek left for the next beginning of a token.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryToken); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_white_or_token_right) | ||||
| CUSTOM_DOC("Seek right for the next end of a token or boundary between whitespace and non-whitespace.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryToken|BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_white_or_token_left) | ||||
| CUSTOM_DOC("Seek left for the next end of a token or boundary between whitespace and non-whitespace.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryToken|BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_alphanumeric_right) | ||||
| CUSTOM_DOC("Seek right for boundary between alphanumeric characters and non-alphanumeric characters.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryAlphanumeric); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_alphanumeric_left) | ||||
| CUSTOM_DOC("Seek left for boundary between alphanumeric characters and non-alphanumeric characters.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryAlphanumeric); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_alphanumeric_or_camel_right) | ||||
| CUSTOM_DOC("Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirRight, BoundaryAlphanumeric|BoundaryCamelCase); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(seek_alphanumeric_or_camel_left) | ||||
| CUSTOM_DOC("Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.") | ||||
| { | ||||
|     current_view_boundary_seek_set_pos(app, DirLeft, BoundaryAlphanumeric|BoundaryCamelCase); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////
 | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(backspace_word) | ||||
| CUSTOM_DOC("Delete characters between the cursor position and the first alphanumeric boundary to the left.") | ||||
| { | ||||
|     current_view_boundary_delete(app, DirLeft, BoundaryAlphanumeric); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(delete_word) | ||||
| CUSTOM_DOC("Delete characters between the cursor position and the first alphanumeric boundary to the right.") | ||||
| { | ||||
|     current_view_boundary_delete(app, DirRight, BoundaryAlphanumeric); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(snipe_token_or_word) | ||||
| CUSTOM_DOC("Delete a single, whole token on or to the left of the cursor and post it to the clipboard.") | ||||
| { | ||||
|     current_view_snipe_delete(app, DirLeft, BoundaryToken|BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(snipe_token_or_word_right) | ||||
| CUSTOM_DOC("Delete a single, whole token on or to the right of the cursor and post it to the clipboard.") | ||||
| { | ||||
|     current_view_snipe_delete(app, DirRight, BoundaryToken|BoundaryWhitespace); | ||||
| } | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
							
								
								
									
										16
									
								
								4ed.cpp
								
								
								
								
							
							
						
						
									
										16
									
								
								4ed.cpp
								
								
								
								
							|  | @ -976,7 +976,7 @@ app_links_init(System_Functions *system, Application_Links *app_links, void *dat | |||
| } | ||||
| 
 | ||||
| internal void | ||||
| setup_command_table(){ | ||||
| setup_command_table(void){ | ||||
| #define SET(n) command_table[cmdid_##n] = command_##n | ||||
|     SET(null); | ||||
|      | ||||
|  | @ -1304,7 +1304,8 @@ App_Init_Sig(app_init){ | |||
|      | ||||
|     Partition *partition = &models->mem.part; | ||||
|      | ||||
|     i32 panel_max_count = models->layout.panel_max_count = MAX_VIEWS; | ||||
|     i32 panel_max_count = MAX_VIEWS; | ||||
|     models->layout.panel_max_count = panel_max_count; | ||||
|     i32 divider_max_count = panel_max_count - 1; | ||||
|     models->layout.panel_count = 0; | ||||
|      | ||||
|  | @ -1355,7 +1356,7 @@ App_Init_Sig(app_init){ | |||
|      | ||||
|     { | ||||
|         umem memsize = KB(8); | ||||
|         void *mem = push_block(partition, (i32)memsize); | ||||
|         void *mem = push_array(partition, u8, (i32)memsize); | ||||
|         parse_context_init_memory(&models->parse_context_memory, mem, memsize); | ||||
|         parse_context_add_default(&models->parse_context_memory, &models->mem.general); | ||||
|     } | ||||
|  | @ -1383,9 +1384,9 @@ App_Init_Sig(app_init){ | |||
|     models->working_set.clipboard_rolling = 0; | ||||
|      | ||||
|     // TODO(allen): more robust allocation solution for the clipboard
 | ||||
|     if (clipboard.str){ | ||||
|     if (clipboard.str != 0){ | ||||
|         String *dest = working_set_next_clipboard_string(&models->mem.general, &models->working_set, clipboard.size); | ||||
|         copy_ss(dest, make_string((char*)clipboard.str, clipboard.size)); | ||||
|         copy(dest, make_string((char*)clipboard.str, clipboard.size)); | ||||
|     } | ||||
|      | ||||
|     // NOTE(allen): style setup
 | ||||
|  | @ -1436,7 +1437,7 @@ App_Init_Sig(app_init){ | |||
|         file_set_unimportant(file, true); | ||||
|         file->settings.unwrapped_lines = true; | ||||
|          | ||||
|         if (init_files[i].ptr){ | ||||
|         if (init_files[i].ptr != 0){ | ||||
|             *init_files[i].ptr = file; | ||||
|         } | ||||
|     } | ||||
|  | @ -1786,15 +1787,12 @@ App_Step_Sig(app_step){ | |||
|      | ||||
|     // NOTE(allen): prepare to start executing commands
 | ||||
|     Command_Data *cmd = &vars->command_data; | ||||
|      | ||||
|     cmd->models = models; | ||||
|     cmd->vars = vars; | ||||
|     cmd->system = system; | ||||
|     cmd->live_set = &models->live_set; | ||||
|      | ||||
|     cmd->screen_width = target->width; | ||||
|     cmd->screen_height = target->height; | ||||
|      | ||||
|     cmd->key = null_key_event_data; | ||||
|      | ||||
|     // NOTE(allen): First frame initialization
 | ||||
|  |  | |||
|  | @ -80,6 +80,7 @@ | |||
| #include "4ed_cli.cpp" | ||||
| #include "4ed_gui.cpp" | ||||
| #include "4ed_layout.cpp" | ||||
| #include "4coder_buffer_seek_constructors.cpp" | ||||
| #include "4ed_view.cpp" | ||||
| #include "4ed_edit.cpp" | ||||
| #include "4ed_view_ui.cpp" | ||||
|  |  | |||
|  | @ -13,8 +13,6 @@ | |||
| // Buffer low level operations
 | ||||
| //
 | ||||
| 
 | ||||
| #include "4coder_helper/4coder_seek_types.h" | ||||
| 
 | ||||
| inline void | ||||
| write_cursor_with_index(Cursor_With_Index *positions, i32 *count, i32 pos){ | ||||
|     positions[(*count)].index = *count; | ||||
|  |  | |||
|  | @ -120,8 +120,8 @@ enum{ | |||
| 
 | ||||
| char *custom_files[] = { | ||||
|     "../code/4coder_default_bindings.cpp", | ||||
|     "../code/power/4coder_experiments.cpp", | ||||
|     "../code/power/4coder_casey.cpp", | ||||
|     "../code/4coder_experiments.cpp", | ||||
|     "../code/4coder_casey.cpp", | ||||
|     "../4vim/4coder_chronal.cpp", | ||||
| }; | ||||
| 
 | ||||
|  | @ -682,23 +682,6 @@ package(char *cdir){ | |||
|         } | ||||
|         fm_end_temp(temp); | ||||
|     } | ||||
|      | ||||
|     // NOTE(allen): power
 | ||||
|     { | ||||
|         Temp temp = fm_begin_temp(); | ||||
|         char *pack_power_par_dir = fm_str("../current_dist_power"); | ||||
|         char *pack_power_dir = fm_str(pack_power_par_dir, "/power"); | ||||
|          | ||||
|         fm_clear_folder(pack_power_par_dir); | ||||
|         fm_make_folder_if_missing(pack_power_dir); | ||||
|         fm_make_folder_if_missing(fm_str(pack_dir, "/power")); | ||||
|         fm_copy_all("power", "*", pack_power_dir); | ||||
|          | ||||
|         char *dist_name = get_4coder_dist_name(Platform_None, "power", Arch_None); | ||||
|         char *zip_name = fm_str(pack_dir, "/power/", dist_name, ".zip"); | ||||
|         fm_zip(pack_power_par_dir, "power", zip_name); | ||||
|         fm_end_temp(temp); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char **argv){ | ||||
|  |  | |||
|  | @ -45,7 +45,9 @@ memory_init(){ | |||
| } | ||||
| 
 | ||||
| internal void | ||||
| load_app_code(){ | ||||
| load_app_code(void){ | ||||
|     LOG("Loading 4coder core..."); | ||||
|      | ||||
|     App_Get_Functions *get_funcs = 0; | ||||
|      | ||||
|     if (system_load_library(&libraries.app_code, "4ed_app", LoadLibrary_BinaryDirectory)){ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Allen Webster
						Allen Webster