eliminated null views (I think)
							parent
							
								
									80d34d26dd
								
							
						
					
					
						commit
						bbc737f7c5
					
				|  | @ -704,16 +704,10 @@ CUSTOM_COMMAND_SIG(write_and_auto_tab){ | |||
|     exec_command(app, cmdid_auto_tab_line_at_cursor); | ||||
| } | ||||
| 
 | ||||
| #include "custom_casey.cpp" | ||||
| 
 | ||||
| extern "C" GET_BINDING_DATA(get_bindings){ | ||||
|     Bind_Helper context_actual = begin_bind_helper(data, size); | ||||
|     Bind_Helper *context = &context_actual; | ||||
|      | ||||
| #if 1 | ||||
|     casey_get_bindings(context); | ||||
| #else | ||||
|      | ||||
|     // NOTE(allen|a3.1): Right now hooks have no loyalties to maps, all hooks are
 | ||||
|     // global and once set they always apply, regardless of what map is active.
 | ||||
|     set_hook(context, hook_start, my_start); | ||||
|  | @ -850,7 +844,6 @@ extern "C" GET_BINDING_DATA(get_bindings){ | |||
|     bind(context, ' ', MDFR_SHIFT, cmdid_write_character); | ||||
|      | ||||
|     end_map(context); | ||||
| #endif | ||||
|      | ||||
|     end_bind_helper(context); | ||||
|      | ||||
|  |  | |||
							
								
								
									
										433
									
								
								4ed.cpp
								
								
								
								
							
							
						
						
									
										433
									
								
								4ed.cpp
								
								
								
								
							|  | @ -945,6 +945,29 @@ COMMAND_DECL(interactive_open){ | |||
|     } | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| panel_make_empty(System_Functions *system, Exchange *exchange, | ||||
|     App_Vars *vars, Style *style, Panel *panel){ | ||||
|      | ||||
|     Mem_Options *mem = &vars->mem; | ||||
|     Live_Views *live_set = &vars->live_set; | ||||
|     Editing_Layout *layout = &vars->layout; | ||||
|      | ||||
|     View *new_view; | ||||
|     File_View *file_view; | ||||
|      | ||||
|     new_view = live_set_alloc_view(live_set, mem); | ||||
|     if (panel->view){ | ||||
|         view_replace_major(system, exchange, new_view, panel, live_set); | ||||
|     } | ||||
|     else{ | ||||
|         view_set_first(new_view, panel); | ||||
|     } | ||||
|     file_view = file_view_init(new_view, layout); | ||||
|     view_set_file(file_view, 0, vars->font_set, style, 0, 0, 0); | ||||
|     new_view->map = app_get_map(vars, mapid_global); | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| view_file_in_panel(Command_Data *cmd, Panel *panel, Editing_File *file){ | ||||
|     Live_Views *live_set = cmd->live_set; | ||||
|  | @ -955,20 +978,25 @@ view_file_in_panel(Command_Data *cmd, Panel *panel, Editing_File *file){ | |||
|     App_Vars *vars = cmd->vars; | ||||
|     Style *style = cmd->style; | ||||
|      | ||||
|     View *new_view = live_set_alloc_view(live_set, mem); | ||||
|     Partition old_part; | ||||
|     Temp_Memory temp; | ||||
|     View *new_view, *old_view; | ||||
|     File_View *file_view; | ||||
|      | ||||
|     new_view = live_set_alloc_view(live_set, mem); | ||||
|     view_replace_major(system, exchange, new_view, panel, live_set); | ||||
| 
 | ||||
|     File_View *file_view = file_view_init(new_view, layout); | ||||
|     file_view = file_view_init(new_view, layout); | ||||
| 
 | ||||
|     View *old_view = cmd->view; | ||||
|     old_view = cmd->view; | ||||
|     cmd->view = new_view; | ||||
| 
 | ||||
|     Partition old_part = cmd->part; | ||||
|     Temp_Memory temp = begin_temp_memory(&mem->part); | ||||
|     old_part = cmd->part; | ||||
|     temp = begin_temp_memory(&mem->part); | ||||
|     cmd->part = partition_sub_part(&mem->part, Kbytes(16)); | ||||
| 
 | ||||
|     view_set_file(system, file_view, file, vars->font_set, | ||||
|         style, vars->hooks[hook_open_file], cmd, &app_links); | ||||
|     view_set_file(file_view, file, vars->font_set, style, | ||||
|         system, vars->hooks[hook_open_file], &app_links); | ||||
| 
 | ||||
|     cmd->part = old_part; | ||||
|     end_temp_memory(temp); | ||||
|  | @ -997,8 +1025,8 @@ COMMAND_DECL(reopen){ | |||
|         index = working_set_get_index(working_set, file); | ||||
|         app_push_file_binding(vars, file_id, index); | ||||
| 
 | ||||
|         view_set_file(system, view, file, vars->font_set, style, | ||||
|             vars->hooks[hook_open_file], command, &app_links); | ||||
|         view_set_file(view, file, vars->font_set, style, | ||||
|             system, vars->hooks[hook_open_file], &app_links); | ||||
|     } | ||||
|     else{ | ||||
|         // TODO(allen): feedback message
 | ||||
|  | @ -1352,9 +1380,11 @@ COMMAND_DECL(open_panel_vsplit){ | |||
|     ProfileMomentFunction(); | ||||
|     USE_LAYOUT(layout); | ||||
|     USE_PANEL(panel); | ||||
|     USE_EXCHANGE(exchange); | ||||
|     USE_VARS(vars); | ||||
|     USE_STYLE(style); | ||||
| 
 | ||||
|     i32 panel_count = layout->panel_count; | ||||
|     if (panel_count < layout->panel_max_count){ | ||||
|     if (layout->panel_count < layout->panel_max_count){ | ||||
|         Split_Result split = layout_split_panel(layout, panel, 1); | ||||
| 
 | ||||
|         Panel *panel1 = panel; | ||||
|  | @ -1371,6 +1401,7 @@ COMMAND_DECL(open_panel_vsplit){ | |||
|         panel2->prev_inner = panel2->inner; | ||||
| 
 | ||||
|         layout->active_panel = (i32)(panel2 - layout->panels); | ||||
|         panel_make_empty(system, exchange, vars, style, panel2); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1378,9 +1409,11 @@ COMMAND_DECL(open_panel_hsplit){ | |||
|     ProfileMomentFunction(); | ||||
|     USE_LAYOUT(layout); | ||||
|     USE_PANEL(panel); | ||||
|     USE_EXCHANGE(exchange); | ||||
|     USE_VARS(vars); | ||||
|     USE_STYLE(style); | ||||
| 
 | ||||
|     i32 panel_count = layout->panel_count; | ||||
|     if (panel_count < layout->panel_max_count){ | ||||
|     if (layout->panel_count < layout->panel_max_count){ | ||||
|         Split_Result split = layout_split_panel(layout, panel, 0); | ||||
| 
 | ||||
|         Panel *panel1 = panel; | ||||
|  | @ -1397,6 +1430,7 @@ COMMAND_DECL(open_panel_hsplit){ | |||
|         panel2->prev_inner = panel2->inner; | ||||
| 
 | ||||
|         layout->active_panel = (i32)(panel2 - layout->panels); | ||||
|         panel_make_empty(system, exchange, vars, style, panel2); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1868,15 +1902,6 @@ build(System_Functions *system, Mem_Options *mem, | |||
|             table_add(&working_set->table, file->name.source_path, index); | ||||
| 
 | ||||
|             if (bind_to_new_view){ | ||||
| #if 0 | ||||
|                 View *new_view = live_set_alloc_view(live_set, mem); | ||||
|                 view_replace_major(system, exchange, new_view, panel, live_set); | ||||
| 
 | ||||
|                 File_View *file_view = file_view_init(new_view, layout); | ||||
|                 view_set_file(system, file_view, file, font_set, style, | ||||
|                     vars->hooks[hook_open_file], command, &app_links); | ||||
|                 new_view->map = app_get_map(vars, file->settings.base_map_id); | ||||
| #endif | ||||
|                 view_file_in_panel(command, panel, file); | ||||
|             } | ||||
| 
 | ||||
|  | @ -2429,8 +2454,8 @@ extern "C"{ | |||
|                 if (buffer_id >= 0 && buffer_id < max){ | ||||
|                     file = working_set->files + buffer_id; | ||||
|                     if (!file->state.is_dummy){ | ||||
|                         view_set_file(cmd->system, file_view, file, cmd->vars->font_set, cmd->style, | ||||
|                             cmd->vars->hooks[hook_open_file], cmd, &app_links); | ||||
|                         view_set_file(file_view, file, cmd->vars->font_set, cmd->style, | ||||
|                             cmd->system, cmd->vars->hooks[hook_open_file], &app_links); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|  | @ -3076,75 +3101,78 @@ App_Init_Sig(app_init){ | |||
| 
 | ||||
|     Partition *partition = &vars->mem.part; | ||||
|     target->partition = partition; | ||||
| 
 | ||||
|     i32 panel_max_count = vars->layout.panel_max_count = 16; | ||||
|     i32 divider_max_count = panel_max_count - 1; | ||||
|      | ||||
|     Panel *panels; | ||||
|     Panel_Divider *dividers, *div; | ||||
|     i32 panel_max_count; | ||||
|     i32 divider_max_count; | ||||
|      | ||||
|     panel_max_count = vars->layout.panel_max_count = 16; | ||||
|     divider_max_count = panel_max_count - 1; | ||||
|     vars->layout.panel_count = 1; | ||||
| 
 | ||||
|     Panel *panels = vars->layout.panels = | ||||
|         push_array(partition, Panel, panel_max_count); | ||||
| 
 | ||||
|     Panel_Divider *dividers = vars->layout.dividers = | ||||
|         push_array(partition, Panel_Divider, divider_max_count); | ||||
| 
 | ||||
|     Panel_Divider *divider = dividers; | ||||
|     for (i32 i = 0; i < divider_max_count-1; ++i, ++divider){ | ||||
|         divider->next_free = (divider + 1); | ||||
|      | ||||
|     panels = push_array(partition, Panel, panel_max_count); | ||||
|     vars->layout.panels = panels; | ||||
|      | ||||
|     dividers = push_array(partition, Panel_Divider, divider_max_count); | ||||
|     vars->layout.dividers = dividers; | ||||
|      | ||||
|     div = dividers; | ||||
|     for (i32 i = 0; i < divider_max_count-1; ++i, ++div){ | ||||
|         div->next = (div + 1); | ||||
|     } | ||||
|     divider->next_free = 0; | ||||
|     div->next = 0; | ||||
|     vars->layout.free_divider = dividers; | ||||
| 
 | ||||
|     vars->live_set.count = 0; | ||||
|     vars->live_set.max = 1 + 2*panel_max_count; | ||||
|      | ||||
|     i32 view_chunk_size = 0; | ||||
|     i32 view_sizes[] = { | ||||
|         sizeof(File_View), | ||||
|         sizeof(Color_View), | ||||
|         sizeof(Interactive_View), | ||||
|         sizeof(Menu_View), | ||||
| #if FRED_INTERNAL | ||||
|         sizeof(Config_View), | ||||
|         sizeof(Debug_View), | ||||
| #endif | ||||
|     }; | ||||
| 
 | ||||
|     i32 view_chunk_size = 0; | ||||
|     for (i32 i = 0; i < ArrayCount(view_sizes); ++i){ | ||||
|         view_chunk_size = Max(view_chunk_size, view_sizes[i]); | ||||
|     } | ||||
|     vars->live_set.stride = view_chunk_size; | ||||
|     vars->live_set.views = (File_View*) | ||||
|         push_block(partition, view_chunk_size*vars->live_set.max); | ||||
| 
 | ||||
|     char *views_ = (char*)vars->live_set.views; | ||||
|     for (i32 i = panel_max_count-2; i >= 0; --i){ | ||||
|         View *view = (View*)(views_ + i*view_chunk_size); | ||||
|         View *view_next = (View*)((char*)view + view_chunk_size); | ||||
|         view->next_free = view_next; | ||||
|     } | ||||
|     { | ||||
|         View *view = (View*)(views_ + (panel_max_count-1)*view_chunk_size); | ||||
|         view->next_free = 0; | ||||
|         char *vptr = 0; | ||||
|         View *v = 0, *n = 0; | ||||
|         i32 i = 0, max = 0; | ||||
|          | ||||
|         vars->live_set.count = 0; | ||||
|         vars->live_set.max = 1 + 2*panel_max_count; | ||||
| 
 | ||||
|         for (i = 0; i < ArrayCount(view_sizes); ++i){ | ||||
|             view_chunk_size = Max(view_chunk_size, view_sizes[i]); | ||||
|         } | ||||
|         vars->live_set.stride = view_chunk_size; | ||||
|         vars->live_set.views = push_block(partition, view_chunk_size*vars->live_set.max); | ||||
|          | ||||
|         max = vars->live_set.max; | ||||
|         vptr = (char*)vars->live_set.views; | ||||
|         vars->live_set.free_view = (View*)vptr; | ||||
|         for (i = 0; i < max; ++i){ | ||||
|             v = (View*)(vptr); | ||||
|             n = (View*)(vptr + view_chunk_size); | ||||
|             v->next_free = n; | ||||
|             vptr = (char*)n; | ||||
|         } | ||||
|         v->next_free = 0; | ||||
|     } | ||||
|     vars->live_set.free_view = (View*)views_; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     setup_command_table(); | ||||
| 
 | ||||
|      | ||||
|     Command_Map *global = &vars->map_top; | ||||
|     Assert(vars->config_api.get_bindings != 0); | ||||
| 
 | ||||
|     i32 size = partition_remaining(partition); | ||||
|     void *data = partition_current(partition); | ||||
| 
 | ||||
|     // TODO(allen): Use a giant bubble of general memory for this.
 | ||||
|         // So that it doesn't interfere with the command maps as they allocate
 | ||||
|         // their own memory.
 | ||||
|     i32 wanted_size = vars->config_api.get_bindings(data, size); | ||||
|      | ||||
|     i32 wanted_size = vars->config_api.get_bindings(app_links.memory, app_links.memory_size); | ||||
| 
 | ||||
|     b32 did_top = 0; | ||||
|     b32 did_file = 0; | ||||
|     if (wanted_size <= size){ | ||||
|         partition_allocate(partition, wanted_size); | ||||
| 
 | ||||
|         Binding_Unit *unit = (Binding_Unit*)data; | ||||
|     if (wanted_size <= app_links.memory_size){ | ||||
|         Binding_Unit *unit = (Binding_Unit*)app_links.memory; | ||||
|         if (unit->type == unit_header && unit->header.error == 0){ | ||||
|             Binding_Unit *end = unit + unit->header.total_size; | ||||
| 
 | ||||
|  | @ -3242,11 +3270,12 @@ App_Init_Sig(app_init){ | |||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     memset(app_links.memory, 0, wanted_size); | ||||
|     if (!did_top) setup_top_commands(&vars->map_top, &vars->mem.part, global); | ||||
|     if (!did_file) setup_file_commands(&vars->map_file, &vars->mem.part, global); | ||||
| 
 | ||||
| #if !defined(FRED_SUPER) | ||||
| #if 1 || !defined(FRED_SUPER) | ||||
|     vars->hooks[hook_start] = 0; | ||||
| #endif | ||||
| 
 | ||||
|  | @ -3348,7 +3377,9 @@ App_Init_Sig(app_init){ | |||
|     vars->palette_size = 40; | ||||
|     vars->palette = push_array(partition, u32, vars->palette_size); | ||||
| 
 | ||||
|     // NOTE(allen): init first panel
 | ||||
|     panel_init(&panels[0]); | ||||
|     panel_make_empty(system, exchange, vars, &vars->style, &panels[0]); | ||||
| 
 | ||||
|     String hdbase = make_fixed_width_string(vars->hot_dir_base_); | ||||
|     hot_directory_init(&vars->hot_directory, hdbase, current_directory, system->slash); | ||||
|  | @ -3475,33 +3506,38 @@ App_Step_Sig(app_step){ | |||
|         vars->cli_processes.count = count; | ||||
|         end_temp_memory(temp); | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     // NOTE(allen): reorganizing panels on screen
 | ||||
|     i32 prev_width = vars->layout.full_width; | ||||
|     i32 prev_height = vars->layout.full_height; | ||||
|     i32 prev_y_off = 0; | ||||
|     i32 prev_x_off = 0; | ||||
| 
 | ||||
|     i32 y_off = 0; | ||||
|     i32 x_off = 0; | ||||
|     i32 full_width = vars->layout.full_width = target->width; | ||||
|     i32 full_height = vars->layout.full_height = target->height; | ||||
| 
 | ||||
|     if (prev_width != full_width || prev_height != full_height || | ||||
|             prev_x_off != x_off || prev_y_off != y_off){ | ||||
|         layout_refit(&vars->layout, prev_x_off, prev_y_off, prev_width, prev_height); | ||||
|         int view_count = vars->layout.panel_max_count; | ||||
|         for (i32 view_i = 0; view_i < view_count; ++view_i){ | ||||
|             View *view_ = live_set_get_view(&vars->live_set, view_i); | ||||
|             if (!view_->is_active) continue; | ||||
|             File_View *view = view_to_file_view(view_); | ||||
|             if (!view) continue; | ||||
|             view_measure_wraps(system, &vars->mem.general, view); | ||||
|             view->cursor = view_compute_cursor_from_pos(view, view->cursor.pos); | ||||
|     { | ||||
|         i32 prev_width = vars->layout.full_width; | ||||
|         i32 prev_height = vars->layout.full_height; | ||||
|         i32 current_width = target->width; | ||||
|         i32 current_height = target->height; | ||||
|          | ||||
|         View *view; | ||||
|         File_View *fview; | ||||
|         i32 i, view_count; | ||||
|          | ||||
|         vars->layout.full_width = current_width; | ||||
|         vars->layout.full_height = current_height; | ||||
|          | ||||
|         view_count = vars->layout.panel_max_count; | ||||
|          | ||||
|         if (prev_width != current_width || prev_height != current_height){ | ||||
|             layout_refit(&vars->layout, prev_width, prev_height); | ||||
|             for (i = 0; i < view_count; ++i){ | ||||
|                 view = live_set_get_view(&vars->live_set, i); | ||||
|                 if (!view->is_active) continue; | ||||
|                 fview = view_to_file_view(view); | ||||
|                 if (!fview) continue; | ||||
|                 // TODO(allen): All responses to a panel changing size should
 | ||||
|                 // be handled in the same place.
 | ||||
|                 view_change_size(system, &vars->mem.general, fview); | ||||
|             } | ||||
|             app_result.redraw = 1; | ||||
|         } | ||||
|         app_result.redraw = 1; | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     // NOTE(allen): prepare input information
 | ||||
|     Key_Summary key_data = {}; | ||||
|     for (i32 i = 0; i < input->press_count; ++i){ | ||||
|  | @ -3510,11 +3546,24 @@ App_Step_Sig(app_step){ | |||
|     for (i32 i = 0; i < input->hold_count; ++i){ | ||||
|         key_data.keys[key_data.count++] = input->hold[i]; | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     mouse->wheel = -mouse->wheel; | ||||
| 
 | ||||
|      | ||||
|     ProfileEnd(OS_syncing); | ||||
| 
 | ||||
|      | ||||
|     // NOTE(allen): while I transition away from this view system to something that has
 | ||||
|     // more unified behavior, I will use this to add checks to the program's state so that I
 | ||||
|     // can make sure it behaving well.
 | ||||
|     ProfileStart(correctness_checks); | ||||
|     { | ||||
|         Panel *panel = panels; | ||||
|         i32 panel_count = vars->layout.panel_count; | ||||
|         for (i32 i = 0; i < panel_count; ++i, ++panel){ | ||||
|             Assert(panel->view); | ||||
|         } | ||||
|     } | ||||
|     ProfileEnd(correctness_checks); | ||||
|      | ||||
|     ProfileStart(hover_status); | ||||
|     // NOTE(allen): detect mouse hover status
 | ||||
|     i32 mx = mouse->x; | ||||
|  | @ -4010,90 +4059,95 @@ App_Step_Sig(app_step){ | |||
|      | ||||
|     // NOTE(allen): processing sys app bindings
 | ||||
|     ProfileStart(sys_app_bind_processing); | ||||
|     for (i32 i = 0; i < vars->sys_app_count; ++i){ | ||||
|         Sys_App_Binding *binding; | ||||
|         b32 remove = 0; | ||||
|         b32 failed = 0; | ||||
|         binding = vars->sys_app_bindings + i; | ||||
|     { | ||||
|         Mem_Options *mem = &vars->mem; | ||||
|         General_Memory *general = &mem->general; | ||||
|          | ||||
|         for (i32 i = 0; i < vars->sys_app_count; ++i){ | ||||
|             Sys_App_Binding *binding; | ||||
|             b32 remove = 0; | ||||
|             b32 failed = 0; | ||||
|             binding = vars->sys_app_bindings + i; | ||||
| 
 | ||||
|         byte *data; | ||||
|         i32 size, max; | ||||
|         Editing_File *ed_file; | ||||
|         Editing_File_Preload preload_settings; | ||||
|         char *filename; | ||||
|             byte *data; | ||||
|             i32 size, max; | ||||
|             Editing_File *ed_file; | ||||
|             Editing_File_Preload preload_settings; | ||||
|             char *filename; | ||||
| 
 | ||||
|         Working_Set *working_set = &vars->working_set; | ||||
|             Working_Set *working_set = &vars->working_set; | ||||
| 
 | ||||
|         if (exchange_file_ready(exchange, binding->sys_id, &data, &size, &max)){ | ||||
|             ed_file = working_set->files + binding->app_id; | ||||
|             filename = exchange_file_filename(exchange, binding->sys_id); | ||||
|             preload_settings = ed_file->preload; | ||||
|             if (data){ | ||||
|                 String val = make_string((char*)data, size); | ||||
|                 file_create_from_string(system, &vars->mem, working_set, ed_file, filename, | ||||
|                     vars->font_set, vars->style.font_id, val); | ||||
|             if (exchange_file_ready(exchange, binding->sys_id, &data, &size, &max)){ | ||||
|                 ed_file = working_set->files + binding->app_id; | ||||
|                 filename = exchange_file_filename(exchange, binding->sys_id); | ||||
|                 preload_settings = ed_file->preload; | ||||
|                 if (data){ | ||||
|                     String val = make_string((char*)data, size); | ||||
|                     file_create_from_string(system, mem, working_set, ed_file, filename, | ||||
|                         vars->font_set, vars->style.font_id, val); | ||||
| 
 | ||||
|                 if (ed_file->settings.tokens_exist){ | ||||
|                     file_first_lex_parallel(system, &vars->mem.general, ed_file); | ||||
|                 } | ||||
|                  | ||||
|                 if ((binding->success & SysAppCreateView) && binding->panel != 0){ | ||||
|                     view_file_in_panel(cmd, binding->panel, ed_file); | ||||
|                 } | ||||
|                  | ||||
|                 app_result.redraw = 1; | ||||
|             } | ||||
|             else{ | ||||
|                 if (binding->fail & SysAppCreateNewBuffer){ | ||||
|                     file_create_empty(system, &vars->mem, working_set, ed_file, filename, | ||||
|                         vars->font_set, vars->style.font_id); | ||||
|                     if (binding->fail & SysAppCreateView){ | ||||
|                     if (ed_file->settings.tokens_exist){ | ||||
|                         file_first_lex_parallel(system, general, ed_file); | ||||
|                     } | ||||
| 
 | ||||
|                     if ((binding->success & SysAppCreateView) && binding->panel != 0){ | ||||
|                         view_file_in_panel(cmd, binding->panel, ed_file); | ||||
|                     } | ||||
| 
 | ||||
|                     app_result.redraw = 1; | ||||
|                 } | ||||
|                 else{ | ||||
|                     table_remove(&vars->working_set.table, ed_file->name.source_path); | ||||
|                     file_get_dummy(ed_file); | ||||
|                     if (binding->fail & SysAppCreateNewBuffer){ | ||||
|                         file_create_empty(system, mem, working_set, ed_file, filename, | ||||
|                             vars->font_set, vars->style.font_id); | ||||
|                         if (binding->fail & SysAppCreateView){ | ||||
|                             view_file_in_panel(cmd, binding->panel, ed_file); | ||||
|                         } | ||||
|                     } | ||||
|                     else{ | ||||
|                         table_remove(&vars->working_set.table, ed_file->name.source_path); | ||||
|                         file_get_dummy(ed_file); | ||||
|                     } | ||||
| 
 | ||||
|                     app_result.redraw = 1; | ||||
|                 } | ||||
|                  | ||||
|                 app_result.redraw = 1; | ||||
|             } | ||||
|              | ||||
|             if (!ed_file->state.is_dummy){ | ||||
|                 for (File_View_Iter iter = file_view_iter_init(&vars->layout, ed_file, 0); | ||||
|                     file_view_iter_good(iter); | ||||
|                     iter = file_view_iter_next(iter)){ | ||||
|                     view_file_loaded_init(system, iter.view, 0); | ||||
|                     view_cursor_move(iter.view, preload_settings.start_line, 0); | ||||
| 
 | ||||
|                 if (!ed_file->state.is_dummy){ | ||||
|                     for (File_View_Iter iter = file_view_iter_init(&vars->layout, ed_file, 0); | ||||
|                         file_view_iter_good(iter); | ||||
|                         iter = file_view_iter_next(iter)){ | ||||
|                         view_measure_wraps(system, general, iter.view); | ||||
|                         view_cursor_move(iter.view, preload_settings.start_line, 0); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 exchange_free_file(exchange, binding->sys_id); | ||||
|                 remove = 1; | ||||
|             } | ||||
|              | ||||
|             exchange_free_file(exchange, binding->sys_id); | ||||
|             remove = 1; | ||||
|         } | ||||
|          | ||||
|         if (exchange_file_save_complete(exchange, binding->sys_id, &data, &size, &max, &failed)){ | ||||
|             Assert(remove == 0); | ||||
|              | ||||
|             if (data){ | ||||
|                 general_memory_free(&vars->mem.general, data); | ||||
|                 exchange_clear_file(exchange, binding->sys_id); | ||||
| 
 | ||||
|             if (exchange_file_save_complete(exchange, binding->sys_id, &data, &size, &max, &failed)){ | ||||
|                 Assert(remove == 0); | ||||
| 
 | ||||
|                 if (data){ | ||||
|                     general_memory_free(general, data); | ||||
|                     exchange_clear_file(exchange, binding->sys_id); | ||||
|                 } | ||||
| 
 | ||||
|                 Editing_File *file = get_file(working_set, binding->app_id); | ||||
|                 if (file){ | ||||
|                     file_synchronize_times(system, file, file->name.source_path.str); | ||||
|                 } | ||||
| 
 | ||||
|                 exchange_free_file(exchange, binding->sys_id); | ||||
|                 remove = 1; | ||||
| 
 | ||||
|                 // if (failed) { TODO(allen): saving error, now what? }
 | ||||
|             } | ||||
|              | ||||
|             Editing_File *file = get_file(working_set, binding->app_id); | ||||
|             if (file){ | ||||
|                 file_synchronize_times(system, file, file->name.source_path.str); | ||||
| 
 | ||||
|             if (remove){ | ||||
|                 *binding = vars->sys_app_bindings[--vars->sys_app_count]; | ||||
|                 --i; | ||||
|             } | ||||
|              | ||||
|             exchange_free_file(exchange, binding->sys_id); | ||||
|             remove = 1; | ||||
|              | ||||
|             // if (failed) { TODO(allen): saving error, now what? }
 | ||||
|         } | ||||
|          | ||||
|         if (remove){ | ||||
|             *binding = vars->sys_app_bindings[--vars->sys_app_count]; | ||||
|             --i; | ||||
|         } | ||||
|     } | ||||
|     ProfileEnd(sys_app_bind_processing); | ||||
|  | @ -4173,8 +4227,8 @@ App_Step_Sig(app_step){ | |||
|                     // TODO(allen): deduplicate
 | ||||
|                     View *view = panel->view; | ||||
|                     File_View *fview = view_to_file_view(view); | ||||
|                     if (!fview && view->is_minor) fview = view_to_file_view(view->major); | ||||
|                     if (!file){ | ||||
|                         if (!fview && view->is_minor) fview = view_to_file_view(view->major); | ||||
|                         if (fview){ | ||||
|                             file = working_set_lookup_file(working_set, string); | ||||
|                         } | ||||
|  | @ -4191,11 +4245,11 @@ App_Step_Sig(app_step){ | |||
| 
 | ||||
|                 case DACT_SAVE_AS: | ||||
|                 { | ||||
|                     // TODO(allen): deduplicate
 | ||||
|                     // TODO(allen): deduplicate 
 | ||||
|                     View *view = panel->view; | ||||
|                     File_View *fview = view_to_file_view(view); | ||||
|                     if (!fview && view->is_minor) fview = view_to_file_view(view->major); | ||||
|                     if (!file){ | ||||
|                         if (!fview && view->is_minor) fview = view_to_file_view(view->major); | ||||
|                         if (fview){ | ||||
|                             file = working_set_lookup_file(working_set, string); | ||||
|                         } | ||||
|  | @ -4215,8 +4269,12 @@ App_Step_Sig(app_step){ | |||
|                 { | ||||
|                     if (!file){ | ||||
|                         if (panel){ | ||||
|                             View *view = panel->view; | ||||
|                             File_View *fview = view_to_file_view(view); | ||||
|                             View *view; | ||||
|                             File_View *fview; | ||||
|                             view = panel->view; | ||||
|                             Assert(view); | ||||
|                             if (view->is_minor) view = view->major; | ||||
|                             fview = view_to_file_view(view); | ||||
|                             if (fview){ | ||||
|                                 file = fview->file; | ||||
|                             } | ||||
|  | @ -4225,9 +4283,13 @@ App_Step_Sig(app_step){ | |||
|                             file = working_set_lookup_file(working_set, string); | ||||
|                         } | ||||
|                     } | ||||
|                     if (!file->state.is_dummy && buffer_needs_save(file)){ | ||||
|                     // TODO(allen): We could handle the case where someone tries to save the same thing
 | ||||
|                     // twice... that would be nice to have under control.
 | ||||
|                     if (file && !file->state.is_dummy && buffer_needs_save(file)){ | ||||
|                         i32 sys_id = file_save(system, exchange, mem, file, file->name.source_path.str); | ||||
|                         if (sys_id){ | ||||
|                             // TODO(allen): This is fishy! Shouldn't we bind it to a file name instead? This file
 | ||||
|                             // might be killed before we get notified that the saving is done!
 | ||||
|                             app_push_file_binding(vars, sys_id, get_file_id(working_set, file)); | ||||
|                         } | ||||
|                         else{ | ||||
|  | @ -4248,8 +4310,8 @@ App_Step_Sig(app_step){ | |||
| 
 | ||||
|                     File_View *file_view = file_view_init(new_view, &vars->layout); | ||||
|                     cmd->view = (View*)file_view; | ||||
|                     view_set_file(system, file_view, file.file, vars->font_set, style, | ||||
|                         vars->hooks[hook_open_file], cmd, &app_links); | ||||
|                     view_set_file(file_view, file.file, vars->font_set, style, | ||||
|                         system,  vars->hooks[hook_open_file], &app_links); | ||||
|                     new_view->map = app_get_map(vars, file.file->settings.base_map_id); | ||||
| #if BUFFER_EXPERIMENT_SCALPEL <= 0 | ||||
|                     if (file.file->settings.tokens_exist) | ||||
|  | @ -4267,8 +4329,8 @@ App_Step_Sig(app_step){ | |||
|                         File_View *file_view = file_view_init(new_view, &vars->layout); | ||||
|                         cmd->view = (View*)file_view; | ||||
| 
 | ||||
|                         view_set_file(system, file_view, file, vars->font_set, style, | ||||
|                             vars->hooks[hook_open_file], cmd, &app_links); | ||||
|                         view_set_file(file_view, file, vars->font_set, style, | ||||
|                             system, vars->hooks[hook_open_file], &app_links); | ||||
| 
 | ||||
|                         new_view->map = app_get_map(vars, file->settings.base_map_id); | ||||
|                     } | ||||
|  | @ -4313,11 +4375,6 @@ App_Step_Sig(app_step){ | |||
|                     view_remove_minor(system, exchange, panel, live_set); | ||||
|                 }break; | ||||
| 
 | ||||
|                 case DACT_CLOSE_MAJOR: | ||||
|                 { | ||||
|                     view_remove_major(system, exchange, panel, live_set); | ||||
|                 }break; | ||||
| 
 | ||||
|                 case DACT_THEME_OPTIONS: | ||||
|                 { | ||||
|                     open_theme_options(system, exchange, vars, live_set, mem, panel); | ||||
|  |  | |||
|  | @ -9,7 +9,6 @@ enum Action_Type{ | |||
|     DACT_TRY_KILL, | ||||
|     DACT_KILL, | ||||
|     DACT_CLOSE_MINOR, | ||||
|     DACT_CLOSE_MAJOR, | ||||
|     DACT_THEME_OPTIONS, | ||||
|     DACT_KEYBOARD_OPTIONS, | ||||
| }; | ||||
|  | @ -115,6 +114,5 @@ delayed_action_repush(Delay *delay, Delayed_Action *act){ | |||
| #define delayed_try_kill(delay, ...) delayed_action_(delay, DACT_TRY_KILL, __VA_ARGS__) | ||||
| #define delayed_kill(delay, ...) delayed_action_(delay, DACT_KILL, __VA_ARGS__) | ||||
| #define delayed_close_minor(delay, ...) delayed_action_(delay, DACT_CLOSE_MINOR, __VA_ARGS__) | ||||
| #define delayed_close_major(delay, ...) delayed_action_(delay, DACT_CLOSE_MAJOR, __VA_ARGS__) | ||||
| #define delayed_theme_options(delay, ...) delayed_action_(delay, DACT_THEME_OPTIONS, __VA_ARGS__) | ||||
| #define delayed_keyboard_options(delay, ...) delayed_action_(delay, DACT_KEYBOARD_OPTIONS, __VA_ARGS__) | ||||
|  |  | |||
|  | @ -45,13 +45,6 @@ enum Link_Type{ | |||
|     link_type_count | ||||
| }; | ||||
| 
 | ||||
| struct Hyper_Link{ | ||||
|     char *file_name; | ||||
|     i32 line_number; | ||||
|     i32 start, end; | ||||
|     Link_Type link_type; | ||||
| }; | ||||
| 
 | ||||
| struct File_View{ | ||||
|     View view_base; | ||||
| 
 | ||||
|  | @ -94,9 +87,6 @@ struct File_View{ | |||
|      | ||||
|     i32 line_count, line_max; | ||||
|     f32 *line_wrap_y; | ||||
|      | ||||
|     Hyper_Link *links; | ||||
|     i32 link_count, link_max; | ||||
| }; | ||||
| 
 | ||||
| inline File_View* | ||||
|  | @ -1311,67 +1301,87 @@ view_get_cursor_y(File_View *view){ | |||
| } | ||||
| 
 | ||||
| internal void | ||||
| view_file_loaded_init(System_Functions *system, File_View *view, i32 cursor_pos){ | ||||
|     General_Memory *general = &view->view_base.mem->general; | ||||
| view_set_file( | ||||
|     // NOTE(allen): These parameters are always meaningful
 | ||||
|     File_View *view, | ||||
|     Editing_File *file, | ||||
|     Font_Set *set, | ||||
|     Style *style, | ||||
|      | ||||
|     view_measure_wraps(system, general, view); | ||||
|     view->cursor = view_compute_cursor_from_pos(view, cursor_pos); | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| view_set_file(System_Functions *system, File_View *view, | ||||
|               Editing_File *file, Font_Set *set, Style *style, | ||||
|               Hook_Function *open_hook, void *cmd_context, Application_Links *app){ | ||||
|     Panel *panel = view->view_base.panel; | ||||
|     view->file = file; | ||||
|     view->locked = file->settings.super_locked; | ||||
| 
 | ||||
|     Font_Info *info = get_font_info(set, style->font_id); | ||||
|     // NOTE(allen): Necessary when file != 0
 | ||||
|     System_Functions *system, | ||||
|     Hook_Function *open_hook, | ||||
|     Application_Links *app){ | ||||
|      | ||||
|     Panel *panel; | ||||
|     Font_Info *fnt_info; | ||||
|      | ||||
|     f32 w, h; | ||||
|     f32 cursor_x, cursor_y; | ||||
|     f32 target_x, target_y; | ||||
|                | ||||
|     panel = view->view_base.panel; | ||||
|      | ||||
|     // NOTE(allen): This is actually more like view_set_style right?
 | ||||
|     fnt_info = get_font_info(set, style->font_id); | ||||
|     view->style = style; | ||||
|     view->font_advance = info->advance; | ||||
|     view->font_height = info->height; | ||||
|     view->font_advance = fnt_info->advance; | ||||
|     view->font_height = fnt_info->height; | ||||
|     view->font_set = set; | ||||
|     view->unwrapped_lines = file->settings.unwrapped_lines; | ||||
|     file->settings.set = set; | ||||
| 
 | ||||
|     // NOTE(allen): Stuff that doesn't assume file exists.
 | ||||
|     view->file = file; | ||||
|      | ||||
|     view->cursor = {}; | ||||
|      | ||||
|     if (!file->state.is_loading){ | ||||
|         view_file_loaded_init(system, view, file->state.cursor_pos); | ||||
|     } | ||||
|      | ||||
|     f32 cursor_x, cursor_y; | ||||
|     f32 w, h; | ||||
|     f32 target_x, target_y; | ||||
|      | ||||
|     cursor_x = view_get_cursor_x(view); | ||||
|     cursor_y = view_get_cursor_y(view); | ||||
|      | ||||
|     w = (f32)(panel->inner.x1 - panel->inner.x0); | ||||
|     h = (f32)(panel->inner.y1 - panel->inner.y0); | ||||
|     view->vel_y = 1.f; | ||||
|     view->vel_x = 1.f; | ||||
|      | ||||
|     target_x = 0; | ||||
|     if (cursor_x < target_x){ | ||||
|         target_x = (f32)Max(0, cursor_x - w*.5f); | ||||
|     } | ||||
|     else if (cursor_x >= target_x + w){ | ||||
|         target_x = (f32)(cursor_x - w*.5f); | ||||
|     target_y = 0; | ||||
|      | ||||
|     // NOTE(allen): Stuff that does assume file exists.
 | ||||
|      | ||||
|     if (file){ | ||||
|         // NOTE(allen): Isn't this a bit clumsy?
 | ||||
|         file->settings.set = set; | ||||
|          | ||||
|         view->locked = file->settings.super_locked; | ||||
|         view->unwrapped_lines = file->settings.unwrapped_lines; | ||||
|          | ||||
|         if (file_is_ready(file)){ | ||||
|             view_measure_wraps(system, &view->view_base.mem->general, view); | ||||
|             view->cursor = view_compute_cursor_from_pos(view, file->state.cursor_pos); | ||||
|              | ||||
|             cursor_x = view_get_cursor_x(view); | ||||
|             cursor_y = view_get_cursor_y(view); | ||||
|              | ||||
|             w = (f32)(panel->inner.x1 - panel->inner.x0); | ||||
|             h = (f32)(panel->inner.y1 - panel->inner.y0); | ||||
|              | ||||
|             Assert(cursor_x >= target_x); | ||||
|             if (cursor_x >= target_x + w){ | ||||
|                 target_x = (f32)(cursor_x - w*.5f); | ||||
|             } | ||||
| 
 | ||||
|             target_y = (f32)FLOOR32(cursor_y - h*.5f); | ||||
|             if (target_y < 0) target_y = 0; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     target_y = (f32)FLOOR32(cursor_y - h*.5f); | ||||
|     if (target_y < 0) target_y = 0; | ||||
|      | ||||
|     // NOTE(allen): More stuff that doesn't assume file exists, but that
 | ||||
|     // has to come after computing target_x, target_y
 | ||||
|     view->target_x = target_x; | ||||
|     view->target_y = target_y; | ||||
|     view->scroll_x = target_x; | ||||
|     view->scroll_y = target_y; | ||||
|      | ||||
|     view->vel_y = 1.f; | ||||
|     view->vel_x = 1.f; | ||||
| 
 | ||||
|     if (open_hook && file->settings.is_initialized == 0){ | ||||
|         open_hook(app); | ||||
|         file->settings.is_initialized = 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 (file){ | ||||
|         if (open_hook && file->settings.is_initialized == 0){ | ||||
|             open_hook(app); | ||||
|             file->settings.is_initialized = 1; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1461,11 +1471,11 @@ view_widget_height(File_View *view, i32 font_height){ | |||
| inline i32_Rect | ||||
| view_widget_rect(File_View *view, i32 font_height){ | ||||
|     Panel *panel = view->view_base.panel; | ||||
|     i32_Rect whole = panel->inner; | ||||
|     i32_Rect result; | ||||
|     result.x0 = whole.x0; | ||||
|     result.x1 = whole.x1; | ||||
|     result.y0 = whole.y0 + font_height + 2; | ||||
|     i32_Rect result = panel->inner; | ||||
|      | ||||
|     if (view->file){ | ||||
|         result.y0 = result.y0 + font_height + 2; | ||||
|     } | ||||
|     result.y1 = result.y0 + view_widget_height(view, font_height); | ||||
|      | ||||
|     return result; | ||||
|  | @ -1481,7 +1491,7 @@ debug_edit_step_check(Edit_Step a, Edit_Step b){ | |||
|     Assert(a.edit.start == b.edit.start); | ||||
|     Assert(a.edit.end == b.edit.end); | ||||
|     Assert(a.edit.len == b.edit.len); | ||||
|     return 1; | ||||
|     return(1); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
|  | @ -2587,13 +2597,6 @@ struct Get_Link_Result{ | |||
|     i32 index; | ||||
| }; | ||||
| 
 | ||||
| internal Get_Link_Result | ||||
| get_link(Hyper_Link *links, i32 link_count, i32 pos){ | ||||
|     Get_Link_Result result = {}; | ||||
|     // TODO TODO TODO TODO TODO TODO TODO TODO
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| internal u32* | ||||
| style_get_link_color(Style *style, Link_Type type){ | ||||
| 	u32 *result; | ||||
|  | @ -2728,6 +2731,66 @@ remeasure_file_view(System_Functions *system, View *view_, i32_Rect rect){ | |||
|     } | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| undo_shit(System_Functions *system, File_View *view, UI_State *state, UI_Layout *layout, | ||||
|     i32 total_count, i32 undo_count, i32 scrub_max){ | ||||
|      | ||||
|     View *view_ = (View*)view; | ||||
|     Editing_File *file = view->file; | ||||
|      | ||||
|     if (view->widget.timeline.undo_line){ | ||||
|         if (do_button(1, state, layout, "- Undo", 1)){ | ||||
|             view->widget.timeline.undo_line = 0; | ||||
|         } | ||||
| 
 | ||||
|         if (view->widget.timeline.undo_line){ | ||||
|             Widget_ID wid = make_id(state, 2); | ||||
|             i32 new_count; | ||||
|             if (do_undo_slider(wid, state, layout, total_count, undo_count, 0, &new_count)){ | ||||
|                 for (i32 i = 0; i < scrub_max && new_count < undo_count; ++i){ | ||||
|                     view_undo(system, view_->mem, view->layout, view); | ||||
|                     --undo_count; | ||||
|                 } | ||||
|                 for (i32 i = 0; i < scrub_max && new_count > undo_count; ++i){ | ||||
|                     view_redo(system, view_->mem, view->layout, view); | ||||
|                     ++undo_count; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else{ | ||||
|         if (do_button(1, state, layout, "+ Undo", 1)){ | ||||
|             view->widget.timeline.undo_line = 1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (view->widget.timeline.history_line){ | ||||
|         if (do_button(3, state, layout, "- History", 1)){ | ||||
|             view->widget.timeline.history_line = 0; | ||||
|         } | ||||
| 
 | ||||
|         Widget_ID wid = make_id(state, 4); | ||||
|         if (view->widget.timeline.history_line){ | ||||
|             i32 new_count; | ||||
|             i32 mid = ((file->state.undo.history.edit_count + file->state.undo.edit_history_cursor) >> 1); | ||||
|             i32 count = file->state.undo.edit_history_cursor; | ||||
|             if (do_undo_slider(wid, state, layout, mid, count, &file->state.undo, &new_count)){ | ||||
|                 for (i32 i = 0; i < scrub_max && new_count < count; ++i){ | ||||
|                     view_history_step(system, view_->mem, view->layout, view, hist_backward); | ||||
|                 } | ||||
|                 for (i32 i = 0; i < scrub_max && new_count > count; ++i){ | ||||
|                     view_history_step(system, view_->mem, view->layout, view, hist_forward); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else{ | ||||
|         if (do_button(3, state, layout, "+ History", 1)){ | ||||
|             view->widget.timeline.history_line = 1; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| internal i32 | ||||
| step_file_view(System_Functions *system, View *view_, i32_Rect rect, | ||||
|                b32 is_active, Input_Summary *user_input){ | ||||
|  | @ -2735,183 +2798,126 @@ step_file_view(System_Functions *system, View *view_, i32_Rect rect, | |||
|     i32 result = 0; | ||||
|     File_View *view = (File_View*)view_; | ||||
|     Editing_File *file = view->file; | ||||
|      | ||||
|     if (file && !file->state.is_loading){ | ||||
|         f32 line_height = (f32)view->font_height; | ||||
|         f32 cursor_y = view_get_cursor_y(view); | ||||
|         f32 target_y = view->target_y; | ||||
|         f32 max_y = view_compute_height(view) - line_height*2; | ||||
|         i32 lowest_line = view_compute_lowest_line(view); | ||||
|         f32 max_target_y = view_compute_max_target_y(lowest_line, (i32)line_height, max_y); | ||||
|         f32 delta_y = 3.f*line_height; | ||||
|         f32 extra_top = (f32)view_widget_height(view, (i32)line_height); | ||||
|         f32 taken_top_space = line_height + extra_top; | ||||
| 
 | ||||
|         if (user_input->mouse.y < rect.y0 + taken_top_space){ | ||||
|             view_->mouse_cursor_type = APP_MOUSE_CURSOR_ARROW; | ||||
|         } | ||||
|         else{ | ||||
|             view_->mouse_cursor_type = APP_MOUSE_CURSOR_IBEAM; | ||||
|         } | ||||
| 
 | ||||
|         if (user_input->mouse.wheel != 0){ | ||||
|             f32 wheel_multiplier = 3.f; | ||||
|             f32 delta_target_y = delta_y*user_input->mouse.wheel*wheel_multiplier; | ||||
|             target_y += delta_target_y; | ||||
| 
 | ||||
|             if (target_y < -taken_top_space) target_y = -taken_top_space; | ||||
|             if (target_y > max_target_y) target_y = max_target_y; | ||||
| 
 | ||||
|             real32 old_cursor_y = cursor_y; | ||||
|             if (cursor_y >= target_y + max_y) cursor_y = target_y + max_y; | ||||
|             if (cursor_y < target_y + taken_top_space) cursor_y = target_y + taken_top_space; | ||||
| 
 | ||||
|             if (cursor_y != old_cursor_y){ | ||||
|                 view->cursor = | ||||
|                     view_compute_cursor_from_xy(view, | ||||
|                     view->preferred_x, | ||||
|                     cursor_y); | ||||
|             } | ||||
| 
 | ||||
|             result = 1; | ||||
|         } | ||||
| 
 | ||||
|         if (cursor_y > target_y + max_y){ | ||||
|             target_y = cursor_y - max_y + delta_y; | ||||
|         } | ||||
|         if (cursor_y < target_y + taken_top_space){ | ||||
|             target_y = cursor_y - delta_y - taken_top_space; | ||||
|         } | ||||
| 
 | ||||
|     if (file->state.is_loading){ | ||||
|         return result; | ||||
|     } | ||||
|      | ||||
|     f32 line_height = (f32)view->font_height; | ||||
|     f32 cursor_y = view_get_cursor_y(view); | ||||
|     f32 target_y = view->target_y; | ||||
|     f32 max_y = view_compute_height(view) - line_height*2; | ||||
|     i32 lowest_line = view_compute_lowest_line(view); | ||||
|     f32 max_target_y = view_compute_max_target_y(lowest_line, (i32)line_height, max_y); | ||||
|     f32 delta_y = 3.f*line_height; | ||||
|     f32 extra_top = 0.f; | ||||
|     extra_top += view_widget_height(view, (i32)line_height); | ||||
|     f32 taken_top_space = line_height + extra_top; | ||||
|      | ||||
|     if (user_input->mouse.y < rect.y0 + taken_top_space){ | ||||
|         view_->mouse_cursor_type = APP_MOUSE_CURSOR_ARROW; | ||||
|     } | ||||
|     else{ | ||||
|         view_->mouse_cursor_type = APP_MOUSE_CURSOR_IBEAM; | ||||
|     } | ||||
|      | ||||
|     if (user_input->mouse.wheel != 0){ | ||||
|         f32 wheel_multiplier = 3.f; | ||||
|         f32 delta_target_y = delta_y*user_input->mouse.wheel*wheel_multiplier; | ||||
|         target_y += delta_target_y; | ||||
|          | ||||
|         if (target_y < -taken_top_space) target_y = -taken_top_space; | ||||
|         if (target_y > max_target_y) target_y = max_target_y; | ||||
|          | ||||
|         real32 old_cursor_y = cursor_y; | ||||
|         if (cursor_y >= target_y + max_y) cursor_y = target_y + max_y; | ||||
|         if (cursor_y < target_y + taken_top_space) cursor_y = target_y + taken_top_space; | ||||
|          | ||||
|         if (cursor_y != old_cursor_y){ | ||||
|             view->cursor = | ||||
|                 view_compute_cursor_from_xy(view, | ||||
|                                             view->preferred_x, | ||||
|                                             cursor_y); | ||||
|         } | ||||
|          | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     if (cursor_y > target_y + max_y){ | ||||
|         target_y = cursor_y - max_y + delta_y; | ||||
|     } | ||||
|     if (cursor_y < target_y + taken_top_space){ | ||||
|         target_y = cursor_y - delta_y - taken_top_space; | ||||
|     } | ||||
|      | ||||
|     if (target_y > max_target_y) target_y = max_target_y; | ||||
|     if (target_y < -extra_top) target_y = -extra_top; | ||||
|     view->target_y = target_y; | ||||
|      | ||||
|     f32 cursor_x = view_get_cursor_x(view); | ||||
|     f32 target_x = view->target_x; | ||||
|     f32 max_x = view_compute_width(view); | ||||
|     if (cursor_x < target_x){ | ||||
|         target_x = (f32)Max(0, cursor_x - max_x/2); | ||||
|     } | ||||
|     else if (cursor_x >= target_x + max_x){ | ||||
|         target_x = (f32)(cursor_x - max_x/2); | ||||
|     } | ||||
|      | ||||
|     view->target_x = target_x; | ||||
|      | ||||
|     if (smooth_camera_step(&view->target_y, &view->scroll_y, &view->vel_y, 40.f, 1.f/4.f)){ | ||||
|         result = 1; | ||||
|     } | ||||
|     if (smooth_camera_step(&view->target_x, &view->scroll_x, &view->vel_x, 40.f, 1.f/4.f)){ | ||||
|         result = 1; | ||||
|     } | ||||
|     if (file->state.paste_effect.tick_down > 0){ | ||||
|         --file->state.paste_effect.tick_down; | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     if (is_active && user_input->mouse.press_l){ | ||||
|         f32 max_y = view_compute_height(view); | ||||
|         f32 rx = (f32)(user_input->mouse.x - rect.x0); | ||||
|         f32 ry = (f32)(user_input->mouse.y - rect.y0 - line_height - 2); | ||||
|          | ||||
|         if (ry >= extra_top){ | ||||
|             view_set_widget(view, FWIDG_NONE); | ||||
|             if (rx >= 0 && rx < max_x && ry >= 0 && ry < max_y){ | ||||
|                 view_cursor_move(view, rx + view->scroll_x, ry + view->scroll_y, 1); | ||||
|                 view->mode = {}; | ||||
|             } | ||||
|         } | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     if (!is_active) view_set_widget(view, FWIDG_NONE); | ||||
|         if (target_y < -extra_top) target_y = -extra_top; | ||||
|         view->target_y = target_y; | ||||
| 
 | ||||
|     // NOTE(allen): framely undo stuff
 | ||||
|     if (file){ | ||||
|         f32 cursor_x = view_get_cursor_x(view); | ||||
|         f32 target_x = view->target_x; | ||||
|         f32 max_x = view_compute_width(view); | ||||
|         if (cursor_x < target_x){ | ||||
|             target_x = (f32)Max(0, cursor_x - max_x/2); | ||||
|         } | ||||
|         else if (cursor_x >= target_x + max_x){ | ||||
|             target_x = (f32)(cursor_x - max_x/2); | ||||
|         } | ||||
| 
 | ||||
|         view->target_x = target_x; | ||||
| 
 | ||||
|         if (smooth_camera_step(&view->target_y, &view->scroll_y, &view->vel_y, 40.f, 1.f/4.f)){ | ||||
|             result = 1; | ||||
|         } | ||||
|         if (smooth_camera_step(&view->target_x, &view->scroll_x, &view->vel_x, 40.f, 1.f/4.f)){ | ||||
|             result = 1; | ||||
|         } | ||||
|         if (file->state.paste_effect.tick_down > 0){ | ||||
|             --file->state.paste_effect.tick_down; | ||||
|             result = 1; | ||||
|         } | ||||
| 
 | ||||
|         if (is_active && user_input->mouse.press_l){ | ||||
|             f32 max_y = view_compute_height(view); | ||||
|             f32 rx = (f32)(user_input->mouse.x - rect.x0); | ||||
|             f32 ry = (f32)(user_input->mouse.y - rect.y0 - line_height - 2); | ||||
| 
 | ||||
|             if (ry >= extra_top){ | ||||
|                 view_set_widget(view, FWIDG_NONE); | ||||
|                 if (rx >= 0 && rx < max_x && ry >= 0 && ry < max_y){ | ||||
|                     view_cursor_move(view, rx + view->scroll_x, ry + view->scroll_y, 1); | ||||
|                     view->mode = {}; | ||||
|                 } | ||||
|             } | ||||
|             result = 1; | ||||
|         } | ||||
| 
 | ||||
|         if (!is_active) view_set_widget(view, FWIDG_NONE); | ||||
| 
 | ||||
|         // NOTE(allen): framely undo stuff
 | ||||
|         i32 scrub_max = view->scrub_max; | ||||
|         i32 undo_count, redo_count, total_count; | ||||
|         undo_count = file->state.undo.undo.edit_count; | ||||
|         redo_count = file->state.undo.redo.edit_count; | ||||
|         total_count = undo_count + redo_count; | ||||
| 
 | ||||
|         i32 undo_count = file->state.undo.undo.edit_count; | ||||
|         i32 redo_count = file->state.undo.redo.edit_count; | ||||
|         i32 total_count = undo_count + redo_count; | ||||
|          | ||||
|         switch (view->widget.type){ | ||||
|         case FWIDG_TIMELINES: | ||||
|         { | ||||
|             i32_Rect widg_rect = view_widget_rect(view, view->font_height); | ||||
|              | ||||
|             UI_State state =  | ||||
|                 ui_state_init(&view->widget.state, 0, user_input, | ||||
|                               view->style, view->font_set, 0, 1); | ||||
|              | ||||
|             UI_Layout layout; | ||||
|             begin_layout(&layout, widg_rect); | ||||
|              | ||||
|             if (view->widget.timeline.undo_line){ | ||||
|                 if (do_button(1, &state, &layout, "- Undo", 1)){ | ||||
|                     view->widget.timeline.undo_line = 0; | ||||
|                 } | ||||
|             case FWIDG_TIMELINES: | ||||
|             { | ||||
|                 i32_Rect widg_rect = view_widget_rect(view, view->font_height); | ||||
|                  | ||||
|                 if (view->widget.timeline.undo_line){ | ||||
|                     Widget_ID wid = make_id(&state, 2); | ||||
|                     i32 new_count; | ||||
|                     if (do_undo_slider(wid, &state, &layout, total_count, undo_count, 0, &new_count)){ | ||||
|                         for (i32 i = 0; i < scrub_max && new_count < undo_count; ++i){ | ||||
|                             view_undo(system, view_->mem, view->layout, view); | ||||
|                             --undo_count; | ||||
|                         } | ||||
|                         for (i32 i = 0; i < scrub_max && new_count > undo_count; ++i){ | ||||
|                             view_redo(system, view_->mem, view->layout, view); | ||||
|                             ++undo_count; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             else{ | ||||
|                 if (do_button(1, &state, &layout, "+ Undo", 1)){ | ||||
|                     view->widget.timeline.undo_line = 1; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             if (view->widget.timeline.history_line){ | ||||
|                 if (do_button(3, &state, &layout, "- History", 1)){ | ||||
|                     view->widget.timeline.history_line = 0; | ||||
|                 } | ||||
|                 UI_State state =  | ||||
|                     ui_state_init(&view->widget.state, 0, user_input, | ||||
|                     view->style, view->font_set, 0, 1); | ||||
|                  | ||||
|                 Widget_ID wid = make_id(&state, 4); | ||||
|                 if (view->widget.timeline.history_line){ | ||||
|                     i32 new_count; | ||||
|                     i32 mid = ((file->state.undo.history.edit_count + file->state.undo.edit_history_cursor) >> 1); | ||||
|                     i32 count = file->state.undo.edit_history_cursor; | ||||
|                     if (do_undo_slider(wid, &state, &layout, mid, count, &file->state.undo, &new_count)){ | ||||
|                         for (i32 i = 0; i < scrub_max && new_count < count; ++i){ | ||||
|                             view_history_step(system, view_->mem, view->layout, view, hist_backward); | ||||
|                         } | ||||
|                         for (i32 i = 0; i < scrub_max && new_count > count; ++i){ | ||||
|                             view_history_step(system, view_->mem, view->layout, view, hist_forward); | ||||
|                         } | ||||
|                     } | ||||
|                 UI_Layout layout; | ||||
|                 begin_layout(&layout, widg_rect); | ||||
|                 undo_shit(system, view, &state, &layout, total_count, undo_count, scrub_max); | ||||
|                  | ||||
|                 view->widget.height = layout.y - widg_rect.y0; | ||||
|                  | ||||
|                 if (ui_finish_frame(&view->widget.state, &state, &layout, widg_rect, 0, 0)){ | ||||
|                     result = 1; | ||||
|                 } | ||||
|             } | ||||
|             else{ | ||||
|                 if (do_button(3, &state, &layout, "+ History", 1)){ | ||||
|                     view->widget.timeline.history_line = 1; | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             view->widget.height = layout.y - widg_rect.y0; | ||||
|              | ||||
|             if (ui_finish_frame(&view->widget.state, &state, &layout, widg_rect, 0, 0)){ | ||||
|                 result = 1; | ||||
|             } | ||||
|         }break; | ||||
|             }break; | ||||
|         } | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
|  | @ -2969,16 +2975,26 @@ draw_file_bar(File_View *view, Interactive_Bar *bar, Render_Target *target){ | |||
|     } | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| draw_file_view_queries(File_View *view, UI_State *state, UI_Layout *layout){ | ||||
|     Widget_ID wid; | ||||
|     Query_Slot *slot; | ||||
|     Query_Bar *bar; | ||||
|     i32 i = 1; | ||||
|      | ||||
|     for (slot = view->query_set.used_slot; slot != 0; slot = slot->next){ | ||||
|         wid = make_id(state, i++); | ||||
|         bar = slot->query_bar; | ||||
|         do_text_field(wid, state, layout, bar->prompt, bar->string); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| internal i32 | ||||
| draw_file_loaded(File_View *view, i32_Rect rect, b32 is_active, Render_Target *target){ | ||||
|     Editing_File *file = view->file; | ||||
|     Style *style = view->style; | ||||
|     i32 line_height = view->font_height; | ||||
| 
 | ||||
|     Interactive_Bar bar; | ||||
|     draw_file_setup_bar(style, line_height, &bar, &rect); | ||||
|      | ||||
| #if BUFFER_EXPERIMENT_SCALPEL <= 3 | ||||
|     i32 max_x = rect.x1 - rect.x0; | ||||
|     i32 max_y = rect.y1 - rect.y0 + line_height; | ||||
|      | ||||
|  | @ -2991,17 +3007,6 @@ draw_file_loaded(File_View *view, i32_Rect rect, b32 is_active, Render_Target *t | |||
|         token_stack = file->state.token_stack; | ||||
|     } | ||||
|      | ||||
|     b32 links_use = 0; | ||||
|     Hyper_Link *links = 0; | ||||
|     i32 link_count = 0; | ||||
|     if (view->links){ | ||||
|         if (view->link_count > 0){ | ||||
|             links_use = 1; | ||||
|             links = view->links; | ||||
|             link_count = view->link_count; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     Partition *part = &view->view_base.mem->part; | ||||
| 
 | ||||
|     Temp_Memory temp = begin_temp_memory(part); | ||||
|  | @ -3056,22 +3061,13 @@ draw_file_loaded(File_View *view, i32_Rect rect, b32 is_active, Render_Target *t | |||
|     } | ||||
|      | ||||
|     i32 token_i = 0; | ||||
|     i32 link_i = 0; | ||||
|     u32 main_color = style->main.default_color; | ||||
|     u32 special_color = style->main.special_character_color; | ||||
|     u32 link_color = 0; | ||||
|     if (tokens_use){ | ||||
|         Cpp_Get_Token_Result result = cpp_get_token(&token_stack, items->index); | ||||
|         main_color = *style_get_color(style, token_stack.tokens[result.token_index]); | ||||
|         token_i = result.token_index + 1; | ||||
|     } | ||||
|     if (links_use){ | ||||
|         Get_Link_Result result = get_link(links, link_count, items->index); | ||||
|         if (result.in_link){ | ||||
|             link_color = *style_get_link_color(style, links[result.index].link_type); | ||||
|         } | ||||
|         link_i = result.index; | ||||
|     } | ||||
|      | ||||
|     u32 mark_color = style->main.mark_color; | ||||
|     Buffer_Render_Item *item = items; | ||||
|  | @ -3156,12 +3152,27 @@ draw_file_loaded(File_View *view, i32_Rect rect, b32 is_active, Render_Target *t | |||
|     } | ||||
|      | ||||
|     end_temp_memory(temp); | ||||
| #endif | ||||
|      | ||||
| #if 0 | ||||
|     ui_render(target, view->gui_target); | ||||
| #else | ||||
|     UI_Style ui_style = get_ui_style_upper(style); | ||||
|     return(0); | ||||
| } | ||||
| 
 | ||||
| internal i32 | ||||
| draw_file_view(View *view_, i32_Rect rect, bool32 is_active, Render_Target *target){ | ||||
|     File_View *view = (File_View*)view_; | ||||
|     i32 result = 0; | ||||
|      | ||||
|     if (view->file){ | ||||
|         Interactive_Bar bar; | ||||
|         draw_file_setup_bar(view->style, view->font_height, &bar, &rect); | ||||
|          | ||||
|         if (file_is_ready(view->file)){ | ||||
|             result = draw_file_loaded(view, rect, is_active, target); | ||||
|         } | ||||
|          | ||||
|         draw_file_bar(view, &bar, target); | ||||
|     } | ||||
|      | ||||
|     UI_Style ui_style = get_ui_style_upper(view->style); | ||||
|      | ||||
|     i32_Rect widg_rect = view_widget_rect(view, view->font_height); | ||||
|      | ||||
|  | @ -3178,122 +3189,60 @@ draw_file_loaded(File_View *view, i32_Rect rect, b32 is_active, Render_Target *t | |||
|     switch (view->widget.type){ | ||||
|         case FWIDG_NONE: | ||||
|         { | ||||
|             Widget_ID wid; | ||||
|             Query_Slot *slot; | ||||
|             Query_Bar *bar; | ||||
|             int i = 1; | ||||
|             for (slot = view->query_set.used_slot; slot != 0; slot = slot->next, ++i){ | ||||
|                 wid = make_id(&state, i); | ||||
|                 bar = slot->query_bar; | ||||
|                 do_text_field(wid, &state, &layout, bar->prompt, bar->string); | ||||
|             } | ||||
|             draw_file_view_queries(view, &state, &layout); | ||||
|         }break; | ||||
|          | ||||
|         case FWIDG_TIMELINES: | ||||
|         { | ||||
|             Assert(file); | ||||
|             if (view->widget.timeline.undo_line){ | ||||
|                 do_button(1, &state, &layout, "- Undo", 1); | ||||
| 
 | ||||
|                 Widget_ID wid = make_id(&state, 2); | ||||
|                 i32 undo_count, redo_count, total_count; | ||||
|                 undo_count = file->state.undo.undo.edit_count; | ||||
|                 redo_count = file->state.undo.redo.edit_count; | ||||
|                 total_count = undo_count + redo_count; | ||||
|                 do_undo_slider(wid, &state, &layout, total_count, undo_count, 0, 0); | ||||
|             if (view->file){ | ||||
|                 Editing_File *file = view->file; | ||||
|                 i32 undo_count = file->state.undo.undo.edit_count; | ||||
|                 i32 redo_count = file->state.undo.redo.edit_count; | ||||
|                 i32 total_count = undo_count + redo_count; | ||||
|                 undo_shit(0, view, &state, &layout, total_count, undo_count, 0); | ||||
|             } | ||||
|             else{ | ||||
|                 do_button(1, &state, &layout, "+ Undo", 1); | ||||
|             } | ||||
| 
 | ||||
|             if (view->widget.timeline.history_line){ | ||||
|                 do_button(3, &state, &layout, "- History", 1); | ||||
| 
 | ||||
|                 Widget_ID wid = make_id(&state, 4); | ||||
|                 i32 new_count; | ||||
|                 i32 mid = ((file->state.undo.history.edit_count + file->state.undo.edit_history_cursor) >> 1); | ||||
|                 do_undo_slider(wid, &state, &layout, mid, | ||||
|                     file->state.undo.edit_history_cursor, &file->state.undo, &new_count); | ||||
|             } | ||||
|             else{ | ||||
|                 do_button(3, &state, &layout, "+ History", 1); | ||||
|                 view->widget.type = FWIDG_NONE; | ||||
|             } | ||||
|         }break; | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     ui_finish_frame(&view->widget.state, &state, &layout, widg_rect, 0, 0); | ||||
| #endif | ||||
| 
 | ||||
|     draw_file_bar(view, &bar, target); | ||||
|      | ||||
|     return(0); | ||||
| } | ||||
| 
 | ||||
| internal i32 | ||||
| draw_file_loading(File_View *view, i32_Rect rect, b32 is_active, Render_Target *target){ | ||||
|     Interactive_Bar bar; | ||||
|     draw_file_setup_bar(view->style, view->font_height, &bar, &rect); | ||||
|      | ||||
|     draw_file_bar(view, &bar, target); | ||||
| 
 | ||||
|     return(0); | ||||
| } | ||||
| 
 | ||||
| internal i32 | ||||
| draw_file_view(View *view_, i32_Rect rect, bool32 is_active, | ||||
|                Render_Target *target){ | ||||
|     File_View *view = (File_View*)view_; | ||||
|     i32 result = 0; | ||||
|      | ||||
|     if (view->file){ | ||||
|         if (view->file->state.is_loading){ | ||||
|             result = draw_file_loading(view, rect, is_active, target); | ||||
|         } | ||||
|         else{ | ||||
|             result = draw_file_loaded(view, rect, is_active, target); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return (result); | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| kill_file(System_Functions *system, Exchange *exchange, | ||||
|           General_Memory *general, Editing_File *file, Live_Views *live_set, Editing_Layout *layout){ | ||||
|     i32 panel_count = layout->panel_count; | ||||
|     Panel *panels = layout->panels, *panel; | ||||
|     panel = panels; | ||||
| kill_file( | ||||
|     System_Functions *system, Exchange *exchange, | ||||
|     General_Memory *general, Editing_File *file, | ||||
|     Live_Views *live_set, Editing_Layout *layout){ | ||||
|      | ||||
|     for (i32 i = 0; i < panel_count; ++i){ | ||||
|         View *view = panel->view; | ||||
|         if (view){ | ||||
|             View *to_kill = view; | ||||
|             if (view->is_minor) to_kill = view->major; | ||||
|             File_View *fview = view_to_file_view(to_kill); | ||||
|             if (fview && fview->file == file){ | ||||
|                 live_set_free_view(system, exchange, live_set, &fview->view_base); | ||||
|                 if (to_kill == view) panel->view = 0; | ||||
|                 else view->major = 0; | ||||
|             } | ||||
|     View *view, *to_kill; | ||||
|     File_View *fview; | ||||
|     Panel *panel; | ||||
|     i32 panel_count, i; | ||||
| 
 | ||||
|     panel_count = layout->panel_count; | ||||
|     panel = layout->panels; | ||||
|     for (i = 0; i < panel_count; ++i, ++panel){ | ||||
|         view = panel->view; | ||||
|         to_kill = view; | ||||
|         if (view->is_minor) to_kill = view->major; | ||||
|         fview = view_to_file_view(to_kill); | ||||
|         if (fview && fview->file == file){ | ||||
|             fview->file = 0; | ||||
|         } | ||||
|         ++panel; | ||||
|     } | ||||
|     file_close(system, general, file); | ||||
|     file_get_dummy(file); | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| command_search(System_Functions*,Command_Data*,Command_Binding); | ||||
| internal void | ||||
| command_reverse_search(System_Functions*,Command_Data*,Command_Binding); | ||||
| 
 | ||||
| inline void | ||||
| free_file_view(View *view){ | ||||
|     File_View *fview = (File_View*)view; | ||||
|     if (fview->line_wrap_y) | ||||
|         general_memory_free(&view->mem->general, fview->line_wrap_y); | ||||
|     if (fview->links) | ||||
|         general_memory_free(&view->mem->general, fview->links); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
|  | @ -3581,5 +3530,13 @@ search_next_match(Partition *part, Search_Set *set, Search_Iter *iter_){ | |||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| view_change_size(System_Functions *system, General_Memory *general, File_View *view){ | ||||
|     if (view->file){ | ||||
|         view_measure_wraps(system, general, view); | ||||
|         view->cursor = view_compute_cursor_from_pos(view, view->cursor.pos); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // BOTTOM
 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										198
									
								
								4ed_layout.cpp
								
								
								
								
							
							
						
						
									
										198
									
								
								4ed_layout.cpp
								
								
								
								
							|  | @ -19,8 +19,8 @@ struct Interactive_Style{ | |||
| 
 | ||||
| struct Interactive_Bar{ | ||||
|     Interactive_Style style; | ||||
|     real32 pos_x, pos_y; | ||||
|     real32 text_shift_x, text_shift_y; | ||||
|     f32 pos_x, pos_y; | ||||
|     f32 text_shift_x, text_shift_y; | ||||
|     i32_Rect rect; | ||||
|     i16 font_id; | ||||
| }; | ||||
|  | @ -79,11 +79,11 @@ struct Live_Views{ | |||
| }; | ||||
| 
 | ||||
| struct Panel_Divider{ | ||||
|     Panel_Divider *next_free; | ||||
|     Panel_Divider *next; | ||||
|     i32 parent; | ||||
|     i32 which_child; | ||||
|     i32 child1, child2; | ||||
|     bool32 v_divider; | ||||
|     b32 v_divider; | ||||
|     i32 pos; | ||||
| }; | ||||
| 
 | ||||
|  | @ -131,17 +131,6 @@ intbar_draw_string(Render_Target *target, | |||
|         (i32)(bar->pos_y + bar->text_shift_y), | ||||
|         char_color); | ||||
|     bar->pos_x += font_string_width(target, font_id, (char*)str); | ||||
| 
 | ||||
| #if 0 | ||||
|     for (i32 i = 0; str[i]; ++i){ | ||||
|         char c = str[i]; | ||||
|         font_draw_glyph(target, font_id, c, | ||||
|                         bar->pos_x + bar->text_shift_x, | ||||
|                         bar->pos_y + bar->text_shift_y, | ||||
|                         char_color); | ||||
|         bar->pos_x += font_get_glyph_width(target, font_id, c); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
|  | @ -154,17 +143,6 @@ intbar_draw_string(Render_Target *target, Interactive_Bar *bar, | |||
|         (i32)(bar->pos_y + bar->text_shift_y), | ||||
|         char_color); | ||||
|     bar->pos_x += font_string_width(target, font_id, str); | ||||
| 
 | ||||
| #if 0 | ||||
|     for (i32 i = 0; i < str.size; ++i){ | ||||
|         char c = str.str[i]; | ||||
|         font_draw_glyph(target, font_id, c, | ||||
|                         bar->pos_x + bar->text_shift_x, | ||||
|                         bar->pos_y + bar->text_shift_y, | ||||
|                         char_color); | ||||
|         bar->pos_x += font_get_glyph_width(target, font_id, c); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
|  | @ -206,16 +184,21 @@ live_set_free_view(System_Functions *system, Exchange *exchange, Live_Views *liv | |||
|     view->is_active = 0; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| view_set_first(View *new_view, Panel *panel){ | ||||
|     new_view->panel = panel; | ||||
|     new_view->minor = 0; | ||||
|     panel->view = new_view; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| view_replace_major(System_Functions *system, Exchange *exchange, | ||||
|                    View *new_view, Panel *panel, Live_Views *live_set){ | ||||
|     View *new_view, Panel *panel, Live_Views *live_set){ | ||||
|     View *view = panel->view; | ||||
|     if (view){ | ||||
|         if (view->is_minor && view->major){ | ||||
|             live_set_free_view(system, exchange, live_set, view->major); | ||||
|         } | ||||
|         live_set_free_view(system, exchange, live_set, view); | ||||
|     if (view->is_minor && view->major){ | ||||
|         live_set_free_view(system, exchange, live_set, view->major); | ||||
|     } | ||||
|     live_set_free_view(system, exchange, live_set, view); | ||||
|     new_view->panel = panel; | ||||
|     new_view->minor = 0; | ||||
|     panel->view = new_view; | ||||
|  | @ -223,76 +206,34 @@ view_replace_major(System_Functions *system, Exchange *exchange, | |||
| 
 | ||||
| inline void | ||||
| view_replace_minor(System_Functions *system, Exchange *exchange, | ||||
|                    View *new_view, Panel *panel, Live_Views *live_set){ | ||||
|     View *new_view, Panel *panel, Live_Views *live_set){ | ||||
|     View *view = panel->view; | ||||
|      | ||||
|     new_view->is_minor = 1; | ||||
|     if (view){ | ||||
|         if (view->is_minor){ | ||||
|             new_view->major = view->major; | ||||
|             live_set_free_view(system, exchange, live_set, view); | ||||
|         } | ||||
|         else{ | ||||
|             new_view->major = view; | ||||
|             view->is_active = 0; | ||||
|         } | ||||
|     if (view->is_minor){ | ||||
|         new_view->major = view->major; | ||||
|         live_set_free_view(system, exchange, live_set, view); | ||||
|     } | ||||
|     else{ | ||||
|         new_view->major = 0; | ||||
|         new_view->major = view; | ||||
|         view->is_active = 0; | ||||
|     } | ||||
|     new_view->panel = panel; | ||||
|     panel->view = new_view; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| view_remove_major(System_Functions *system, Exchange *exchange, | ||||
|                   Panel *panel, Live_Views *live_set){ | ||||
| view_remove_minor(System_Functions *system, Exchange *exchange, | ||||
|     Panel *panel, Live_Views *live_set){ | ||||
|     View *view = panel->view; | ||||
|     if (view){ | ||||
|         if (view->is_minor && view->major){ | ||||
|             live_set_free_view(system, exchange, live_set, view->major); | ||||
|         } | ||||
|     View *major = view; | ||||
|     if (view->is_minor){ | ||||
|         major = view->major; | ||||
|         live_set_free_view(system, exchange, live_set, view); | ||||
|     } | ||||
|     panel->view = 0; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| view_remove_major_leave_minor(System_Functions *system, Exchange *exchange, | ||||
|                               Panel *panel, Live_Views *live_set){ | ||||
|     View *view = panel->view; | ||||
|     if (view){ | ||||
|         if (view->is_minor && view->major){ | ||||
|             live_set_free_view(system, exchange, live_set, view->major); | ||||
|             view->major = 0; | ||||
|         } | ||||
|         else{ | ||||
|             live_set_free_view(system, exchange, live_set, view); | ||||
|             panel->view = 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| view_remove_minor(System_Functions *system, Exchange *exchange, | ||||
|                   Panel *panel, Live_Views *live_set){ | ||||
|     View *view = panel->view; | ||||
|     View *major = 0; | ||||
|     if (view){ | ||||
|         if (view->is_minor){ | ||||
|             major = view->major; | ||||
|             live_set_free_view(system, exchange, live_set, view); | ||||
|         } | ||||
|     } | ||||
|     Assert(major); | ||||
|     panel->view = major; | ||||
|     if (major) major->is_active = 1; | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| view_remove(System_Functions *system, Exchange *exchange, | ||||
|             Panel *panel, Live_Views *live_set){ | ||||
|     View *view = panel->view; | ||||
|     if (view->is_minor) view_remove_minor(system, exchange, panel, live_set); | ||||
|     else view_remove_major(system, exchange, panel, live_set); | ||||
|     major->is_active = 1; | ||||
| } | ||||
| 
 | ||||
| struct Divider_And_ID{ | ||||
|  | @ -302,10 +243,12 @@ struct Divider_And_ID{ | |||
| 
 | ||||
| internal Divider_And_ID | ||||
| layout_alloc_divider(Editing_Layout *layout){ | ||||
|     Assert(layout->free_divider); | ||||
|     Divider_And_ID result; | ||||
|      | ||||
|     Assert(layout->free_divider); | ||||
|     result.divider = layout->free_divider; | ||||
|     layout->free_divider = result.divider->next_free; | ||||
|     layout->free_divider = result.divider->next; | ||||
|      | ||||
|     *result.divider = {}; | ||||
|     result.divider->parent = -1; | ||||
|     result.divider->child1 = -1; | ||||
|  | @ -314,7 +257,8 @@ layout_alloc_divider(Editing_Layout *layout){ | |||
|     if (layout->panel_count == 1){ | ||||
|         layout->root = result.id; | ||||
|     } | ||||
|     return result; | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal Divider_And_ID | ||||
|  | @ -337,21 +281,22 @@ layout_alloc_panel(Editing_Layout *layout){ | |||
| 
 | ||||
| internal void | ||||
| layout_free_divider(Editing_Layout *layout, Panel_Divider *divider){ | ||||
|     divider->next_free = layout->free_divider; | ||||
|     divider->next = layout->free_divider; | ||||
|     layout->free_divider = divider; | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| layout_free_panel(Editing_Layout *layout, Panel *panel){ | ||||
|     Panel *panels = layout->panels; | ||||
|     i32 panel_count = --layout->panel_count; | ||||
|     i32 panel_i = (i32)(panel - layout->panels); | ||||
|     for (i32 i = panel_i; i < panel_count; ++i){ | ||||
|         Panel *p = panels + i; | ||||
|     Panel *p, *panels; | ||||
|     i32 panel_count, i; | ||||
|      | ||||
|     panels = layout->panels; | ||||
|     panel_count = --layout->panel_count; | ||||
| 
 | ||||
|     p = panel; | ||||
|     for (i = (i32)(panel - layout->panels); i < panel_count; ++i, ++p){ | ||||
|         *p = panels[i+1]; | ||||
|         if (p->view){ | ||||
|             p->view->panel = p; | ||||
|         } | ||||
|         p->view->panel = p; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -369,18 +314,22 @@ struct Split_Result{ | |||
| }; | ||||
| 
 | ||||
| internal Split_Result | ||||
| layout_split_panel(Editing_Layout *layout, Panel *panel, bool32 vertical){ | ||||
|     Divider_And_ID div = layout_alloc_divider(layout); | ||||
| layout_split_panel(Editing_Layout *layout, Panel *panel, b32 vertical){ | ||||
|     Split_Result result = {}; | ||||
|     Divider_And_ID div = {}, parent_div = {}; | ||||
|     Panel *new_panel = 0; | ||||
|      | ||||
|     div = layout_alloc_divider(layout); | ||||
|     if (panel->parent != -1){ | ||||
|         Divider_And_ID pdiv = layout_get_divider(layout, panel->parent); | ||||
|         parent_div = layout_get_divider(layout, panel->parent); | ||||
|         if (panel->which_child == -1){ | ||||
|             pdiv.divider->child1 = div.id; | ||||
|             parent_div.divider->child1 = div.id; | ||||
|         } | ||||
|         else{ | ||||
|             pdiv.divider->child2 = div.id; | ||||
|             parent_div.divider->child2 = div.id; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     div.divider->parent = panel->parent; | ||||
|     div.divider->which_child = panel->which_child; | ||||
|     if (vertical){ | ||||
|  | @ -392,13 +341,12 @@ layout_split_panel(Editing_Layout *layout, Panel *panel, bool32 vertical){ | |||
|         div.divider->pos = (panel->full.y0 + panel->full.y1) / 2; | ||||
|     } | ||||
| 
 | ||||
|     Panel *new_panel = layout_alloc_panel(layout); | ||||
|     new_panel = layout_alloc_panel(layout); | ||||
|     panel->parent = div.id; | ||||
|     panel->which_child = -1; | ||||
|     new_panel->parent = div.id; | ||||
|     new_panel->which_child = 1; | ||||
| 
 | ||||
|     Split_Result result; | ||||
|     result.divider = div.divider; | ||||
|     result.panel = new_panel; | ||||
|     return result; | ||||
|  | @ -489,25 +437,29 @@ layout_fix_all_panels(Editing_Layout *layout){ | |||
| } | ||||
| 
 | ||||
| internal void | ||||
| layout_refit(Editing_Layout *layout, | ||||
|              i32 prev_x_off, i32 prev_y_off, | ||||
|              i32 prev_width, i32 prev_height){ | ||||
| layout_refit(Editing_Layout *layout, i32 prev_width, i32 prev_height){ | ||||
|      | ||||
|     Panel_Divider *dividers = layout->dividers; | ||||
|     i32 divider_max_count = layout->panel_max_count - 1; | ||||
|     i32 max = layout->panel_max_count - 1; | ||||
|      | ||||
|     f32 h_ratio, v_ratio; | ||||
| 
 | ||||
|     i32 x_off = 0; | ||||
|     i32 y_off = 0; | ||||
|     Panel_Divider *divider = dividers; | ||||
|     i32 i; | ||||
| 
 | ||||
|     real32 h_ratio = ((real32)layout->full_width) / prev_width; | ||||
|     real32 v_ratio = ((real32)layout->full_height) / prev_height; | ||||
|     if (layout->panel_count > 1){ | ||||
|         Assert(prev_width != 0 && prev_height != 0); | ||||
| 
 | ||||
|     for (i32 divider_id = 0; divider_id < divider_max_count; ++divider_id){ | ||||
|         Panel_Divider *divider = dividers + divider_id; | ||||
|         if (divider->v_divider){ | ||||
|             divider->pos = x_off + ROUND32((divider->pos - prev_x_off) * h_ratio); | ||||
|         } | ||||
|         else{ | ||||
|             divider->pos = y_off + ROUND32((divider->pos - prev_y_off) * v_ratio); | ||||
|         h_ratio = ((f32)layout->full_width) / prev_width; | ||||
|         v_ratio = ((f32)layout->full_height) / prev_height; | ||||
| 
 | ||||
|         for (i = 0; i < max; ++i, ++divider){ | ||||
|             if (divider->v_divider){ | ||||
|                 divider->pos = ROUND32((divider->pos) * h_ratio); | ||||
|             } | ||||
|             else{ | ||||
|                 divider->pos = ROUND32((divider->pos) * v_ratio); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -121,7 +121,6 @@ char *daction_enum[] = { | |||
|     "TRY_KILL", | ||||
|     "KILL", | ||||
|     "CLOSE_MINOR", | ||||
|     "CLOSE_MAJOR", | ||||
|     "THEME_OPTIONS", | ||||
|     "KEYBOARD_OPTIONS" | ||||
| }; | ||||
|  |  | |||
|  | @ -26,8 +26,6 @@ | |||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #undef Assert | ||||
| #undef internal | ||||
| #include "4coder_custom.cpp" | ||||
| 
 | ||||
| #undef exec_command | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Allen Webster
						Allen Webster