From 852a7fd71ccbe5e37fad0abedced3646ae80c0c4 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Wed, 30 Sep 2015 12:32:01 -0400 Subject: [PATCH] style-system --- 4ed.cpp | 128 ++++++++++---- 4ed_debug_view.cpp | 2 + 4ed_file_view.cpp | 407 +++++++++++++++++++++++++++++---------------- 4ed_style.cpp | 264 ++++++++++++++++++++++++++--- 4 files changed, 604 insertions(+), 197 deletions(-) diff --git a/4ed.cpp b/4ed.cpp index 632eeb6f..56e9a8ae 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -12,8 +12,6 @@ // // BUGS & PROBLEMS // -// - LOGGING SYSTEM FOR ALL BUILD CONFIGS -// // - line_wrap_ys remeasurement optimization // // GENERAL @@ -31,8 +29,6 @@ // // - configuration / GUI for generating configuration // -// - no scroll on line wrap/line mode change -// // - travel packaging // // - multiple live name conflicts @@ -63,8 +59,6 @@ // // - select token // -// - seek token or whitespace within token -// // - reprogrammable lexing / auto indent // // - bracket match / mismatch highlighting @@ -89,9 +83,7 @@ // - generate header // -/* - * App Structs - */ +// App Structs enum App_State{ APP_STATE_EDIT, @@ -142,9 +134,7 @@ struct App_Vars{ Panel *prev_mouse_panel; }; -/* - * Commands - */ +// Commands globalvar Application_Links app_links; @@ -235,7 +225,7 @@ COMMAND_DECL(write_character){ current_view->preferred_x = view_get_cursor_x(current_view); } } - file->cursor.pos = view->cursor.pos; + file->cursor_pos = view->cursor.pos; } internal i32 @@ -732,11 +722,8 @@ COMMAND_DECL(paste_next){ (u8*)src->str, src->size); view_measure_wraps(&mem->general, view); - - view->cursor = view_compute_cursor_from_pos(view, range.smaller+src->size); - view->preferred_x = view_get_cursor_x(view); - view->file->cursor.pos = view->cursor.pos; - + + view_cursor_move(view, range.smaller+src->size); view->mark = pos_universal_fix(range.smaller, file->data, file->size, file->endline_mode); @@ -792,11 +779,10 @@ COMMAND_DECL(delete_chunk){ } buffer_delete_range(mem, file, range); view_measure_wraps(&mem->general, view); - view->cursor = view_compute_cursor_from_pos(view, range.smaller); + view_cursor_move(view, range.smaller); view->mark = pos_universal_fix(range.smaller, file->data, file->size, file->endline_mode); - view->file->cursor.pos = view->cursor.pos; Editing_Layout *layout = command->layout; Panel *panels = layout->panels; @@ -828,6 +814,49 @@ COMMAND_DECL(delete_chunk){ } } +COMMAND_DECL(undo){ + ProfileMomentFunction(); + REQ_FILE_VIEW(view); + REQ_FILE(file, view); + USE_MEM(mem); + + if (file->undo.edit_count > 0){ + Edit_Step step = file->undo.edits[--file->undo.edit_count]; + + buffer_post_redo(&mem->general, file, step.range.start, step.range.end, step.replaced.size); + buffer_replace_range(mem, file, step.range.start, step.range.end, + (u8*)step.replaced.str, step.replaced.size, 0); + view_cursor_move(view, step.cursor_pos); + view->mark = view->cursor.pos; + + view_post_paste_effect(view, 10, step.range.start, step.replaced.size, + view->style->main.undo_color); + + file->undo.str_size -= step.replaced.size; + } +} + +COMMAND_DECL(redo){ + ProfileMomentFunction(); + REQ_FILE_VIEW(view); + REQ_FILE(file, view); + USE_MEM(mem); + + if (file->undo.edit_redo < file->undo.edit_max){ + Edit_Step step = file->undo.edits[file->undo.edit_redo++]; + + buffer_replace_range(mem, file, step.range.start, step.range.end, + (u8*)step.replaced.str, step.replaced.size, 2); + view_cursor_move(view, step.cursor_pos); + view->mark = view->cursor.pos; + + view_post_paste_effect(view, 10, step.range.start, step.replaced.size, + view->style->main.undo_color); + + file->undo.str_redo += step.replaced.size; + } +} + COMMAND_DECL(interactive_new){ ProfileMomentFunction(); USE_VARS(vars); @@ -1132,6 +1161,7 @@ COMMAND_DECL(to_lowercase){ } } +#if 0 internal void view_clean_line(Mem_Options *mem, File_View *view, Editing_File *file, i32 line_start){ u8 *data = file->data; @@ -1188,8 +1218,10 @@ view_clean_line(Mem_Options *mem, File_View *view, Editing_File *file, i32 line_ //view_auto_tab(mem, view, pos, pos); } } +#endif COMMAND_DECL(clean_line){ +#if 0 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -1198,9 +1230,11 @@ COMMAND_DECL(clean_line){ i32 line_start = view_find_beginning_of_line(view, view->cursor.pos); view_clean_line(mem, view, file, line_start); view_measure_wraps(&mem->general, view); +#endif } COMMAND_DECL(clean_all_lines){ +#if 0 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -1213,9 +1247,11 @@ COMMAND_DECL(clean_all_lines){ view_measure_wraps(&mem->general, view); view->cursor = view_compute_cursor_from_pos(view, view->cursor.pos); +#endif } COMMAND_DECL(eol_dosify){ +#if 0 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -1223,9 +1259,11 @@ COMMAND_DECL(eol_dosify){ view_endline_convert(mem, view, ENDLINE_RN, ENDLINE_ERASE, ENDLINE_RN); view_measure_wraps(&mem->general, view); +#endif } COMMAND_DECL(eol_nixify){ +#if 0 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -1233,17 +1271,19 @@ COMMAND_DECL(eol_nixify){ view_endline_convert(mem, view, ENDLINE_N, ENDLINE_ERASE, ENDLINE_N); view_measure_wraps(&mem->general, view); +#endif } COMMAND_DECL(auto_tab){ +#if 0 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); USE_MEM(mem); - Range range = get_range(view->cursor.pos, view->mark); view_auto_tab(mem, view, range.smaller, range.larger); view_measure_wraps(&mem->general, view); +#endif } COMMAND_DECL(open_panel_vsplit){ @@ -1541,7 +1581,7 @@ COMMAND_DECL(move_up){ real32 px = view->preferred_x; if (cy >= 0){ view->cursor = view_compute_cursor_from_xy(view, px, cy); - view->file->cursor.pos = view->cursor.pos; + view->file->cursor_pos = view->cursor.pos; } } @@ -1553,7 +1593,7 @@ COMMAND_DECL(move_down){ real32 cy = view_get_cursor_y(view)+view->style->font->height; real32 px = view->preferred_x; view->cursor = view_compute_cursor_from_xy(view, px, cy); - view->file->cursor.pos = view->cursor.pos; + view->file->cursor_pos = view->cursor.pos; } COMMAND_DECL(seek_end_of_line){ @@ -1709,12 +1749,15 @@ COMMAND_DECL(cursor_mark_swap){ view->mark = pos; } -internal void -fulfill_interaction(Command_Data *command, char *data, bool32 full_set){ +internal bool32 +fulfill_interaction_intview(Command_Data *command, char *data, bool32 full_set){ + bool32 result = 0; Panel *panel = command->panel; View *view = panel->view; Interactive_View *int_view = view_to_interactive_view(view); if (int_view){ + result = 1; + String *dest = 0; switch (int_view->interaction){ case INTV_SYS_FILE_LIST: @@ -1726,9 +1769,11 @@ fulfill_interaction(Command_Data *command, char *data, bool32 full_set){ } if (full_set) dest->size = 0; append(dest, data); + + interactive_view_complete(int_view); } - - interactive_view_complete(int_view); + + return result; } COMMAND_DECL(user_callback){ @@ -1766,7 +1811,8 @@ extern "C"{ FULFILL_INTERACTION_SIG(fulfill_interaction_external){ Command_Data *cmd = (Command_Data*)cmd_context; - fulfill_interaction(cmd, data, full_set); + bool32 handled = 0; + handled = fulfill_interaction_intview(cmd, data, full_set); } } @@ -1829,6 +1875,8 @@ setup_file_commands(Command_Map *commands, Key_Codes *codes){ map_add(commands, 'x', MDFR_CTRL, command_cut); map_add(commands, 'v', MDFR_CTRL, command_paste); map_add(commands, 'V', MDFR_CTRL, command_paste_next); + map_add(commands, 'z', MDFR_CTRL, command_undo); + map_add(commands, 'y', MDFR_CTRL, command_redo); map_add(commands, 'd', MDFR_CTRL, command_delete_chunk); map_add(commands, 'l', MDFR_CTRL, command_toggle_line_wrap); map_add(commands, 'L', MDFR_CTRL, command_toggle_endline_mode); @@ -1956,9 +2004,7 @@ setup_command_table(){ #undef SET } -/* - * Interactive Bar - */ +// Interactive Bar internal void hot_directory_draw_helper(Render_Target *target, @@ -2074,12 +2120,14 @@ app_hardcode_styles(App_Vars *vars){ style->main.special_character_color = 0xFFFF0000; style->main.paste_color = 0xFFDDEE00; + style->main.undo_color = 0xFF00DDEE; + style->main.next_undo_color = 0xFF006E77; style->main.highlight_junk_color = 0xff3a0000; style->main.highlight_white_color = 0xff003a3a; file_info_style.bar_color = 0xFF888888; - file_info_style.bar_active_color = 0xFF888888; + file_info_style.bar_active_color = 0xFF666666; file_info_style.base_color = 0xFF000000; file_info_style.pop1_color = 0xFF4444AA; file_info_style.pop2_color = 0xFFFF0000; @@ -2119,12 +2167,14 @@ app_hardcode_styles(App_Vars *vars){ style->main.special_character_color = 0xFFFF0000; style->main.paste_color = 0xFFFFBB00; + style->main.undo_color = 0xFFFF00BB; + style->main.undo_color = 0xFF80005D; style->main.highlight_junk_color = 0xFF3A0000; style->main.highlight_white_color = 0xFF003A3A; file_info_style.bar_color = 0xFFCACACA; - file_info_style.bar_active_color = 0xFFCACACA; + file_info_style.bar_active_color = 0xFFA8A8A8; file_info_style.base_color = 0xFF000000; file_info_style.pop1_color = 0xFF1504CF; file_info_style.pop2_color = 0xFFFF0000; @@ -2158,12 +2208,14 @@ app_hardcode_styles(App_Vars *vars){ style->main.special_character_color = 0xFFFF0000; style->main.paste_color = 0xFFDDEE00; + style->main.undo_color = 0xFF00DDEE; + style->main.next_undo_color = 0xFF006E77; style->main.highlight_junk_color = 0xff3a0000; style->main.highlight_white_color = 0xFF151F2A; file_info_style.bar_color = 0xFF315E68; - file_info_style.bar_active_color = 0xFF315E68; + file_info_style.bar_active_color = 0xFF0F3C46; file_info_style.base_color = 0xFF000000; file_info_style.pop1_color = 0xFF1BFF0C; file_info_style.pop2_color = 0xFFFF200D; @@ -2197,12 +2249,14 @@ app_hardcode_styles(App_Vars *vars){ style->main.special_character_color = 0xFFFF0000; style->main.paste_color = 0xFF900090; + style->main.undo_color = 0xFF606090; + style->main.next_undo_color = 0xFF404070; style->main.highlight_junk_color = 0xff3a0000; style->main.highlight_white_color = 0xff003a3a; file_info_style.bar_color = 0xFF7082F9; - file_info_style.bar_active_color = 0xFF7082F9; + file_info_style.bar_active_color = 0xFF4E60D7; file_info_style.base_color = 0xFF000000; file_info_style.pop1_color = 0xFFFAFA15; file_info_style.pop2_color = 0xFFD20000; @@ -2236,12 +2290,14 @@ app_hardcode_styles(App_Vars *vars){ style->main.special_character_color = 0xFF9A0000; style->main.paste_color = 0xFF00B8B8; + style->main.undo_color = 0xFFB800B8; + style->main.next_undo_color = 0xFF5C005C; style->main.highlight_junk_color = 0xFFFF7878; style->main.highlight_white_color = 0xFFBCBCBC; file_info_style.bar_color = 0xFF606060; - file_info_style.bar_active_color = 0xFF888888; + file_info_style.bar_active_color = 0xFF3E3E3E; file_info_style.base_color = 0xFF000000; file_info_style.pop1_color = 0xFF1111DC; file_info_style.pop2_color = 0xFFE80505; diff --git a/4ed_debug_view.cpp b/4ed_debug_view.cpp index bd6375c8..e757458a 100644 --- a/4ed_debug_view.cpp +++ b/4ed_debug_view.cpp @@ -60,6 +60,8 @@ draw_general_memory(Debug_View *view, i32_Rect rect, Render_Target *target, i32 case BUBBLE_WIDTHS: append(&s, "widths"); break; case BUBBLE_WRAPS: append(&s, "wraps"); break; case BUBBLE_TOKENS: append(&s, "tokens"); break; + case BUBBLE_UNDO_STRING: append(&s, "undo string"); break; + case BUBBLE_UNDO: append(&s, "undo"); break; default: append(&s, "unknown"); break; } } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 1933ca7a..83974d58 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -9,20 +9,45 @@ // TOP -struct Cursor_Data{ - i32 pos; -}; - enum Endline_Mode{ ENDLINE_RN_COMBINED, ENDLINE_RN_SEPARATE, ENDLINE_RN_SHOWALLR }; +struct Range{ + union{ + struct{ + i32 smaller, larger; + }; + struct{ + i32 start, end; + }; + }; + bool32 swapped; +}; + +struct Edit_Step{ + String replaced; + Range range; + i32 cursor_pos; + bool32 can_merge; +}; + +struct Undo_Data{ + i32 str_size, str_redo, str_max; + u8 *strings; + + i32 edit_count, edit_redo, edit_max; + Edit_Step *edits; +}; + struct Editing_File{ i32 size, max_size; u8 *data; + Undo_Data undo; + i32 line_count, line_max; i32 *line_starts; @@ -31,7 +56,7 @@ struct Editing_File{ real32 *line_width; Endline_Mode endline_mode; - Cursor_Data cursor; + i32 cursor_pos; bool32 is_dummy; char source_path_[256]; @@ -215,18 +240,6 @@ struct File_View{ Text_Effect paste_effect; }; -struct Range{ - union{ - struct{ - i32 smaller, larger; - }; - struct{ - i32 start, end; - }; - }; - bool32 swapped; -}; - inline File_View* view_to_file_view(View *view){ File_View* result = 0; @@ -388,6 +401,8 @@ enum File_Bubble_Type{ BUBBLE_WIDTHS, BUBBLE_WRAPS, BUBBLE_TOKENS, + BUBBLE_UNDO_STRING, + BUBBLE_UNDO, // FILE_BUBBLE_TYPE_END, }; @@ -689,7 +704,7 @@ view_measure_wraps(General_Memory *general, File_View *view){ internal void buffer_create_from_string(General_Memory *general, Editing_File *file, u8 *filename, Font *font, String val){ - i32 request_size = LargeRoundUp(1+val.size*2, Kbytes(256)); + i32 request_size = LargeRoundUp(1+val.size*2, Kbytes(64)); u8 *data = (u8*)general_memory_allocate(general, request_size, BUBBLE_BUFFER); // TODO(allen): if we didn't get the memory what is going on? @@ -713,6 +728,14 @@ buffer_create_from_string(General_Memory *general, Editing_File *file, u8 *filen buffer_measure_starts(general, file); buffer_measure_widths(general, file, font); file->font = font; + + file->undo.str_max = request_size; + file->undo.str_redo = file->undo.str_max; + file->undo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); + + file->undo.edit_max = request_size / sizeof(Edit_Step); + file->undo.edit_redo = file->undo.edit_max; + file->undo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); if (!match(file->extension, make_lit_string("txt"))){ file->tokens_exist = 1; @@ -789,12 +812,6 @@ buffer_get_dummy(Editing_File *buffer){ buffer->is_dummy = 1; } -enum Replace_Operation_Type{ - REP_UNKNOWN, - REP_REGULAR, - REP_WHITESPACE -}; - struct Shift_Information{ i32 start, end, amount; }; @@ -955,7 +972,6 @@ buffer_relex_parallel(Mem_Options *mem, Editing_File *file, } if (!inline_lex){ - // TODO(allen): duplicated see REP_WHITESPACE i32 end_token_i = cpp_get_end_token(&file->token_stack, end_i); cpp_shift_token_starts(&file->token_stack, end_token_i, amount); --end_token_i; @@ -997,73 +1013,171 @@ buffer_grow_as_needed(General_Memory *general, Editing_File *file, i32 additiona return result; } +inline void +buffer_grow_undo_string(General_Memory *general, Editing_File *file, i32 extra_size){ + i32 old_max = file->undo.str_max; + u8 *old_str = file->undo.strings; + i32 redo_size = old_max - file->undo.str_redo; + i32 new_max = old_max*2 + extra_size; + u8 *new_str = (u8*) + general_memory_allocate(general, new_max, BUBBLE_UNDO_STRING); + i32 new_redo = new_max - redo_size; + + memcpy(new_str, old_str, file->undo.str_size); + memcpy(new_str + new_redo, old_str + file->undo.str_redo, redo_size); + + general_memory_free(general, old_str); + + file->undo.strings = new_str; + file->undo.str_max = new_max; + file->undo.str_redo = new_redo; +} + +inline void +buffer_grow_undo_edits(General_Memory *general, Editing_File *file){ + i32 old_max = file->undo.edit_max; + Edit_Step *old_eds = file->undo.edits; + i32 redo_size = old_max - file->undo.edit_redo; + i32 new_max = old_max*2 + 2; + Edit_Step *new_eds = (Edit_Step*) + general_memory_allocate(general, new_max*sizeof(Edit_Step), BUBBLE_UNDO); + i32 new_redo = new_max - redo_size; + + memcpy(new_eds, old_eds, file->undo.edit_count*sizeof(Edit_Step)); + memcpy(new_eds + new_redo, old_eds, redo_size*sizeof(Edit_Step)); + + general_memory_free(general, old_eds); + + file->undo.edits = new_eds; + file->undo.edit_max = new_max; + file->undo.edit_redo = new_redo; +} + +inline void +buffer_post_undo(General_Memory *general, Editing_File *file, + i32 start, i32 end, i32 str_len, bool32 do_merge, bool32 can_merge, + bool32 clear_redo){ + String replaced = make_string((char*)file->data + start, end - start); + + if (clear_redo){ + file->undo.str_redo = file->undo.str_max; + file->undo.edit_redo = file->undo.edit_max; + } + + if (file->undo.str_redo < file->undo.str_size + replaced.size) + buffer_grow_undo_string(general, file, replaced.size); + + Edit_Step edit; + edit.replaced = make_string((char*)file->undo.strings + file->undo.str_size, replaced.size); + file->undo.str_size += replaced.size; + copy(&edit.replaced, replaced); + edit.range = {start, start + str_len, 0}; + edit.cursor_pos = file->cursor_pos; + edit.can_merge = can_merge; + + bool32 did_merge = 0; + if (do_merge && file->undo.edit_count > 0){ + Edit_Step prev = file->undo.edits[file->undo.edit_count-1]; + if (prev.can_merge && edit.replaced.size == 0 && prev.replaced.size == 0){ + if (prev.range.end == edit.range.start){ + did_merge = 1; + edit.range.start = prev.range.start; + edit.cursor_pos = prev.cursor_pos; + } + } + } + + if (did_merge){ + file->undo.edits[file->undo.edit_count-1] = edit; + } + else{ + if (file->undo.edit_redo <= file->undo.edit_count) + buffer_grow_undo_edits(general, file); + file->undo.edits[file->undo.edit_count++] = edit; + } +} + +inline void +buffer_post_redo(General_Memory *general, Editing_File *file, + i32 start, i32 end, i32 str_len){ + String replaced = make_string((char*)file->data + start, end - start); + + if (file->undo.str_redo - replaced.size < file->undo.str_size) + buffer_grow_undo_string(general, file, replaced.size); + + file->undo.str_redo -= replaced.size; + TentativeAssert(file->undo.str_redo >= file->undo.str_size); + + Edit_Step edit; + edit.replaced = make_string((char*)file->undo.strings + file->undo.str_redo, replaced.size); + copy(&edit.replaced, replaced); + edit.range = {start, start + str_len, 0}; + edit.cursor_pos = file->cursor_pos; + + if (file->undo.edit_redo <= file->undo.edit_count) + buffer_grow_undo_edits(general, file); + --file->undo.edit_redo; + file->undo.edits[file->undo.edit_redo] = edit; +} + +inline i32 +buffer_text_replace(General_Memory *general, Editing_File *file, + i32 start, i32 end, u8 *str, i32 str_len){ + i32 shift_amount = (str_len - (end - start)); + + buffer_grow_as_needed(general, file, shift_amount); + Assert(shift_amount + file->size < file->max_size); + + i32 size = file->size; + u8 *data = (u8*)file->data; + memmove(data + end + shift_amount, data + end, size - end); + file->size += shift_amount; + + memcpy(data + start, str, str_len); + + return shift_amount; +} + // TODO(allen): Proper strings? internal Shift_Information buffer_replace_range(Mem_Options *mem, Editing_File *file, i32 start, i32 end, u8 *str, i32 str_len, - Replace_Operation_Type op_type = REP_UNKNOWN){ + i32 save_undo = 1){ ProfileMomentFunction(); - General_Memory *general = &mem->general; - Shift_Information shift = {}; - shift.start = start; - shift.end = end; - shift.amount = (str_len - (end - start)); - - // TODO(allen): Quickly figure out which op type is appropriate? - // Or just assume REGULAR, as that is always correct? - - buffer_grow_as_needed(general, file, shift.amount); - Assert(shift.amount + file->size < file->max_size); - - if (file->still_lexing){ + if (file->still_lexing) system_cancel_job(BACKGROUND_THREADS, file->lex_job); - } file->last_4ed_edit_time = system_get_now(); - i32 size = file->size; - u8 *data = (u8*)file->data; - memmove(data + shift.end + shift.amount, data + shift.end, size - end); - file->size += shift.amount; - - memcpy(data + start, str, str_len); - - if (file->tokens_exist){ - switch (op_type){ - case REP_UNKNOWN: - case REP_REGULAR: - { - buffer_relex_parallel(mem, file, start, end, shift.amount); - }break; - - case REP_WHITESPACE: - { - // TODO(allen): duplicated see buffer_relex_parallel - i32 end_token_i = cpp_get_end_token(&file->token_stack, end); - cpp_shift_token_starts(&file->token_stack, end_token_i, shift.amount); - --end_token_i; - if (end_token_i >= 0){ - Cpp_Token *token = file->token_stack.tokens + end_token_i; - if (token->start < end && token->start + token->size > end){ - token->size += shift.amount; - } - } - }break; - } + General_Memory *general = &mem->general; + if (save_undo){ + bool32 can_merge = 0, do_merge = 0; + if (str_len == 1 && char_is_alpha_numeric(*str)) can_merge = 1; + if (str_len == 1 && (can_merge || char_is_whitespace(*str))) do_merge = 1; + buffer_post_undo(general, file, start, end, str_len, do_merge, can_merge, save_undo == 1); } - i32 line_start = buffer_get_line_index(file, shift.start); - i32 line_end = buffer_get_line_index(file, shift.end); + i32 shift_amount = buffer_text_replace(general, file, start, end, str, str_len); + + if (file->tokens_exist) + buffer_relex_parallel(mem, file, start, end, shift_amount); + + i32 line_start = buffer_get_line_index(file, start); + i32 line_end = buffer_get_line_index(file, end); i32 replaced_line_count = line_end - line_start; - i32 new_line_count = buffer_count_newlines(file, shift.start, shift.start+str_len); + i32 new_line_count = buffer_count_newlines(file, start, start+str_len); i32 line_shift = new_line_count - replaced_line_count; - buffer_remeasure_starts(general, file, line_start, line_end, line_shift, shift.amount); + buffer_remeasure_starts(general, file, line_start, line_end, line_shift, shift_amount); // TODO(allen): Can we "remeasure" widths now!? buffer_measure_widths(general, file, file->font); + Shift_Information shift; + shift.start = start; + shift.end = end; + shift.amount = shift_amount; return shift; } @@ -1490,7 +1604,7 @@ view_set_file(File_View *view, Editing_File *file, Style *style){ view_measure_wraps(general, view); view->cursor = {}; - view->cursor = view_compute_cursor_from_pos(view, file->cursor.pos); + view->cursor = view_compute_cursor_from_pos(view, file->cursor_pos); real32 cursor_x, cursor_y; real32 w, h; @@ -1555,7 +1669,7 @@ inline void view_cursor_move(File_View *view, View_Cursor_Data cursor){ view->cursor = cursor; view->preferred_x = view_get_cursor_x(view); - view->file->cursor.pos = view->cursor.pos; + view->file->cursor_pos = view->cursor.pos; view->show_temp_highlight = 0; } @@ -1563,7 +1677,7 @@ inline void view_cursor_move(File_View *view, i32 pos){ view->cursor = view_compute_cursor_from_pos(view, pos); view->preferred_x = view_get_cursor_x(view); - view->file->cursor.pos = view->cursor.pos; + view->file->cursor_pos = view->cursor.pos; view->show_temp_highlight = 0; } @@ -1576,7 +1690,7 @@ view_cursor_move(File_View *view, real32 x, real32 y, bool32 round_down = 0){ view->cursor = view_compute_cursor_from_wrapped_xy(view, x, y, round_down); } view->preferred_x = view_get_cursor_x(view); - view->file->cursor.pos = view->cursor.pos; + view->file->cursor_pos = view->cursor.pos; view->show_temp_highlight = 0; } @@ -1721,6 +1835,7 @@ clipboard_copy(General_Memory *general, Working_Set *working, u8 *data, Range ra system_post_clipboard(*dest); } +#if 0 internal void view_endline_convert(Mem_Options *mem, File_View *view, Endline_Convert_Type rn_to, @@ -1766,8 +1881,7 @@ view_endline_convert(Mem_Options *mem, File_View *view, if (rn_to != ENDLINE_RN){ buffer_replace_range(mem, file, i, i+2, eol_strings[rn_to].str, - eol_strings[rn_to].size, - REP_WHITESPACE); + eol_strings[rn_to].size); i32 shift = eol_strings[rn_to].size - 2; if (cursor >= i){ cursor += shift; @@ -1785,8 +1899,7 @@ view_endline_convert(Mem_Options *mem, File_View *view, if (r_to != ENDLINE_R){ buffer_replace_range(mem, file, i, i+1, eol_strings[r_to].str, - eol_strings[r_to].size, - REP_WHITESPACE); + eol_strings[r_to].size); i32 shift = eol_strings[r_to].size - 1; if (cursor >= i){ cursor += shift; @@ -1803,8 +1916,7 @@ view_endline_convert(Mem_Options *mem, File_View *view, if (n_to != ENDLINE_N){ buffer_replace_range(mem, file, i, i+1, eol_strings[n_to].str, - eol_strings[n_to].size, - REP_WHITESPACE); + eol_strings[n_to].size); i32 shift = eol_strings[n_to].size - 1; if (cursor >= i){ cursor += shift; @@ -1821,6 +1933,7 @@ view_endline_convert(Mem_Options *mem, File_View *view, view->cursor = view_compute_cursor_from_pos(view, cursor); view->mark = mark; } +#endif struct Indent_Definition{ i32 tabs, spaces; @@ -1860,6 +1973,7 @@ buffer_find_hard_start(Editing_File *file, i32 line_start){ return result; } +#if 0 // NOTE(allen): Assumes that whitespace_buffer has at least // indent.tabs*4 + indent.spaces bytes available. internal Shift_Information @@ -1885,7 +1999,7 @@ buffer_set_indent_whitespace(Mem_Options *mem, Editing_File *file, if (leading_white.smaller < leading_white.larger){ shift = buffer_replace_range(mem, file, leading_white.smaller, leading_white.larger, - whitespace_buffer, i, REP_WHITESPACE); + whitespace_buffer, i); } return shift; @@ -2005,7 +2119,9 @@ buffer_compute_nest_level_tokens(Editing_File *file, i32 pos, Nest_Level_Hint hi } return result; } +#endif +#if 0 internal void view_auto_tab(Mem_Options *mem, File_View *view, i32 start, i32 end){ Editing_File *file = view->file; @@ -2258,6 +2374,7 @@ view_auto_tab(Mem_Options *mem, File_View *view, i32 start, i32 end){ view_cursor_move(view, cursor); view->mark = pos_adjust_to_self(mark, data, file->size); } +#endif internal u32* style_get_color(Style *style, Cpp_Token token){ @@ -2458,62 +2575,6 @@ step_file_view(Thread_Context *thread, View *view_, i32_Rect rect, return result; } -internal void -file_view_intbar(Thread_Context *thread, Render_Target *target, - Interactive_Bar *bar, File_View *view, - Editing_File *file, Style *style){ - i32 w, h; - w = bar->rect.x1 - bar->rect.x0; - h = bar->rect.y1 - bar->rect.y0; - u32 back_color = bar->style.bar_color; - draw_rectangle(target, bar->rect, back_color); - - u32 base_color = bar->style.base_color; - intbar_draw_string(target, bar, file->live_name, base_color); - intbar_draw_string(target, bar, make_lit_string(" - "), base_color); - - char line_number_space[30]; - String line_number = make_string(line_number_space, 0, 30); - append(&line_number, "L#"); - append_int_to_str(view->cursor.line, &line_number); - - intbar_draw_string(target, bar, line_number, base_color); - - switch (view->state){ - case FVIEW_STATE_EDIT: - { - if (file->last_4ed_write_time != file->last_sys_write_time){ - persist String out_of_sync = make_lit_string(" BEHIND OS"); - intbar_draw_string(target, bar, out_of_sync, bar->style.pop2_color); - } - else if (file->last_4ed_edit_time > file->last_sys_write_time){ - persist String out_of_sync = make_lit_string(" *"); - intbar_draw_string(target, bar, out_of_sync, bar->style.pop2_color); - } - }break; - - case FVIEW_STATE_SEARCH: - { - persist String search_str = make_lit_string(" I-Search: "); - persist String rsearch_str = make_lit_string(" Reverse-I-Search: "); - if (view->isearch.reverse){ - intbar_draw_string(target, bar, rsearch_str, bar->style.pop1_color); - } - else{ - intbar_draw_string(target, bar, search_str, bar->style.pop1_color); - } - intbar_draw_string(target, bar, view->isearch.str, bar->style.base_color); - }break; - - case FVIEW_STATE_GOTO_LINE: - { - persist String gotoline_str = make_lit_string(" Goto Line: "); - intbar_draw_string(target, bar, gotoline_str, bar->style.pop1_color); - intbar_draw_string(target, bar, view->isearch.str, bar->style.base_color); - }break; - } -} - internal i32 draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_active, Render_Target *target){ @@ -2601,7 +2662,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act real32 fade_amount = 0.f; if (view->paste_effect.tick_down > 0 && view->paste_effect.start <= i && i < view->paste_effect.end){ - fade_color = style->main.paste_color; + fade_color = view->paste_effect.color; fade_amount = (real32)(view->paste_effect.tick_down) / view->paste_effect.tick_max; } @@ -2765,7 +2826,69 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act } } - file_view_intbar(thread, target, &bar, view, file, style); + { + Interactive_Bar bar2; + bar2.style = style->main.file_info_style; + bar2.font = style->font; + bar2.pos_x = (real32)rect.x0; + bar2.pos_y = (real32)rect.y0 + 3; + bar2.text_shift_y = 0; + bar2.text_shift_x = 0; + bar2.rect = rect; + bar2.rect.y1 = bar2.rect.y0 + font->height + 2; + + switch (view->state){ + case FVIEW_STATE_SEARCH: + { + draw_rectangle(target, bar2.rect, bar2.style.bar_active_color); + + persist String search_str = make_lit_string("I-Search: "); + persist String rsearch_str = make_lit_string("Reverse-I-Search: "); + if (view->isearch.reverse){ + intbar_draw_string(target, &bar2, rsearch_str, bar2.style.pop1_color); + } + else{ + intbar_draw_string(target, &bar2, search_str, bar2.style.pop1_color); + } + intbar_draw_string(target, &bar2, view->isearch.str, bar2.style.base_color); + }break; + + case FVIEW_STATE_GOTO_LINE: + { + draw_rectangle(target, bar2.rect, bar2.style.bar_active_color); + + persist String gotoline_str = make_lit_string("Goto Line: "); + intbar_draw_string(target, &bar2, gotoline_str, bar2.style.pop1_color); + intbar_draw_string(target, &bar2, view->isearch.str, bar2.style.base_color); + }break; + } + } + + { + u32 back_color = bar.style.bar_color; + draw_rectangle(target, bar.rect, back_color); + + u32 base_color = bar.style.base_color; + intbar_draw_string(target, &bar, file->live_name, base_color); + intbar_draw_string(target, &bar, make_lit_string(" - "), base_color); + + char line_number_space[30]; + String line_number = make_string(line_number_space, 0, 30); + append(&line_number, "L#"); + append_int_to_str(view->cursor.line, &line_number); + + intbar_draw_string(target, &bar, line_number, base_color); + + if (file->last_4ed_write_time != file->last_sys_write_time){ + persist String out_of_sync = make_lit_string(" BEHIND OS"); + intbar_draw_string(target, &bar, out_of_sync, bar.style.pop2_color); + } + else if (file->last_4ed_edit_time > file->last_sys_write_time){ + persist String out_of_sync = make_lit_string(" *"); + intbar_draw_string(target, &bar, out_of_sync, bar.style.pop2_color); + } + } + return 0; } diff --git a/4ed_style.cpp b/4ed_style.cpp index 9ea3f79d..0f818a59 100644 --- a/4ed_style.cpp +++ b/4ed_style.cpp @@ -118,11 +118,97 @@ struct Style_File_Format_v3{ Style_Main_Data_v3 main; }; +struct Style_Main_Data{ + u32 back_color; + u32 margin_color; + u32 margin_hover_color; + u32 margin_active_color; + u32 cursor_color; + u32 at_cursor_color; + u32 highlight_color; + u32 at_highlight_color; + u32 mark_color; + u32 default_color; + u32 comment_color; + u32 keyword_color; + u32 str_constant_color; + u32 char_constant_color; + u32 int_constant_color; + u32 float_constant_color; + u32 bool_constant_color; + u32 preproc_color; + u32 include_color; + u32 special_character_color; + u32 highlight_junk_color; + u32 highlight_white_color; + u32 paste_color; + u32 undo_color; + u32 next_undo_color; + Interactive_Style file_info_style; +}; + +struct Style_File_Format_v4{ + i32 name_size; + char name[24]; + i32 font_name_size; + char font_name[24]; + Style_Main_Data main; +}; + +enum Style_Color_Tag{ + STAG_BAR_COLOR, + STAG_BAR_ACTIVE_COLOR, + STAG_BAR_BASE_COLOR, + STAG_BAR_POP1_COLOR, + STAG_BAR_POP2_COLOR, + STAG_BACK_COLOR, + STAG_MARGIN_COLOR, + STAG_MARGIN_HOVER_COLOR, + STAG_MARGIN_ACTIVE_COLOR, + STAG_CURSOR_COLOR, + STAG_AT_CURSOR_COLOR, + STAG_HIGHLIGHT_COLOR, + STAG_AT_HIGHLIGHT_COLOR, + STAG_MARK_COLOR, + STAG_DEFAULT_COLOR, + STAG_COMMENT_COLOR, + STAG_KEYWORD_COLOR, + STAG_STR_CONSTANT_COLOR, + STAG_CHAR_CONSTANT_COLOR, + STAG_INT_CONSTANT_COLOR, + STAG_FLOAT_CONSTANT_COLOR, + STAG_BOOL_CONSTANT_COLOR, + STAG_PREPROC_COLOR, + STAG_INCLUDE_COLOR, + STAG_SPECIAL_CHARACTER_COLOR, + STAG_HIGHLIGHT_JUNK_COLOR, + STAG_HIGHLIGHT_WHITE_COLOR, + STAG_PASTE_COLOR, + STAG_UNDO_COLOR, + STAG_NEXT_UNDO_COLOR, + // never below this + STAG_COUNT +}; + +struct Style_Color_Specifier{ + u32 tag; + u32 color; +}; + +struct Style_File_Format{ + i32 name_size; + char name[24]; + i32 font_name_size; + char font_name[24]; + + i32 color_specifier_count; +}; + struct Style{ char name_[24]; String name; Font *font; - Style_Main_Data_v3 main; + Style_Main_Data main; bool32 font_changed; }; @@ -232,30 +318,148 @@ style_form_convert(Style_File_Format_v3 *o, Style_File_Format_v2 *i){ o->main.file_info_style = i->main.file_info_style; } -typedef Style_Main_Data_v3 Style_Main_Data; -typedef Style_File_Format_v3 Style_File_Format; - internal void +style_form_convert(Style_File_Format_v4 *o, Style_File_Format_v3 *i){ + o->name_size = i->name_size; + memcpy(o->name, i->name, i->name_size); + o->font_name_size = i->font_name_size; + memcpy(o->font_name, i->font_name, i->font_name_size); + + o->main.back_color = i->main.back_color; + o->main.margin_color = i->main.margin_color; + o->main.margin_hover_color = i->main.margin_hover_color; + o->main.margin_active_color = i->main.margin_active_color; + + o->main.cursor_color = i->main.cursor_color; + o->main.at_cursor_color = i->main.at_cursor_color; + o->main.highlight_color = i->main.highlight_color; + o->main.at_highlight_color = i->main.at_highlight_color; + o->main.mark_color = i->main.mark_color; + o->main.default_color = i->main.default_color; + o->main.comment_color = i->main.comment_color; + o->main.keyword_color = i->main.keyword_color; + o->main.str_constant_color = i->main.str_constant_color; + o->main.char_constant_color = i->main.char_constant_color; + o->main.int_constant_color = i->main.int_constant_color; + o->main.float_constant_color = i->main.float_constant_color; + o->main.bool_constant_color = i->main.bool_constant_color; + o->main.include_color = i->main.include_color; + o->main.preproc_color = i->main.preproc_color; + o->main.special_character_color = i->main.special_character_color; + o->main.highlight_junk_color = i->main.highlight_junk_color; + o->main.highlight_white_color = i->main.highlight_white_color; + o->main.paste_color = i->main.paste_color; + o->main.undo_color = i->main.paste_color ^ 0x00FFFFFF; + o->main.next_undo_color = i->main.paste_color ^ 0x00FFFFFF; + o->main.file_info_style = i->main.file_info_style; + o->main.file_info_style.bar_active_color = i->main.file_info_style.bar_color; +} + +inline u32* +style_index_by_tag(Style *s, u32 tag){ + u32 *result = 0; + switch (tag){ + case STAG_BAR_COLOR: result = &s->main.file_info_style.bar_color; break; + case STAG_BAR_ACTIVE_COLOR: result = &s->main.file_info_style.bar_active_color; break; + case STAG_BAR_BASE_COLOR: result = &s->main.file_info_style.base_color; break; + case STAG_BAR_POP1_COLOR: result = &s->main.file_info_style.pop1_color; break; + case STAG_BAR_POP2_COLOR: result = &s->main.file_info_style.pop2_color; break; + + case STAG_BACK_COLOR: result = &s->main.back_color; break; + case STAG_MARGIN_COLOR: result = &s->main.margin_color; break; + case STAG_MARGIN_HOVER_COLOR: result = &s->main.margin_hover_color; break; + case STAG_MARGIN_ACTIVE_COLOR: result = &s->main.margin_active_color; break; + + case STAG_CURSOR_COLOR: result = &s->main.cursor_color; break; + case STAG_AT_CURSOR_COLOR: result = &s->main.at_cursor_color; break; + case STAG_HIGHLIGHT_COLOR: result = &s->main.highlight_color; break; + case STAG_AT_HIGHLIGHT_COLOR: result = &s->main.at_highlight_color; break; + case STAG_MARK_COLOR: result = &s->main.mark_color; break; + + case STAG_DEFAULT_COLOR: result = &s->main.default_color; break; + case STAG_COMMENT_COLOR: result = &s->main.comment_color; break; + case STAG_KEYWORD_COLOR: result = &s->main.keyword_color; break; + case STAG_STR_CONSTANT_COLOR: result = &s->main.str_constant_color; break; + case STAG_CHAR_CONSTANT_COLOR: result = &s->main.char_constant_color; break; + case STAG_INT_CONSTANT_COLOR: result = &s->main.int_constant_color; break; + case STAG_FLOAT_CONSTANT_COLOR: result = &s->main.float_constant_color; break; + case STAG_BOOL_CONSTANT_COLOR: result = &s->main.bool_constant_color; break; + + case STAG_PREPROC_COLOR: result = &s->main.preproc_color; break; + case STAG_INCLUDE_COLOR: result = &s->main.include_color; break; + + case STAG_SPECIAL_CHARACTER_COLOR: result = &s->main.special_character_color; break; + + case STAG_HIGHLIGHT_JUNK_COLOR: result = &s->main.highlight_junk_color; break; + case STAG_HIGHLIGHT_WHITE_COLOR: result = &s->main.highlight_white_color; break; + + case STAG_PASTE_COLOR: result = &s->main.paste_color; break; + case STAG_UNDO_COLOR: result = &s->main.undo_color; break; + case STAG_NEXT_UNDO_COLOR: result = &s->main.next_undo_color; break; + } + return result; +} + +internal Style_File_Format* style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format *style){ out->name = make_string(out->name_, 0, ArrayCount(out->name_) - 1); out->name_[ArrayCount(out->name_) - 1] = 0; copy(&out->name, style->name); out->font = font_set_extract(fonts, style->font_name, style->font_name_size); + + i32 spec_count = style->color_specifier_count; + Style_Color_Specifier *spec = (Style_Color_Specifier*)(style + 1); + + for (i32 i = 0; i < spec_count; ++i, ++spec){ + u32 *color = style_index_by_tag(out, spec->tag); + if (color) *color = spec->color; + } + +#if 0 // TODO(allen): when new colors are introduced, derive them here. + for (u32 i = 0; i < STAG_COUNT; ++i){ + u32 *color = style_index_by_tag(out, i); + if (color && (*color >> 24) == 0){ + switch (i){ + } + } + } +#endif + + return (Style_File_Format*)(spec); +} + +inline void +style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format_v4 *style){ + out->name = make_string(out->name_, 0, ArrayCount(out->name_) - 1); + out->name_[ArrayCount(out->name_) - 1] = 0; + copy(&out->name, style->name); + out->font = font_set_extract(fonts, style->font_name, style->font_name_size); out->main = style->main; } inline void style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format_v1 *style){ Style_File_Format_v2 form2; - Style_File_Format form; + Style_File_Format_v3 form3; + Style_File_Format_v4 form; style_form_convert(&form2, style); - style_form_convert(&form, &form2); + style_form_convert(&form3, &form2); + style_form_convert(&form, &form3); style_format_for_use(fonts, out, &form); } inline void style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format_v2 *style){ - Style_File_Format form; + Style_File_Format_v3 form3; + Style_File_Format_v4 form; + style_form_convert(&form3, style); + style_form_convert(&form, &form3); + style_format_for_use(fonts, out, &form); +} + +inline void +style_format_for_use(Font_Set *fonts, Style *out, Style_File_Format_v3 *style){ + Style_File_Format_v4 form; style_form_convert(&form, style); style_format_for_use(fonts, out, &form); } @@ -304,6 +508,7 @@ style_library_import(u8 *filename, Font_Set *fonts, Style *out, i32 max, style_format_for_use(fonts, out++, in++); } }break; + case 3: { Style_File_Format_v3 *in = (Style_File_Format_v3*)cursor; @@ -311,6 +516,14 @@ style_library_import(u8 *filename, Font_Set *fonts, Style *out, i32 max, style_format_for_use(fonts, out++, in++); } }break; + case 4: + { + Style_File_Format *in = (Style_File_Format*)cursor; + for (i32 i = 0; i < to_read; ++i){ + in = style_format_for_use(fonts, out++, in); + } + }break; + default: result = 0; break; } @@ -345,21 +558,34 @@ style_library_add(Style_Library *library, Style *style){ return result; } -internal Style_File_Format -style_format_for_file(Style *style){ - Style_File_Format result; +internal Style_File_Format* +style_format_for_file(Style *style, Style_File_Format *out){ Font *font = style->font; - result.name_size = style->name.size; - memcpy(result.name, style->name.str, ArrayCount(result.name)); - result.font_name_size = font->name.size; - memcpy(result.font_name, font->name.str, ArrayCount(result.font_name)); - result.main = style->main; - return result; + out->name_size = style->name.size; + memcpy(out->name, style->name.str, ArrayCount(out->name)); + out->font_name_size = font->name.size; + memcpy(out->font_name, font->name.str, ArrayCount(out->font_name)); + + Style_Color_Specifier *spec = (Style_Color_Specifier*)(out + 1); + i32 count = 0; + + for (u32 i = 0; i < STAG_COUNT; ++i){ + u32 *color = style_index_by_tag(style, i); + if (color){ + spec->tag = i; + spec->color = *color; + ++count; + ++spec; + } + } + out->color_specifier_count = count; + + return (Style_File_Format*)spec; } internal void style_library_export(u8 *filename, Style **styles, i32 count){ - i32 size = count*sizeof(Style_File_Format) + + i32 size = count*(sizeof(Style_File_Format) + STAG_COUNT*sizeof(Style_Color_Specifier)) + sizeof(P4C_Page_Header) + sizeof(Style_Page_Header); void *data = system_get_memory(size); void *cursor = data; @@ -373,7 +599,7 @@ style_library_export(u8 *filename, Style **styles, i32 count){ { Style_Page_Header *h = (Style_Page_Header*)cursor; - h->version = 1; + h->version = 4; h->count = count; cursor = h+1; } @@ -381,7 +607,7 @@ style_library_export(u8 *filename, Style **styles, i32 count){ Style_File_Format *out = (Style_File_Format*)cursor; Style **in = styles; for (i32 i = 0; i < count; ++i){ - *out++ = style_format_for_file(*in++); + out = style_format_for_file(*in++, out); } system_save_file(filename, data, size); system_free_memory(data);