working on removing open_hook from view_set_file
							parent
							
								
									db058ea6d7
								
							
						
					
					
						commit
						a690547aa2
					
				|  | @ -357,6 +357,7 @@ struct Application_Links; | |||
| #define GET_PARAMETER_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int param_index) | ||||
| #define GET_BUFFER_BY_NAME(n) Buffer_Summary n(Application_Links *app, char *filename, int len) | ||||
| 
 | ||||
| // TODO(allen): Need more flexible seek system somehow.  Regex?  Just expose the text stream to the user?
 | ||||
| #define BUFFER_SEEK_DELIMITER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out) | ||||
| #define BUFFER_SEEK_STRING_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out) | ||||
| #define BUFFER_SEEK_STRING_INSENSITIVE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out) | ||||
|  |  | |||
|  | @ -40,6 +40,7 @@ struct Models{ | |||
|     u32 command_coroutine_flags[2]; | ||||
|      | ||||
|     Hook_Function *hooks[hook_type_count]; | ||||
|     Application_Links *app; | ||||
|      | ||||
|     i32 *buffer_param_indices; | ||||
|     i32 buffer_param_count, buffer_param_max; | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -576,6 +576,9 @@ file_create_from_string(System_Functions *system, Models *models, | |||
|         file->state.undo.history_head_block = 0; | ||||
|         file->state.undo.current_block_normal = 1; | ||||
|     } | ||||
|      | ||||
|     Hook_Function *open_hook = models->hooks[hook_open_file]; | ||||
|     open_hook(models->app); | ||||
| } | ||||
| 
 | ||||
| internal b32 | ||||
|  | @ -1283,9 +1286,8 @@ view_set_file( | |||
|             view->reinit_scrolling = 1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // TODO(allen): Bypass all this nonsense, it's a hack!  Hooks need parameters!
 | ||||
|     // Just accept it and pass the file to the open hook when it is loaded.
 | ||||
|      | ||||
| #if 0 | ||||
|     if (file){ | ||||
|         if (open_hook && file->settings.is_initialized == 0){ | ||||
|             models->buffer_param_indices[models->buffer_param_count++] = file->id.id; | ||||
|  | @ -1294,13 +1296,6 @@ view_set_file( | |||
|             file->settings.is_initialized = 1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| #if 0 | ||||
|     if (set_vui){ | ||||
|         // TODO(allen): Fix this! There should be a way to easily separate setting a file,
 | ||||
|         // and switching to file mode, so that they don't cross over eachother like this.
 | ||||
|         view->showing_ui = VUI_None; | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| Distribution Date: 12.5.2016 (dd.mm.yyyy) | ||||
| Distribution Date: 13.5.2016 (dd.mm.yyyy) | ||||
| 
 | ||||
| Thank you for contributing to the 4coder project! | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| Distribution Date: 12.5.2016 (dd.mm.yyyy) | ||||
| Distribution Date: 13.5.2016 (dd.mm.yyyy) | ||||
| 
 | ||||
| Thank you for contributing to the 4coder project! | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,29 +1,42 @@ | |||
| @echo off | ||||
| 
 | ||||
| call "ctime" -begin 4ed_data.ctm | ||||
| 
 | ||||
| set OPTS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd4610 /wd4390 /WX | ||||
| set OPTS=%OPTS% /GR- /EHa- /nologo /FC | ||||
| set INCLUDES=/I..\foreign | ||||
| set LIBS=user32.lib winmm.lib gdi32.lib opengl32.lib | ||||
| set ICON=..\res\icon.res | ||||
| set DEFINES= | ||||
| set FirstError=0 | ||||
| 
 | ||||
| pushd ..\meta | ||||
| cl %OPTS% ..\code\4ed_metagen.cpp /Femetagen | ||||
| if %ERRORLEVEL% neq 0 (set FirstError=1) | ||||
| popd | ||||
| 
 | ||||
| pushd ..\code | ||||
| "..\meta\metagen" | ||||
| if %ERRORLEVEL% neq 0 (set FirstError=1) | ||||
| popd | ||||
| 
 | ||||
| pushd ..\build | ||||
| REM call "..\code\buildsuper.bat" ..\code\4coder_default_bindings.cpp | ||||
| call "..\code\buildsuper.bat" ..\code\power\4coder_experiments.cpp | ||||
| call "..\code\buildsuper.bat" ..\code\4coder_default_bindings.cpp | ||||
| REM call "..\code\buildsuper.bat" ..\code\power\4coder_experiments.cpp | ||||
| REM call "..\code\buildsuper.bat" ..\code\power\4coder_casey.cpp | ||||
| if %ERRORLEVEL% neq 0 (set FirstError=1) | ||||
| 
 | ||||
| set EXPORTS=/EXPORT:app_get_functions | ||||
| cl %OPTS% %INCLUDES% %DEFINES% ..\code\4ed_app_target.cpp %* /Fe4ed_app /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS% | ||||
| if %ERRORLEVEL% neq 0 (set FirstError=1) | ||||
| 
 | ||||
| cl %OPTS% %INCLUDES% %DEFINES% ..\code\win32_4ed.cpp %LIBS% %ICON% %* /Fe4ed | ||||
| if %ERRORLEVEL% neq 0 (set FirstError=1) | ||||
| 
 | ||||
| popd | ||||
| 
 | ||||
| call "ctime" -end 4ed_data.ctm %FirstError% | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,6 +14,13 @@ | |||
| /* TODO(casey): Here are our current issues
 | ||||
| 
 | ||||
|    - High priority: | ||||
|      - Buffer switching still seems a little bit broken.  I find I can't reliably hit switch-return | ||||
|        and switch to the most recently viewed file that wasn't one of the two currently viewed buffers? | ||||
|        But maybe I'm imagining things? | ||||
|      - High-DPI settings break rendering and all fonts just show up as solid squares | ||||
|      - Pretty sure auto-indent has some bugs.  Things that should be pretty easy to indent | ||||
|        properly even from only a few surrounding lines seem to be indented improperly at the moment | ||||
|      - Multi-line comments should default to indenting to the indentation of the line prior? | ||||
|      - Would like the option to indent to hanging parentheses, equals signs, etc. instead of | ||||
|        always just "one tab in from the previous line". | ||||
|        - Actually, maybe just expose the dirty state, so that the user can decide whether to | ||||
|  | @ -24,18 +31,29 @@ | |||
|      - Auto-complete doesn't pick nearby words first, it seems, which makes it much slower to use? | ||||
|      - Bug with not being able to switch-to-corresponding-file in another buffer | ||||
|        without accidentally bringing up the file open dialog? | ||||
|       | ||||
|      - Up/down arrows and mouse clicks on wrapped lines don't seem to work properly with several wraps. | ||||
|        (eg., a line wrapped to more than 2 physical lines on the screen often doesn't work anymore, | ||||
|         with up or down jumping to totally wrong places, and mouse clicking jumping to wrong places | ||||
|         as well - similarly, scrolling breaks, in that it thinks it has "hit the end" of the buffer | ||||
|         when you cursor down, but the cursor and the rest of the wrapped lines are actually off | ||||
|         the bottom of the screen) | ||||
| 
 | ||||
|    - Display: | ||||
|      - There are often repaint bugs with 4coder coming to the front / unminimizing, etc. | ||||
|        I think this might have something to do with the way you're doing lots of semaphore | ||||
|        locking but I haven't investigated yet. | ||||
|      - Need a word-wrap mode that wraps at word boundaries instead of characters | ||||
|      - Need to be able to set a word wrap length at something other than the window | ||||
| ?FIXED First go-to-line for a file seems to still just go to the beginning of the buffer? | ||||
|        Not sure Allen's right about the slash problem, but either way, we need some | ||||
|        way to fix it. | ||||
|      - Need a way of highlighting the current line like Emacs does for the benefit | ||||
|        of people on The Stream(TM) | ||||
|      - NOTE / IMPORTANT / TODO highlighting?  Ability to customize?  Whatever. | ||||
|      - Some kind of parentheses highlighting?  I can write this myself, but I | ||||
|        would need some way of adding highlight information to the buffer. | ||||
|      - Need a way of highlighting the current line like Emacs does for the benefit | ||||
|        of people on The Stream(TM) | ||||
|      - Some kind of matching brace display so in long ifs, etc., you can see | ||||
|        what they match (maybe draw it directly into the buffer?) | ||||
| 
 | ||||
|    - Indentation: | ||||
|      - Multiple // lines don't seem to indent properly.  The first one will go to the correct place, but the subsequent ones will go to the first column regardless?
 | ||||
|  | @ -44,28 +62,44 @@ | |||
|        the same margin as the prev. line (4coder just goes back to column 1).  It'd | ||||
|        be nice if it go _better_ than Emacs, with no need to manually flow comments, | ||||
|        etc. | ||||
|      - Up/down arrows and mouse clicks on wrapped lines don't seem to work properly after the second wrap  | ||||
|        (eg., a line wrapped to more than 2 physical lines on the screen.) | ||||
| 
 | ||||
|    - Buffer management:  | ||||
|      - Switch-to-buffer with no typing, just return, should switch to the most recently | ||||
|        used buffer that is not currently displayed in a view. | ||||
|   ?FIXED Kill-buffer should perform this switch automatically, or it should be easy | ||||
|        to build a custom kill buffer that does | ||||
|      - Seems like there's no way to switch to buffers whose names are substrings of other | ||||
|        buffers' names without using the mouse? | ||||
|        - Also, mouse-clicking on buffers doesn't seem to work reliably?  Often it just goes to a  | ||||
|          blank window? | ||||
| 
 | ||||
|    - File system | ||||
|      - When switching to a buffer that has changed on disk, notify?  Really this can just | ||||
|        be some way to query the modification flag and then the customization layer can do it? | ||||
|      - Still can't seem to open a zero-length file? | ||||
|      - I'd prefer it if file-open could create new files, and that I could get called on that | ||||
|        so I can insert my boilerplate headers on new files | ||||
|      - I'd prefer it if file-open deleted per-character instead of deleting entire path sections | ||||
| 
 | ||||
|    - Need auto-complete for things like "arbitrary command", with options listed, etc., | ||||
|      so this should either be built into 4ed, or the custom DLL should have the ability | ||||
|      to display possible completions and iterate over internal cmdid's, etc.  Possibly | ||||
|      the latter, for maximal ability of customizers to add their own commands? | ||||
| 
 | ||||
|    - Default directory for file open / build search should be that of the current | ||||
|      buffer, not tracked separately?  Probably I should code this on my own. | ||||
| 
 | ||||
|    - Macro recording/playback | ||||
| 
 | ||||
|    - Arbitrary cool features: | ||||
|      - LOC count for the buffer and for all buffers summed shown in the title bar? | ||||
|      - Show auto-parsed #if/if/for/while/etc. statements at else and closing places. | ||||
|      - Automatic highlighting of the region in side the parentheses / etc. | ||||
|      - You should just implement a shell inside 4coder which can call all the 4coder | ||||
|        stuff as well as execute system stuff, so that from now on you just write | ||||
|        scripts "in 4coder", etc., so they are always portable everywhere 4coder runs? | ||||
| 
 | ||||
|    - Things I should write: | ||||
|      - Ability to do "file open from same directory as the current buffer" | ||||
|      - Spell-checker | ||||
|      - To-do list dependent on project? | ||||
|      - Repeat last replace? | ||||
|      - Maybe search could be a permanent thing, so instead of initiating a search, | ||||
|        you're just _changing_ the search term with MODAL-S, and then there's _always_ | ||||
|        a next-of-these-in... and that could go through buffers in order, to... | ||||
| */ | ||||
| 
 | ||||
| // NOTE(casey): Microsoft/Windows is poopsauce.
 | ||||
|  | @ -73,10 +107,10 @@ | |||
| #include <math.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "..\4coder_default_includes.cpp" | ||||
| #include "..\4coder_default_include.cpp" | ||||
| 
 | ||||
| enum maps{ | ||||
| 	my_code_map | ||||
|     my_code_map | ||||
| }; | ||||
| 
 | ||||
| #ifndef Assert | ||||
|  | @ -90,6 +124,7 @@ struct Parsed_Error | |||
| 
 | ||||
|     String target_file_name; | ||||
|     int target_line_number; | ||||
|     int target_column_number; | ||||
| 
 | ||||
|     int source_buffer_id; | ||||
|     int source_position; | ||||
|  | @ -114,6 +149,7 @@ enum token_type | |||
|     Token_Percent, | ||||
|     Token_Colon, | ||||
|     Token_Number, | ||||
|     Token_Comma, | ||||
| 
 | ||||
|     Token_EndOfStream, | ||||
| }; | ||||
|  | @ -231,6 +267,7 @@ GetToken(tokenizer *Tokenizer) | |||
|         case '/': {Token.Type = Token_ForwardSlash;} break; | ||||
|         case '%': {Token.Type = Token_Percent;} break; | ||||
|         case ':': {Token.Type = Token_Colon;} break; | ||||
|         case ',': {Token.Type = Token_Comma;} break; | ||||
| 
 | ||||
|         default: | ||||
|         { | ||||
|  | @ -380,6 +417,7 @@ CUSTOM_COMMAND_SIG(casey_kill_to_end_of_line) | |||
| 
 | ||||
|     Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); | ||||
|     app->buffer_replace_range(app, &buffer, range.min, range.max, 0, 0); | ||||
|     exec_command(app, auto_tab_line_at_cursor); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(casey_paste_and_tab) | ||||
|  | @ -396,6 +434,12 @@ CUSTOM_COMMAND_SIG(casey_seek_beginning_of_line_and_tab) | |||
|     exec_command(app, auto_tab_line_at_cursor); | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(casey_seek_beginning_of_line) | ||||
| { | ||||
|     exec_command(app, auto_tab_line_at_cursor); | ||||
|     exec_command(app, cmdid_seek_beginning_of_line); | ||||
| } | ||||
| 
 | ||||
| struct switch_to_result | ||||
| { | ||||
|     bool Switched; | ||||
|  | @ -621,7 +665,7 @@ casey_goto_error(Application_Links *app, Parsed_Error e) | |||
|         switch_to_result Switch = SwitchToOrLoadFile(app, e.target_file_name, false); | ||||
|         if(Switch.Switched) | ||||
|         { | ||||
|             app->view_set_cursor(app, &Switch.view, seek_line_char(e.target_line_number, 0), 1); | ||||
|             app->view_set_cursor(app, &Switch.view, seek_line_char(e.target_line_number, e.target_column_number), 1); | ||||
|         } | ||||
| 
 | ||||
|         View_Summary compilation_view = get_first_view_with_buffer(app, e.source_buffer_id); | ||||
|  | @ -667,6 +711,18 @@ casey_parse_error(Application_Links *app, Buffer_Summary buffer, View_Summary vi | |||
|             if(LineToken.Type == Token_Number) | ||||
|             { | ||||
|                 token CloseToken = GetToken(&Tokenizer); | ||||
| 
 | ||||
|                 int column_number = 0; | ||||
|                 if(CloseToken.Type == Token_Comma) | ||||
|                 { | ||||
|                     token ColumnToken = GetToken(&Tokenizer); | ||||
|                     if(ColumnToken.Type == Token_Number) | ||||
|                     { | ||||
|                         column_number = atoi(ColumnToken.Text); | ||||
|                         CloseToken = GetToken(&Tokenizer); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if(CloseToken.Type == Token_CloseParen) | ||||
|                 { | ||||
|                     token ColonToken = GetToken(&Tokenizer); | ||||
|  | @ -693,6 +749,7 @@ casey_parse_error(Application_Links *app, Buffer_Summary buffer, View_Summary vi | |||
|                         result.exists = true; | ||||
|                         result.target_file_name = make_string(Seek, (int)(Token.Text - Seek));; | ||||
|                         result.target_line_number = line_number; | ||||
|                         result.target_column_number = column_number; | ||||
|                         result.source_buffer_id = buffer.buffer_id; | ||||
|                         result.source_position = start + (int)(ColonToken.Text - ParsingRegion); | ||||
| 
 | ||||
|  | @ -1066,7 +1123,8 @@ CUSTOM_COMMAND_SIG(casey_execute_arbitrary_command) | |||
| internal void | ||||
| UpdateModalIndicator(Application_Links *app) | ||||
| { | ||||
|     Theme_Color normal_colors[] = { | ||||
|     Theme_Color normal_colors[] =  | ||||
|     { | ||||
|         {Stag_Cursor, 0x40FF40}, | ||||
|         {Stag_At_Cursor, 0x161616}, | ||||
|         {Stag_Mark, 0x808080}, | ||||
|  | @ -1076,7 +1134,8 @@ UpdateModalIndicator(Application_Links *app) | |||
|         {Stag_Bar, 0xCACACA} | ||||
|     }; | ||||
| 
 | ||||
|     Theme_Color edit_colors[] = { | ||||
|     Theme_Color edit_colors[] =  | ||||
|     { | ||||
|         {Stag_Cursor, 0xFF0000}, | ||||
|         {Stag_At_Cursor, 0x00FFFF}, | ||||
|         {Stag_Mark, 0xFF6F1A}, | ||||
|  | @ -1137,22 +1196,22 @@ DEFINE_MODAL_KEY(modal_forward_slash, cmdid_change_active_panel); | |||
| DEFINE_MODAL_KEY(modal_semicolon, cmdid_cursor_mark_swap); // TODO(casey): Maybe cmdid_history_backward?
 | ||||
| DEFINE_BIMODAL_KEY(modal_open_bracket, casey_begin_keyboard_macro_recording, write_and_auto_tab); | ||||
| DEFINE_BIMODAL_KEY(modal_close_bracket, casey_end_keyboard_macro_recording, write_and_auto_tab); | ||||
| DEFINE_MODAL_KEY(modal_a, cmdid_write_character); // TODO(casey): Available
 | ||||
| DEFINE_MODAL_KEY(modal_a, cmdid_write_character); // TODO(casey): Arbitrary command + casey_quick_calc
 | ||||
| DEFINE_MODAL_KEY(modal_b, cmdid_interactive_switch_buffer); | ||||
| DEFINE_MODAL_KEY(modal_c, casey_find_corresponding_file); | ||||
| DEFINE_MODAL_KEY(modal_d, cmdid_write_character); // TODO(casey): Available
 | ||||
| DEFINE_MODAL_KEY(modal_d, casey_kill_to_end_of_line); | ||||
| DEFINE_MODAL_KEY(modal_e, cmdid_write_character); // TODO(casey): Available
 | ||||
| DEFINE_MODAL_KEY(modal_f, casey_paste_and_tab); | ||||
| DEFINE_MODAL_KEY(modal_g, goto_line); | ||||
| DEFINE_MODAL_KEY(modal_h, cmdid_auto_tab_range); | ||||
| DEFINE_MODAL_KEY(modal_i, cmdid_redo); | ||||
| DEFINE_MODAL_KEY(modal_j, casey_imenu); | ||||
| DEFINE_MODAL_KEY(modal_k, casey_kill_to_end_of_line); | ||||
| DEFINE_MODAL_KEY(modal_l, replace_in_range); | ||||
| DEFINE_MODAL_KEY(modal_i, cmdid_move_up); | ||||
| DEFINE_MODAL_KEY(modal_j, seek_white_or_token_left); | ||||
| DEFINE_MODAL_KEY(modal_k, cmdid_move_down); | ||||
| DEFINE_MODAL_KEY(modal_l, seek_white_or_token_right); | ||||
| DEFINE_MODAL_KEY(modal_m, casey_save_and_make_without_asking); | ||||
| DEFINE_MODAL_KEY(modal_n, casey_goto_next_error); | ||||
| DEFINE_MODAL_KEY(modal_o, query_replace); | ||||
| DEFINE_MODAL_KEY(modal_p, casey_quick_calc); | ||||
| DEFINE_MODAL_KEY(modal_p, replace_in_range); | ||||
| DEFINE_MODAL_KEY(modal_q, cmdid_copy); | ||||
| DEFINE_MODAL_KEY(modal_r, reverse_search); // NOTE(allen): I've modified my default search so you can use it now.
 | ||||
| DEFINE_MODAL_KEY(modal_s, search); | ||||
|  | @ -1161,7 +1220,7 @@ DEFINE_MODAL_KEY(modal_u, cmdid_undo); | |||
| DEFINE_MODAL_KEY(modal_v, casey_switch_buffer_other_window); | ||||
| DEFINE_MODAL_KEY(modal_w, cmdid_cut); | ||||
| DEFINE_MODAL_KEY(modal_x, casey_find_corresponding_file_other_window); | ||||
| DEFINE_MODAL_KEY(modal_y, auto_tab_line_at_cursor); | ||||
| DEFINE_MODAL_KEY(modal_y, cmdid_redo); | ||||
| DEFINE_MODAL_KEY(modal_z, cmdid_interactive_open); | ||||
| 
 | ||||
| DEFINE_MODAL_KEY(modal_1, casey_build_search); // TODO(casey): Shouldn't need to bind a key for this?
 | ||||
|  | @ -1183,7 +1242,7 @@ DEFINE_BIMODAL_KEY(modal_down, cmdid_move_down, cmdid_move_down); | |||
| DEFINE_BIMODAL_KEY(modal_left, seek_white_or_token_left, cmdid_move_left);  | ||||
| DEFINE_BIMODAL_KEY(modal_right, seek_white_or_token_right, cmdid_move_right); | ||||
| DEFINE_BIMODAL_KEY(modal_delete, casey_delete_token_right, cmdid_delete); | ||||
| DEFINE_BIMODAL_KEY(modal_home, cmdid_seek_beginning_of_line, casey_seek_beginning_of_line_and_tab); | ||||
| DEFINE_BIMODAL_KEY(modal_home, casey_seek_beginning_of_line, casey_seek_beginning_of_line_and_tab); | ||||
| DEFINE_BIMODAL_KEY(modal_end, cmdid_seek_end_of_line, cmdid_seek_end_of_line); | ||||
| DEFINE_BIMODAL_KEY(modal_page_up, cmdid_page_up, cmdid_seek_whitespace_up); | ||||
| DEFINE_BIMODAL_KEY(modal_page_down, cmdid_page_down, cmdid_seek_whitespace_down); | ||||
|  | @ -1365,14 +1424,50 @@ HOOK_SIG(casey_start) | |||
|     app->change_theme(app, literal("Handmade Hero")); | ||||
|     app->change_font(app, literal("liberation mono")); | ||||
| 
 | ||||
|     Theme_Color colors[] = | ||||
|     { | ||||
|         {Stag_Default, 0xA08563}, | ||||
|         // {Stag_Bar, },
 | ||||
|         // {Stag_Bar_Active, },
 | ||||
|         // {Stag_Base, },
 | ||||
|         // {Stag_Pop1, },
 | ||||
|         // {Stag_Pop2, },
 | ||||
|         // {Stag_Back, },
 | ||||
|         // {Stag_Margin, },
 | ||||
|         // {Stag_Margin_Hover, },
 | ||||
|         // {Stag_Margin_Active, },
 | ||||
|         // {Stag_Cursor, },
 | ||||
|         // {Stag_At_Cursor, },
 | ||||
|         // {Stag_Highlight, },
 | ||||
|         // {Stag_At_Highlight, },
 | ||||
|         {Stag_Comment, 0x7D7D7D}, | ||||
|         {Stag_Keyword, 0xCD950C}, | ||||
|         // {Stag_Str_Constant, },
 | ||||
|         // {Stag_Char_Constant, },
 | ||||
|         // {Stag_Int_Constant, },
 | ||||
|         // {Stag_Float_Constant, },
 | ||||
|         // {Stag_Bool_Constant, },
 | ||||
|         {Stag_Preproc, 0xDAB98F}, | ||||
|         {Stag_Include, 0x6B8E23}, | ||||
|         // {Stag_Special_Character, },
 | ||||
|         // {Stag_Highlight_Junk, },
 | ||||
|         // {Stag_Highlight_White, },
 | ||||
|         // {Stag_Paste, },
 | ||||
|         // {Stag_Undo, },
 | ||||
|         // {Stag_Next_Undo, },
 | ||||
|     }; | ||||
|     app->set_theme_colors(app, colors, ArrayCount(colors)); | ||||
| 
 | ||||
|     win32_toggle_fullscreen(); | ||||
| 
 | ||||
|     return(0); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| get_bindings(Bind_Helper *context) | ||||
| extern "C" GET_BINDING_DATA(get_bindings) | ||||
| { | ||||
|     Bind_Helper context_actual = begin_bind_helper(data, size); | ||||
|     Bind_Helper *context = &context_actual; | ||||
| 
 | ||||
|     set_hook(context, hook_start, casey_start); | ||||
|     set_hook(context, hook_open_file, casey_file_settings); | ||||
|     set_scroll_rule(context, casey_smooth_scroll_rule); | ||||
|  | @ -1388,18 +1483,12 @@ get_bindings(Bind_Helper *context) | |||
|         bind(context, 'b', MDFR_NONE, cmdid_interactive_switch_buffer); | ||||
|         bind(context, key_page_up, MDFR_NONE, search); | ||||
|         bind(context, key_page_down, MDFR_NONE, reverse_search); | ||||
| 
 | ||||
|         // NOTE(allen): I added this here myself, I believe this is what you want.
 | ||||
|         bind(context, 'm', MDFR_NONE, casey_save_and_make_without_asking); | ||||
|     }         | ||||
|     end_map(context); | ||||
| 
 | ||||
|     begin_map(context, mapid_file); | ||||
| 
 | ||||
|     // NOTE(allen): This is a new concept in the API. Binding this can be thought of as binding
 | ||||
|     // all combos which have an ascii code (shifted or not) and unmodified by CTRL or ALT.
 | ||||
|     // As of now, if this is used it cannot be overriden for particular combos; this overrides
 | ||||
|     // normal bindings.
 | ||||
|     bind_vanilla_keys(context, cmdid_write_character); | ||||
| 
 | ||||
|     bind(context, key_insert, MDFR_NONE, begin_free_typing); | ||||
|  | @ -1496,4 +1585,8 @@ get_bindings(Bind_Helper *context) | |||
|     bind(context, '\t', MDFR_SHIFT, modal_tab); | ||||
| 
 | ||||
|     end_map(context); | ||||
| 
 | ||||
|     end_bind_helper(context); | ||||
|     return context->write_total; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,6 +26,230 @@ CUSTOM_COMMAND_SIG(kill_rect){ | |||
|     } | ||||
| } | ||||
| 
 | ||||
| // NOTE(allen): This stream stuff will be moved to helper if it looks
 | ||||
| // like it will be helpful.  So if you want to use it to build your own
 | ||||
| // commands I suggest you move it there first.
 | ||||
| struct Stream_Chunk{ | ||||
|     Application_Links *app; | ||||
|     Buffer_Summary *buffer; | ||||
|      | ||||
|     char *base_data; | ||||
|     int start, end; | ||||
|     int data_size; | ||||
|      | ||||
|     char *data; | ||||
| }; | ||||
| 
 | ||||
| int | ||||
| round_down(int x, int b){ | ||||
|     int r = 0; | ||||
|     if (x >= 0){ | ||||
|         r = x - (x % b); | ||||
|     } | ||||
|     return(r); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| round_up(int x, int b){ | ||||
|     int r = 0; | ||||
|     if (x >= 0){ | ||||
|         r = x - (x % b) + b; | ||||
|     } | ||||
|     return(r); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| init_stream_chunk(Stream_Chunk *chunk, | ||||
|     Application_Links *app, Buffer_Summary *buffer, | ||||
|     int pos, char *data, int size){ | ||||
|     int result = 0; | ||||
|      | ||||
|     app->refresh_buffer(app, buffer); | ||||
|     if (pos >= 0 && pos < buffer->size && size > 0){ | ||||
|         result = 1; | ||||
|         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->end > buffer->size){ | ||||
|             chunk->end = buffer->size; | ||||
|         } | ||||
|         app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data); | ||||
|         chunk->data = chunk->base_data - chunk->start; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| forward_stream_chunk(Stream_Chunk *chunk){ | ||||
|     Application_Links *app = chunk->app; | ||||
|     Buffer_Summary *buffer = chunk->buffer; | ||||
|     int result = 0; | ||||
|      | ||||
|     app->refresh_buffer(app, buffer); | ||||
|     if (chunk->end < buffer->size){ | ||||
|         result = 1; | ||||
|         chunk->start = chunk->end; | ||||
|         chunk->end += chunk->data_size; | ||||
|         if (chunk->end > buffer->size){ | ||||
|             chunk->end = buffer->size; | ||||
|         } | ||||
|         app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data); | ||||
|         chunk->data = chunk->base_data - chunk->start; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| backward_stream_chunk(Stream_Chunk *chunk){ | ||||
|     Application_Links *app = chunk->app; | ||||
|     Buffer_Summary *buffer = chunk->buffer; | ||||
|     int result = 0; | ||||
|      | ||||
|     app->refresh_buffer(app, buffer); | ||||
|     if (chunk->start > 0){ | ||||
|         result = 1; | ||||
|         chunk->end = chunk->start; | ||||
|         chunk->start -= chunk->data_size; | ||||
|         if (chunk->start < 0){ | ||||
|             chunk->start = 0; | ||||
|         } | ||||
|         app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data); | ||||
|         chunk->data = chunk->base_data - chunk->start; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| // TODO(allen): Both of these brace related commands would work better
 | ||||
| // if the API exposed access to the tokens in a code file.
 | ||||
| CUSTOM_COMMAND_SIG(mark_matching_brace){ | ||||
|     View_Summary view = app->get_active_view(app); | ||||
|     Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); | ||||
|      | ||||
|     int start_pos = view.cursor.pos; | ||||
|      | ||||
|     // NOTE(allen): The user provides the memory that the chunk uses,
 | ||||
|     // this chunk will then be filled at each step of the text stream loop.
 | ||||
|     // This way you can look for something that should be nearby without
 | ||||
|     // having to copy the whole file in at once.
 | ||||
|     Stream_Chunk chunk; | ||||
|     char chunk_space[(1 << 10)]; | ||||
|      | ||||
|     int result = 0; | ||||
|     int found_result = 0; | ||||
|      | ||||
|     int i = start_pos; | ||||
|     int still_looping = 1; | ||||
|     int nesting_counter = 0; | ||||
|     char at_cursor = 0; | ||||
|      | ||||
|     if (init_stream_chunk(&chunk, app, &buffer, i, chunk_space, sizeof(chunk_space))){ | ||||
|          | ||||
|         // NOTE(allen): This is important! The data array is a pointer that is adjusted
 | ||||
|         // so that indexing it with "i" will put it with the chunk that is actually loaded.
 | ||||
|         // If i goes below chunk.start or above chunk.end _that_ is an invalid access.
 | ||||
|         at_cursor = chunk.data[i]; | ||||
|         if (at_cursor == '{'){ | ||||
|             do{ | ||||
|                 for (++i; i < chunk.end; ++i){ | ||||
|                     at_cursor = chunk.data[i]; | ||||
|                     if (at_cursor == '{'){ | ||||
|                         ++nesting_counter; | ||||
|                     } | ||||
|                     else if (at_cursor == '}'){ | ||||
|                         if (nesting_counter == 0){ | ||||
|                             found_result = 1; | ||||
|                             result = i; | ||||
|                             goto finished; | ||||
|                         } | ||||
|                         else{ | ||||
|                             --nesting_counter; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 still_looping = forward_stream_chunk(&chunk); | ||||
|             } | ||||
|             while (still_looping); | ||||
|         } | ||||
|         else if (at_cursor == '}'){ | ||||
|             do{ | ||||
|                 for (--i; i >= chunk.start; --i){ | ||||
|                     at_cursor = chunk.data[i]; | ||||
|                     if (at_cursor == '}'){ | ||||
|                         ++nesting_counter; | ||||
|                     } | ||||
|                     else if (at_cursor == '{'){ | ||||
|                         if (nesting_counter == 0){ | ||||
|                             found_result = 1; | ||||
|                             result = i; | ||||
|                             goto finished; | ||||
|                         } | ||||
|                         else{ | ||||
|                             --nesting_counter; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 still_looping = backward_stream_chunk(&chunk); | ||||
|             } | ||||
|             while (still_looping); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     finished: | ||||
|     if (found_result){ | ||||
|         app->view_set_mark(app, &view, seek_pos(result)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CUSTOM_COMMAND_SIG(cursor_to_surrounding_scope){ | ||||
|     View_Summary view = app->get_active_view(app); | ||||
|     Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); | ||||
|      | ||||
|     int start_pos = view.cursor.pos - 1; | ||||
|      | ||||
|     Stream_Chunk chunk; | ||||
|     char chunk_space[(1 << 10)]; | ||||
|      | ||||
|     int result = 0; | ||||
|     int found_result = 0; | ||||
|      | ||||
|     int i = start_pos; | ||||
|     int still_looping = 1; | ||||
|     int nesting_counter = 0; | ||||
|     char at_cursor = 0; | ||||
|      | ||||
|     if (init_stream_chunk(&chunk, app, &buffer, i, chunk_space, sizeof(chunk_space))){ | ||||
|         do{ | ||||
|             for (; i >= chunk.start; --i){ | ||||
|                 at_cursor = chunk.data[i]; | ||||
|                 if (at_cursor == '}'){ | ||||
|                     ++nesting_counter; | ||||
|                 } | ||||
|                 else if (at_cursor == '{'){ | ||||
|                     if (nesting_counter == 0){ | ||||
|                         found_result = 1; | ||||
|                         result = i; | ||||
|                         goto finished; | ||||
|                     } | ||||
|                     else{ | ||||
|                         --nesting_counter; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             still_looping = backward_stream_chunk(&chunk); | ||||
|         } while(still_looping); | ||||
|     } | ||||
|      | ||||
|     finished: | ||||
|     if (found_result){ | ||||
|         app->view_set_cursor(app, &view, seek_pos(result), 0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // NOTE(allen): Incomplete
 | ||||
| #if 0 | ||||
| CUSTOM_COMMAND_SIG(complete_word){ | ||||
|     app->print_message(app, literal("complete_word\n")); | ||||
|      | ||||
|  | @ -44,7 +268,7 @@ CUSTOM_COMMAND_SIG(complete_word){ | |||
|     start = view.cursor.pos; | ||||
|      | ||||
|     String complete_string; | ||||
|     int size = (start - end); | ||||
|     int size = (end - start); | ||||
|     char complete_space[256]; | ||||
|      | ||||
|     if (size < sizeof(complete_space) - 1){ | ||||
|  | @ -54,11 +278,12 @@ CUSTOM_COMMAND_SIG(complete_word){ | |||
|         complete_string.str[size] = 0; | ||||
|          | ||||
|         // TODO(allen): Complete this when the heavy duty coroutine stuff
 | ||||
|         // and the hash table are available
 | ||||
|         // and the hash table are available.
 | ||||
|          | ||||
|         app->print_message(app, complete_string.str, complete_string.size); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| // TODO(allen): Query theme settings
 | ||||
| #if 0 | ||||
|  | @ -83,7 +308,8 @@ CUSTOM_COMMAND_SIG(save_theme_settings){ | |||
| 
 | ||||
| void experiment_extension(Bind_Helper *context){ | ||||
|     bind(context, 'k', MDFR_ALT, kill_rect); | ||||
|     bind(context, '+', MDFR_CTRL, complete_word); | ||||
|     bind(context, '/', MDFR_ALT, mark_matching_brace); | ||||
|     bind(context, '\'', MDFR_ALT, cursor_to_surrounding_scope); | ||||
| } | ||||
| 
 | ||||
| #include <stdio.h> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Allen Webster
						Allen Webster