From 295cb0d0a6fa1335fd0484582d0a827f925b37a0 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Thu, 21 Nov 2019 21:37:11 -0800 Subject: [PATCH] All obvious memory leaks fixed - except when profiler is enabled - need to set it to default disabled and fix the inspect ui to still work --- 4ed.cpp | 4 +- 4ed_app_target.cpp | 2 +- 4ed_font_provider_freetype.cpp | 33 +- 4ed_font_set.cpp | 1 + 4ed_system_api.cpp | 6 + custom/4coder_base_types.cpp | 1826 ++++++++++----------- custom/4coder_base_types.h | 18 +- custom/4coder_build_commands.cpp | 6 +- custom/4coder_config.cpp | 6 +- custom/4coder_font_helper.cpp | 6 +- custom/4coder_malloc_allocator.cpp | 2 +- custom/4coder_profile.cpp | 14 +- custom/4coder_profile_inspect.cpp | 111 ++ custom/4coder_profile_inspect.h | 8 + custom/4coder_system_allocator.cpp | 4 +- custom/4coder_system_helpers.cpp | 8 + custom/4coder_system_types.h | 13 + custom/4coder_table.cpp | 30 +- custom/4coder_types.h | 1 - custom/generated/command_metadata.h | 438 ++--- custom/generated/system_api.cpp | 2 + custom/generated/system_api.h | 11 +- custom/generated/system_api_master_list.h | 3 +- platform_win32/win32_4ed.cpp | 6 +- platform_win32/win32_4ed_functions.cpp | 77 +- 25 files changed, 1425 insertions(+), 1211 deletions(-) diff --git a/4ed.cpp b/4ed.cpp index baf3dfbf..c54e5b88 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -334,9 +334,9 @@ App_Init_Sig(app_init){ // NOTE(allen): style setup { + Scratch_Block scratch(tctx); Face_Description description = {}; - description.font.file_name = string_u8_litexpr("liberation-mono.ttf"); - description.font.in_4coder_font_folder = true; + description.font.file_name = get_file_path_in_fonts_folder(scratch, string_u8_litexpr("liberation-mono.ttf")); description.parameters.pt_size = 12; Face *new_face = font_set_new_face(&models->font_set, &description); models->global_face_id = new_face->id; diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index e5aa72ec..538547f3 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -62,10 +62,10 @@ #include "4coder_base_types.cpp" #include "4coder_layout.cpp" -#include "4coder_system_helpers.cpp" #include "4coder_events.cpp" #include "4coder_string_match.cpp" #include "4coder_stringf.cpp" +#include "4coder_system_helpers.cpp" #include "4coder_app_links_allocator.cpp" #include "4coder_system_allocator.cpp" #include "4coder_profile.cpp" diff --git a/4ed_font_provider_freetype.cpp b/4ed_font_provider_freetype.cpp index 1800935f..57dec3ca 100644 --- a/4ed_font_provider_freetype.cpp +++ b/4ed_font_provider_freetype.cpp @@ -100,7 +100,7 @@ ft__get_codepoint_index_map(Base_Allocator *base_allocator, FT_Face face){ return(map); } -struct FT_Bad_Rect_Pack{ +struct Bad_Rect_Pack{ Vec2_i32 max_dim; Vec3_i32 dim; Vec3_i32 p; @@ -108,7 +108,7 @@ struct FT_Bad_Rect_Pack{ }; internal void -ft__bad_rect_pack_init(FT_Bad_Rect_Pack *pack, Vec2_i32 max_dim){ +ft__bad_rect_pack_init(Bad_Rect_Pack *pack, Vec2_i32 max_dim){ pack->max_dim = max_dim; pack->dim = V3i32(0, 0, 1); pack->p = V3i32(0, 0, 0); @@ -116,7 +116,7 @@ ft__bad_rect_pack_init(FT_Bad_Rect_Pack *pack, Vec2_i32 max_dim){ } internal void -ft__bad_rect_pack_end_line(FT_Bad_Rect_Pack *pack){ +ft__bad_rect_pack_end_line(Bad_Rect_Pack *pack){ pack->p.y += pack->current_line_h; pack->dim.y = Max(pack->dim.y, pack->p.y); pack->current_line_h = 0; @@ -124,7 +124,7 @@ ft__bad_rect_pack_end_line(FT_Bad_Rect_Pack *pack){ } internal Vec3_i32 -ft__bad_rect_pack_next(FT_Bad_Rect_Pack *pack, Vec2_i32 dim){ +ft__bad_rect_pack_next(Bad_Rect_Pack *pack, Vec2_i32 dim){ Vec3_i32 result = {}; if (dim.x <= pack->max_dim.x && dim.y <= pack->max_dim.y){ if (pack->current_line_h < dim.y){ @@ -150,7 +150,7 @@ ft__bad_rect_pack_next(FT_Bad_Rect_Pack *pack, Vec2_i32 dim){ } internal void -ft__bad_rect_store_finish(FT_Bad_Rect_Pack *pack){ +ft__bad_rect_store_finish(Bad_Rect_Pack *pack){ ft__bad_rect_pack_end_line(pack); } @@ -162,16 +162,7 @@ ft__glyph_bounds_store_uv_raw(Vec3_i32 p, Vec2_i32 dim, Glyph_Bounds *bounds){ internal Face* ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor){ - String_Const_u8 file_name = {}; - if (description->font.in_4coder_font_folder){ - String_Const_u8 binary_path = system_get_path(arena, SystemPath_Binary); - binary_path = string_mod_replace_character(binary_path, '\\', '/'); - file_name = push_u8_stringf(arena, "%.*sfonts/%.*s", string_expand(binary_path), - string_expand(description->font.file_name)); - } - else{ - file_name = push_string_copy(arena, description->font.file_name); - } + String_Const_u8 file_name = push_string_copy(arena, description->font.file_name); FT_Library ft; FT_Init_FreeType(&ft); @@ -192,7 +183,6 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor FT_Request_Size(ft_face, &size); face->description.font.file_name = file_name; - face->description.font.in_4coder_font_folder = false; face->description.parameters = description->parameters; Face_Metrics *met = &face->metrics; @@ -225,15 +215,16 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor face->advance_map.advance = push_array_zero(arena, f32, index_count); face->bounds = push_array(arena, Glyph_Bounds, index_count); - struct FT_Bitmap{ + Temp_Memory_Block temp_memory(arena); + struct Bitmap{ Vec2_i32 dim; u8 *data; }; - FT_Bitmap *glyph_bitmaps = push_array(arena, FT_Bitmap, index_count); + Bitmap *glyph_bitmaps = push_array(arena, Bitmap, index_count); u32 load_flags = ft__load_flags(hinting); for (u16 i = 0; i < index_count; i += 1){ - FT_Bitmap *bitmap = &glyph_bitmaps[i]; + Bitmap *bitmap = &glyph_bitmaps[i]; error = FT_Load_Glyph(ft_face, i, load_flags); if (error == 0){ @@ -288,11 +279,11 @@ ft__font_make_face(Arena *arena, Face_Description *description, f32 scale_factor 0xFF, 0xFF, 0xFF, 0xFF, }; - FT_Bitmap white = {}; + Bitmap white = {}; white.dim = V2i32(4, 4); white.data = white_data; - FT_Bad_Rect_Pack pack = {}; + Bad_Rect_Pack pack = {}; ft__bad_rect_pack_init(&pack, V2i32(1024, 1024)); ft__glyph_bounds_store_uv_raw(ft__bad_rect_pack_next(&pack, white.dim), white.dim, &face->white); for (u16 i = 0; i < index_count; i += 1){ diff --git a/4ed_font_set.cpp b/4ed_font_set.cpp index 189f07b4..173baba1 100644 --- a/4ed_font_set.cpp +++ b/4ed_font_set.cpp @@ -60,6 +60,7 @@ font_set__alloc_face_slot(Font_Set *set){ internal void font_set__free_face_slot(Font_Set *set, Font_Face_Slot *slot){ if (slot->arena.base_allocator != 0){ + table_free(&slot->face->advance_map.codepoint_to_index.table); linalloc_clear(&slot->arena); } block_zero_struct(slot); diff --git a/4ed_system_api.cpp b/4ed_system_api.cpp index ce70b9f5..9cd6e599 100644 --- a/4ed_system_api.cpp +++ b/4ed_system_api.cpp @@ -230,6 +230,7 @@ define_api(Arena *arena){ { API_Call *call = api_call(arena, api, "memory_allocate", "void*"); api_param(arena, call, "umem", "size"); + api_param(arena, call, "String_Const_u8", "location"); } { @@ -245,6 +246,11 @@ define_api(Arena *arena){ api_param(arena, call, "umem", "size"); } + { + API_Call *call = api_call(arena, api, "memory_annotation", "Memory_Annotation"); + api_param(arena, call, "Arena*", "arena"); + } + { API_Call *call = api_call(arena, api, "show_mouse_cursor", "void"); api_param(arena, call, "i32", "show"); diff --git a/custom/4coder_base_types.cpp b/custom/4coder_base_types.cpp index fa07aaa2..72be5f71 100644 --- a/custom/4coder_base_types.cpp +++ b/custom/4coder_base_types.cpp @@ -2549,926 +2549,6 @@ flip_side(Side side){ //////////////////////////////// -internal void* -base_reserve__noop(void *user_data, umem size, umem *size_out){ - *size_out = 0; - return(0); -} -internal void -base_commit__noop(void *user_data, void *ptr, umem size){} -internal void -base_uncommit__noop(void *user_data, void *ptr, umem size){} -internal void -base_free__noop(void *user_data, void *ptr){} -internal void -base_set_access__noop(void *user_data, void *ptr, umem size, Access_Flag flags){} - -internal Base_Allocator -make_base_allocator(Base_Allocator_Reserve_Signature *func_reserve, - Base_Allocator_Commit_Signature *func_commit, - Base_Allocator_Uncommit_Signature *func_uncommit, - Base_Allocator_Free_Signature *func_free, - Base_Allocator_Set_Access_Signature *func_set_access, - void *user_data){ - if (func_reserve == 0){ - func_reserve = base_reserve__noop; - } - if (func_commit == 0){ - func_commit = base_commit__noop; - } - if (func_uncommit == 0){ - func_uncommit = base_uncommit__noop; - } - if (func_free == 0){ - func_free = base_free__noop; - } - if (func_set_access == 0){ - func_set_access = base_set_access__noop; - } - Base_Allocator base_allocator = { - func_reserve, - func_commit, - func_uncommit, - func_free, - func_set_access, - user_data, - }; - return(base_allocator); -} -internal Data -base_allocate(Base_Allocator *allocator, umem size){ - umem full_size = 0; - void *memory = allocator->reserve(allocator->user_data, size, &full_size); - allocator->commit(allocator->user_data, memory, full_size); - return(make_data(memory, full_size)); -} -internal void -base_free(Base_Allocator *allocator, void *ptr){ - if (ptr != 0){ - allocator->free(allocator->user_data, ptr); - } -} - -#define base_array(a,T,c) (T*)(base_allocate((a), sizeof(T)*(c)).data) - -//////////////////////////////// - -internal Cursor -make_cursor(void *base, umem size){ - Cursor cursor = {(u8*)base, 0, size}; - return(cursor); -} -internal Cursor -make_cursor(Data data){ - return(make_cursor(data.data, data.size)); -} -internal Cursor -make_cursor(Base_Allocator *allocator, umem size){ - Data memory = base_allocate(allocator, size); - return(make_cursor(memory)); -} -internal Data -linalloc_push(Cursor *cursor, umem size){ - Data result = {}; - if (cursor->pos + size <= cursor->cap){ - result.data = cursor->base + cursor->pos; - result.size = size; - cursor->pos += size; - } - return(result); -} -internal void -linalloc_pop(Cursor *cursor, umem size){ - if (cursor->pos > size){ - cursor->pos -= size; - } - else{ - cursor->pos = 0; - } -} -internal Data -linalloc_align(Cursor *cursor, umem alignment){ - umem pos = round_up_umem(cursor->pos, alignment); - umem new_size = pos - cursor->pos; - return(linalloc_push(cursor, new_size)); -} -internal Temp_Memory_Cursor -linalloc_begin_temp(Cursor *cursor){ - Temp_Memory_Cursor temp = {cursor, cursor->pos}; - return(temp); -} -internal void -linalloc_end_temp(Temp_Memory_Cursor temp){ - temp.cursor->pos = temp.pos; -} -internal void -linalloc_clear(Cursor *cursor){ - cursor->pos = 0; -} -internal Arena -make_arena(Base_Allocator *allocator, umem chunk_size, umem alignment){ - Arena arena = {allocator, 0, chunk_size, alignment}; - return(arena); -} -internal Arena -make_arena(Base_Allocator *allocator, umem chunk_size){ - return(make_arena(allocator, chunk_size, 8)); -} -internal Arena -make_arena(Base_Allocator *allocator){ - return(make_arena(allocator, KB(64), 8)); -} -internal Cursor_Node* -arena__new_node(Arena *arena, umem min_size){ - min_size = clamp_bot(min_size, arena->chunk_size); - Data memory = base_allocate(arena->base_allocator, min_size + sizeof(Cursor_Node)); - Cursor_Node *cursor_node = (Cursor_Node*)memory.data; - cursor_node->cursor = make_cursor(cursor_node + 1, memory.size - sizeof(Cursor_Node)); - sll_stack_push(arena->cursor_node, cursor_node); - return(cursor_node); -} -internal Data -linalloc_push(Arena *arena, umem size){ - Data result = {}; - if (size > 0){ - Cursor_Node *cursor_node = arena->cursor_node; - if (cursor_node == 0){ - cursor_node = arena__new_node(arena, size); - } - result = linalloc_push(&cursor_node->cursor, size); - if (result.data == 0){ - cursor_node = arena__new_node(arena, size); - result = linalloc_push(&cursor_node->cursor, size); - } - Data alignment_data = linalloc_align(&cursor_node->cursor, arena->alignment); - result.size += alignment_data.size; - } - return(result); -} -internal void -linalloc_pop(Arena *arena, umem size){ - Base_Allocator *allocator = arena->base_allocator; - Cursor_Node *cursor_node = arena->cursor_node; - for (Cursor_Node *prev = 0; - cursor_node != 0 && size != 0; - cursor_node = prev){ - prev = cursor_node->prev; - if (size >= cursor_node->cursor.pos){ - size -= cursor_node->cursor.pos; - base_free(allocator, cursor_node); - } - else{ - linalloc_pop(&cursor_node->cursor, size); - break; - } - } - arena->cursor_node = cursor_node; -} -internal Data -linalloc_align(Arena *arena, umem alignment){ - arena->alignment = alignment; - Data data = {}; - Cursor_Node *cursor_node = arena->cursor_node; - if (cursor_node != 0){ - data = linalloc_align(&cursor_node->cursor, arena->alignment); - } - return(data); -} -internal Temp_Memory_Arena -linalloc_begin_temp(Arena *arena){ - Cursor_Node *cursor_node = arena->cursor_node; - Temp_Memory_Arena temp = {arena, cursor_node, - cursor_node == 0?0:cursor_node->cursor.pos}; - return(temp); -} -internal void -linalloc_end_temp(Temp_Memory_Arena temp){ - Base_Allocator *allocator = temp.arena->base_allocator; - Cursor_Node *cursor_node = temp.arena->cursor_node; - for (Cursor_Node *prev = 0; - cursor_node != temp.cursor_node && cursor_node != 0; - cursor_node = prev){ - prev = cursor_node->prev; - base_free(allocator, cursor_node); - } - temp.arena->cursor_node = cursor_node; - if (cursor_node != 0){ - if (temp.pos > 0){ - cursor_node->cursor.pos = temp.pos; - } - else{ - temp.arena->cursor_node = cursor_node->prev; - base_free(allocator, cursor_node); - } - } -} -internal void -linalloc_clear(Arena *arena){ - Temp_Memory_Arena temp = {arena, 0, 0}; - linalloc_end_temp(temp); -} -internal void -arena_tap(Arena *arena){ - Cursor_Node *cursor_node = arena->cursor_node; - if (cursor_node == 0){ - arena__new_node(arena, 0); - } - else if (cursor_node->cursor.pos == cursor_node->cursor.cap){ - arena__new_node(arena, 0); - } -} -internal Cursor* -arena_as_cursor(Arena *arena){ - Cursor *cursor = 0; - arena_tap(arena); - Cursor_Node *node = arena->cursor_node; - if (node != 0){ - cursor = &node->cursor; - } - return(cursor); -} -internal void* -linalloc_wrap_unintialized(Data data){ - return(data.data); -} -internal void* -linalloc_wrap_zero(Data data){ - block_zero(data.data, data.size); - return(data.data); -} -internal void* -linalloc_wrap_write(Data data, umem size, void *src){ - block_copy(data.data, src, clamp_top(data.size, size)); - return(data.data); -} -#define push_array(a,T,c) ((T*)linalloc_wrap_unintialized(linalloc_push((a), sizeof(T)*(c)))) -#define push_array_zero(a,T,c) ((T*)linalloc_wrap_zero(linalloc_push((a), sizeof(T)*(c)))) -#define push_array_write(a,T,c,s) ((T*)linalloc_wrap_write(linalloc_push((a), sizeof(T)*(c)), sizeof(T)*(c), (s))) -#define pop_array(a,T,c) (linalloc_pop((a), sizeof(T)*(c))) -#define push_align(a,b) (linalloc_align((a), (b))) -#define push_align_zero(a,b) (linalloc_wrap_zero(linalloc_align((a), (b)))) -internal Temp_Memory -begin_temp(Cursor *cursor){ - Temp_Memory temp = {LinearAllocatorKind_Cursor}; - temp.temp_memory_cursor = linalloc_begin_temp(cursor); - return(temp); -} -internal Temp_Memory -begin_temp(Arena *arena){ - Temp_Memory temp = {LinearAllocatorKind_Arena}; - temp.temp_memory_arena = linalloc_begin_temp(arena); - return(temp); -} -internal void -end_temp(Temp_Memory temp){ - switch (temp.kind){ - case LinearAllocatorKind_Cursor: - { - linalloc_end_temp(temp.temp_memory_cursor); - }break; - case LinearAllocatorKind_Arena: - { - linalloc_end_temp(temp.temp_memory_arena); - }break; - } -} - -//////////////////////////////// - -internal void -thread_ctx_init(Thread_Context *tctx, Thread_Kind kind, Base_Allocator *allocator, - Base_Allocator *prof_allocator){ - block_zero_struct(tctx); - tctx->kind = kind; - tctx->allocator = allocator; - tctx->node_arena = make_arena(allocator, KB(4), 8); - - tctx->prof_allocator = prof_allocator; - tctx->prof_id_counter = 1; - tctx->prof_arena = make_arena(prof_allocator, KB(4)); -} - -internal void -thread_ctx_release(Thread_Context *tctx){ - for (Arena_Node *node = tctx->free_arenas; - node != 0; - node = node->next){ - linalloc_clear(&node->arena); - } - linalloc_clear(&tctx->node_arena); - block_zero_struct(tctx); -} - -internal Arena* -reserve_arena(Thread_Context *tctx, umem chunk_size, umem align){ - Arena_Node *node = tctx->free_arenas; - if (node != 0){ - sll_stack_pop(tctx->free_arenas); - } - else{ - node = push_array_zero(&tctx->node_arena, Arena_Node, 1); - } - node->arena = make_arena(tctx->allocator, chunk_size, align); - return(&node->arena); -} - -internal Arena* -reserve_arena(Thread_Context *tctx, umem chunk_size){ - return(reserve_arena(tctx, chunk_size, 8)); -} - -internal Arena* -reserve_arena(Thread_Context *tctx){ - return(reserve_arena(tctx, KB(64), 8)); -} - -internal void -release_arena(Thread_Context *tctx, Arena *arena){ - Arena_Node *node = CastFromMember(Arena_Node, arena, arena); - linalloc_clear(arena); - sll_stack_push(tctx->free_arenas, node); -} - -//////////////////////////////// - -internal void -scratch_block__init(Scratch_Block *block, Thread_Context *tctx, Scratch_Share_Code share){ - Arena *arena = tctx->sharable_scratch; - if (arena != 0){ - block->arena = arena; - block->temp = begin_temp(arena); - block->do_full_clear = false; - } - else{ - arena = reserve_arena(tctx); - block->arena = arena; - block_zero_struct(&block->temp); - block->do_full_clear = true; - } - block->tctx = tctx; - block->sharable_restore = tctx->sharable_scratch; - if (share == Scratch_Share){ - tctx->sharable_scratch = arena; - } - else{ - tctx->sharable_scratch = 0; - } -} - -global_const Scratch_Share_Code share_code_default = Scratch_DontShare; - -Scratch_Block::Scratch_Block(Thread_Context *tctx, Scratch_Share_Code share){ - scratch_block__init(this, tctx, share); -} - -Scratch_Block::Scratch_Block(Thread_Context *tctx){ - scratch_block__init(this, tctx, share_code_default); -} - -Scratch_Block::~Scratch_Block(){ - if (this->do_full_clear){ - Assert(this->tctx != 0); - release_arena(this->tctx, this->arena); - } - else{ - end_temp(this->temp); - } - if (this->tctx != 0){ - this->tctx->sharable_scratch = this->sharable_restore; - } -} - -Scratch_Block::operator Arena*(){ - return(this->arena); -} - -void -Scratch_Block::restore(void){ - if (this->do_full_clear){ - linalloc_clear(this->arena); - } - else{ - end_temp(this->temp); - } -} - -Temp_Memory_Block::Temp_Memory_Block(Temp_Memory t){ - this->temp = t; -} - -Temp_Memory_Block::Temp_Memory_Block(Arena *arena){ - this->temp = begin_temp(arena); -} - -Temp_Memory_Block::~Temp_Memory_Block(){ - end_temp(this->temp); -} - -void -Temp_Memory_Block::restore(void){ - end_temp(this->temp); -} - -//////////////////////////////// - -#define heap__sent_init(s) (s)->next=(s)->prev=(s) -#define heap__insert_next(p,n) ((n)->next=(p)->next,(n)->prev=(p),(n)->next->prev=(n),(p)->next=(n)) -#define heap__insert_prev(p,n) ((n)->prev=(p)->prev,(n)->next=(p),(n)->prev->next=(n),(p)->prev=(n)) -#define heap__remove(n) ((n)->next->prev=(n)->prev,(n)->prev->next=(n)->next) - -#if defined(DO_HEAP_CHECKS) -internal void -heap_assert_good(Heap *heap){ - if (heap->in_order.next != 0){ - Assert(heap->in_order.prev != 0); - Assert(heap->free_nodes.next != 0); - Assert(heap->free_nodes.prev != 0); - for (Heap_Basic_Node *node = &heap->in_order;;){ - Assert(node->next->prev == node); - Assert(node->prev->next == node); - node = node->next; - if (node == &heap->in_order){ - break; - } - } - for (Heap_Basic_Node *node = &heap->free_nodes;;){ - Assert(node->next->prev == node); - Assert(node->prev->next == node); - node = node->next; - if (node == &heap->free_nodes){ - break; - } - } - } -} -#else -#define heap_assert_good(heap) ((void)(heap)) -#endif - -internal void -heap_init(Heap *heap, Base_Allocator *allocator){ - heap->arena_ = make_arena(allocator); - heap->arena = &heap->arena_; - heap__sent_init(&heap->in_order); - heap__sent_init(&heap->free_nodes); - heap->used_space = 0; - heap->total_space = 0; -} - -internal void -heap_init(Heap *heap, Arena *arena){ - heap->arena = arena; - heap__sent_init(&heap->in_order); - heap__sent_init(&heap->free_nodes); - heap->used_space = 0; - heap->total_space = 0; -} - -internal Base_Allocator* -heap_get_base_allocator(Heap *heap){ - return(heap->arena->base_allocator); -} - -internal void -heap_free_all(Heap *heap){ - if (heap->arena == &heap->arena_){ - linalloc_clear(heap->arena); - } - block_zero_struct(heap); -} - -internal void -heap__extend(Heap *heap, void *memory, umem size){ - heap_assert_good(heap); - if (size >= sizeof(Heap_Node)){ - Heap_Node *new_node = (Heap_Node*)memory; - heap__insert_prev(&heap->in_order, &new_node->order); - heap__insert_next(&heap->free_nodes, &new_node->alloc); - new_node->size = size - sizeof(*new_node); - heap->total_space += size; - } - heap_assert_good(heap); -} - -internal void -heap__extend_automatic(Heap *heap, umem size){ - void *memory = push_array(heap->arena, u8, size); - heap__extend(heap, memory, size); -} - -internal void* -heap__reserve_chunk(Heap *heap, Heap_Node *node, umem size){ - u8 *ptr = (u8*)(node + 1); - Assert(node->size >= size); - umem left_over_size = node->size - size; - if (left_over_size > sizeof(*node)){ - umem new_node_size = left_over_size - sizeof(*node); - Heap_Node *new_node = (Heap_Node*)(ptr + size); - heap__insert_next(&node->order, &new_node->order); - heap__insert_next(&node->alloc, &new_node->alloc); - new_node->size = new_node_size; - } - heap__remove(&node->alloc); - node->alloc.next = 0; - node->alloc.prev = 0; - node->size = size; - heap->used_space += sizeof(*node) + size; - return(ptr); -} - -internal void* -heap_allocate(Heap *heap, umem size){ - b32 first_try = true; - for (;;){ - if (heap->in_order.next != 0){ - heap_assert_good(heap); - umem aligned_size = (size + sizeof(Heap_Node) - 1); - aligned_size = aligned_size - (aligned_size%sizeof(Heap_Node)); - for (Heap_Basic_Node *n = heap->free_nodes.next; - n != &heap->free_nodes; - n = n->next){ - Heap_Node *node = CastFromMember(Heap_Node, alloc, n); - if (node->size >= aligned_size){ - void *ptr = heap__reserve_chunk(heap, node, aligned_size); - heap_assert_good(heap); - return(ptr); - } - } - heap_assert_good(heap); - } - - if (first_try){ - umem extension_size = clamp_bot(KB(64), size*2); - heap__extend_automatic(heap, extension_size); - first_try = false; - } - else{ - break; - } - } - return(0); -} - -internal void -heap__merge(Heap *heap, Heap_Node *l, Heap_Node *r){ - if (&l->order != &heap->in_order && &r->order != &heap->in_order && - l->alloc.next != 0 && l->alloc.prev != 0 && - r->alloc.next != 0 && r->alloc.prev != 0){ - u8 *ptr = (u8*)(l + 1) + l->size; - if (PtrDif(ptr, r) == 0){ - heap__remove(&r->order); - heap__remove(&r->alloc); - heap__remove(&l->alloc); - l->size += r->size + sizeof(*r); - heap__insert_next(&heap->free_nodes, &l->alloc); - } - } -} - -internal void -heap_free(Heap *heap, void *memory){ - if (heap->in_order.next != 0 && memory != 0){ - Heap_Node *node = ((Heap_Node*)memory) - 1; - Assert(node->alloc.next == 0); - Assert(node->alloc.prev == 0); - heap->used_space -= sizeof(*node) + node->size; - heap_assert_good(heap); - heap__insert_next(&heap->free_nodes, &node->alloc); - heap_assert_good(heap); - heap__merge(heap, node, CastFromMember(Heap_Node, order, node->order.next)); - heap_assert_good(heap); - heap__merge(heap, CastFromMember(Heap_Node, order, node->order.prev), node); - heap_assert_good(heap); - } -} - -#define heap_array(heap, T, c) (T*)(heap_allocate((heap), sizeof(T)*(c))) - -//////////////////////////////// - -internal void* -base_reserve__heap(void *user_data, umem size, umem *size_out){ - Heap *heap = (Heap*)user_data; - void *memory = heap_allocate(heap, size); - *size_out = size; - return(memory); -} - -internal void -base_free__heap(void *user_data, void *ptr){ - Heap *heap = (Heap*)user_data; - heap_free(heap, ptr); -} - -internal Base_Allocator -base_allocator_on_heap(Heap *heap){ - return(make_base_allocator(base_reserve__heap, 0, 0, base_free__heap, 0, heap)); -} - -//////////////////////////////// - -internal Data -push_data(Arena *arena, umem size){ - Data result = {}; - result.data = push_array(arena, u8, size); - result.size = size; - return(result); -} - -internal Data -push_data_copy(Arena *arena, Data data){ - Data result = {}; - result.data = push_array_write(arena, u8, data.size, data.data); - result.size = data.size; - return(result); -} - -internal b32 -data_match(Data a, Data b){ - return(a.size == b.size && block_match(a.data, b.data, a.size)); -} - -//////////////////////////////// - -internal b32 -character_is_basic_ascii(char c){ - return(' ' <= c && c <= '~'); -} -internal b32 -character_is_basic_ascii(u8 c){ - return(' ' <= c && c <= '~'); -} -internal b32 -character_is_basic_ascii(u16 c){ - return(' ' <= c && c <= '~'); -} -internal b32 -character_is_basic_ascii(u32 c){ - return(' ' <= c && c <= '~'); -} - -internal b32 -character_is_slash(char c){ - return((c == '/') || (c == '\\')); -} -internal b32 -character_is_slash(u8 c){ - return((c == '/') || (c == '\\')); -} -internal b32 -character_is_slash(u16 c){ - return((c == '/') || (c == '\\')); -} -internal b32 -character_is_slash(u32 c){ - return((c == '/') || (c == '\\')); -} - -internal b32 -character_is_upper(char c){ - return(('A' <= c) && (c <= 'Z')); -} -internal b32 -character_is_upper(u8 c){ - return(('A' <= c) && (c <= 'Z')); -} -internal b32 -character_is_upper(u16 c){ - return(('A' <= c) && (c <= 'Z')); -} -internal b32 -character_is_upper(u32 c){ - return(('A' <= c) && (c <= 'Z')); -} - -internal b32 -character_is_lower(char c){ - return(('a' <= c) && (c <= 'z')); -} -internal b32 -character_is_lower(u8 c){ - return(('a' <= c) && (c <= 'z')); -} -internal b32 -character_is_lower(u16 c){ - return(('a' <= c) && (c <= 'z')); -} -internal b32 -character_is_lower(u32 c){ - return(('a' <= c) && (c <= 'z')); -} - -internal b32 -character_is_lower_unicode(u8 c){ - return((('a' <= c) && (c <= 'z')) || c >= 128); -} -internal b32 -character_is_lower_unicode(u16 c){ - return((('a' <= c) && (c <= 'z')) || c >= 128); -} -internal b32 -character_is_lower_unicode(u32 c){ - return((('a' <= c) && (c <= 'z')) || c >= 128); -} - -internal char -character_to_upper(char c){ - if (('a' <= c) && (c <= 'z')){ - c -= 'a' - 'A'; - } - return(c); -} -internal u8 -character_to_upper(u8 c){ - if (('a' <= c) && (c <= 'z')){ - c -= 'a' - 'A'; - } - return(c); -} -internal u16 -character_to_upper(u16 c){ - if (('a' <= c) && (c <= 'z')){ - c -= 'a' - 'A'; - } - return(c); -} -internal u32 -character_to_upper(u32 c){ - if (('a' <= c) && (c <= 'z')){ - c -= 'a' - 'A'; - } - return(c); -} -internal char -character_to_lower(char c){ - if (('A' <= c) && (c <= 'Z')){ - c += 'a' - 'A'; - } - return(c); -} -internal u8 -character_to_lower(u8 c){ - if (('A' <= c) && (c <= 'Z')){ - c += 'a' - 'A'; - } - return(c); -} -internal u16 -character_to_lower(u16 c){ - if (('A' <= c) && (c <= 'Z')){ - c += 'a' - 'A'; - } - return(c); -} -internal u32 -character_to_lower(u32 c){ - if (('A' <= c) && (c <= 'Z')){ - c += 'a' - 'A'; - } - return(c); -} - -internal b32 -character_is_whitespace(char c){ - return(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); -} -internal b32 -character_is_whitespace(u8 c){ - return(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); -} -internal b32 -character_is_whitespace(u16 c){ - return(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); -} -internal b32 -character_is_whitespace(u32 c){ - return(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); -} - -internal b32 -character_is_base10(char c){ - return('0' <= c && c <= '9'); -} -internal b32 -character_is_base10(u8 c){ - return('0' <= c && c <= '9'); -} -internal b32 -character_is_base10(u16 c){ - return('0' <= c && c <= '9'); -} -internal b32 -character_is_base10(u32 c){ - return('0' <= c && c <= '9'); -} - -internal b32 -character_is_base16(char c){ - return(('0' <= c && c <= '9') || ('A' <= c && c <= 'F')); -} -internal b32 -character_is_base16(u8 c){ - return(('0' <= c && c <= '9') || ('A' <= c && c <= 'F')); -} -internal b32 -character_is_base16(u16 c){ - return(('0' <= c && c <= '9') || ('A' <= c && c <= 'F')); -} -internal b32 -character_is_base16(u32 c){ - return(('0' <= c && c <= '9') || ('A' <= c && c <= 'F')); -} - -internal b32 -character_is_base64(char c){ - return(('0' <= c && c <= '9') || - ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') || - c == '_' || c == '$' || c == '?'); -} -internal b32 -character_is_base64(u8 c){ - return(('0' <= c && c <= '9') || - ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') || - c == '_' || c == '$' || c == '?'); -} -internal b32 -character_is_base64(u16 c){ - return(('0' <= c && c <= '9') || - ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') || - c == '_' || c == '$' || c == '?'); -} -internal b32 -character_is_base64(u32 c){ - return(('0' <= c && c <= '9') || - ('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') || - c == '_' || c == '$' || c == '?'); -} - -internal b32 -character_is_alpha(char c){ - return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_'); -} -internal b32 -character_is_alpha(u8 c){ - return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_'); -} -internal b32 -character_is_alpha(u16 c){ - return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_'); -} -internal b32 -character_is_alpha(u32 c){ - return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_'); -} - -internal b32 -character_is_alpha_numeric(char c){ - return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_'); -} -internal b32 -character_is_alpha_numeric(u8 c){ - return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_'); -} -internal b32 -character_is_alpha_numeric(u16 c){ - return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_'); -} -internal b32 -character_is_alpha_numeric(u32 c){ - return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_'); -} - - -internal b32 -character_is_alpha_unicode(u8 c){ - return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_' || c >= 128); -} -internal b32 -character_is_alpha_unicode(u16 c){ - return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_' || c >= 128); -} -internal b32 -character_is_alpha_unicode(u32 c){ - return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_' || c >= 128); -} - -internal b32 -character_is_alpha_numeric_unicode(u8 c){ - return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_' || c >= 128); -} -internal b32 -character_is_alpha_numeric_unicode(u16 c){ - return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_' || c >= 128); -} -internal b32 -character_is_alpha_numeric_unicode(u32 c){ - return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_' || c >= 128); -} - internal umem cstring_length(char *str){ umem length = 0; @@ -3864,6 +2944,912 @@ SCany(String_Const_u32 str){ internal String_Const_char string_empty = {"", 0}; internal String_Const_u8 string_u8_empty = {"", 0}; +#define file_name_line_number_lit_u8 string_u8_litexpr(file_name_line_number) + +//////////////////////////////// + +internal void* +base_reserve__noop(void *user_data, umem size, umem *size_out, String_Const_u8 location){ + *size_out = 0; + return(0); +} +internal void +base_commit__noop(void *user_data, void *ptr, umem size){} +internal void +base_uncommit__noop(void *user_data, void *ptr, umem size){} +internal void +base_free__noop(void *user_data, void *ptr){} +internal void +base_set_access__noop(void *user_data, void *ptr, umem size, Access_Flag flags){} + +internal Base_Allocator +make_base_allocator(Base_Allocator_Reserve_Signature *func_reserve, + Base_Allocator_Commit_Signature *func_commit, + Base_Allocator_Uncommit_Signature *func_uncommit, + Base_Allocator_Free_Signature *func_free, + Base_Allocator_Set_Access_Signature *func_set_access, + void *user_data){ + if (func_reserve == 0){ + func_reserve = base_reserve__noop; + } + if (func_commit == 0){ + func_commit = base_commit__noop; + } + if (func_uncommit == 0){ + func_uncommit = base_uncommit__noop; + } + if (func_free == 0){ + func_free = base_free__noop; + } + if (func_set_access == 0){ + func_set_access = base_set_access__noop; + } + Base_Allocator base_allocator = { + func_reserve, + func_commit, + func_uncommit, + func_free, + func_set_access, + user_data, + }; + return(base_allocator); +} +internal Data +base_allocate__inner(Base_Allocator *allocator, umem size, String_Const_u8 location){ + umem full_size = 0; + void *memory = allocator->reserve(allocator->user_data, size, &full_size, location); + allocator->commit(allocator->user_data, memory, full_size); + return(make_data(memory, full_size)); +} +internal void +base_free(Base_Allocator *allocator, void *ptr){ + if (ptr != 0){ + allocator->free(allocator->user_data, ptr); + } +} + +#define base_allocate(a,s) base_allocate__inner((a), (s), file_name_line_number_lit_u8) +#define base_array_loc(a,T,c,l) (T*)(base_allocate__inner((a), sizeof(T)*(c), (l)).data) +#define base_array(a,T,c) base_array_loc(a,T,c, file_name_line_number_lit_u8) + +//////////////////////////////// + +internal Cursor +make_cursor(void *base, umem size){ + Cursor cursor = {(u8*)base, 0, size}; + return(cursor); +} +internal Cursor +make_cursor(Data data){ + return(make_cursor(data.data, data.size)); +} +internal Cursor +make_cursor(Base_Allocator *allocator, umem size){ + Data memory = base_allocate(allocator, size); + return(make_cursor(memory)); +} +internal Data +linalloc_push(Cursor *cursor, umem size, String_Const_u8 location){ + Data result = {}; + if (cursor->pos + size <= cursor->cap){ + result.data = cursor->base + cursor->pos; + result.size = size; + cursor->pos += size; + } + return(result); +} +internal void +linalloc_pop(Cursor *cursor, umem size){ + if (cursor->pos > size){ + cursor->pos -= size; + } + else{ + cursor->pos = 0; + } +} +internal Data +linalloc_align(Cursor *cursor, umem alignment){ + umem pos = round_up_umem(cursor->pos, alignment); + umem new_size = pos - cursor->pos; + return(linalloc_push(cursor, new_size, file_name_line_number_lit_u8)); +} +internal Temp_Memory_Cursor +linalloc_begin_temp(Cursor *cursor){ + Temp_Memory_Cursor temp = {cursor, cursor->pos}; + return(temp); +} +internal void +linalloc_end_temp(Temp_Memory_Cursor temp){ + temp.cursor->pos = temp.pos; +} +internal void +linalloc_clear(Cursor *cursor){ + cursor->pos = 0; +} +internal Arena +make_arena(Base_Allocator *allocator, umem chunk_size, umem alignment){ + Arena arena = {allocator, 0, chunk_size, alignment}; + return(arena); +} +internal Arena +make_arena(Base_Allocator *allocator, umem chunk_size){ + return(make_arena(allocator, chunk_size, 8)); +} +internal Arena +make_arena(Base_Allocator *allocator){ + return(make_arena(allocator, KB(64), 8)); +} +internal Cursor_Node* +arena__new_node(Arena *arena, umem min_size, String_Const_u8 location){ + min_size = clamp_bot(min_size, arena->chunk_size); + Data memory = base_allocate__inner(arena->base_allocator, min_size + sizeof(Cursor_Node), location); + Cursor_Node *cursor_node = (Cursor_Node*)memory.data; + cursor_node->cursor = make_cursor(cursor_node + 1, memory.size - sizeof(Cursor_Node)); + sll_stack_push(arena->cursor_node, cursor_node); + return(cursor_node); +} +internal Data +linalloc_push(Arena *arena, umem size, String_Const_u8 location){ + Data result = {}; + if (size > 0){ + Cursor_Node *cursor_node = arena->cursor_node; + if (cursor_node == 0){ + cursor_node = arena__new_node(arena, size, location); + } + result = linalloc_push(&cursor_node->cursor, size, location); + if (result.data == 0){ + cursor_node = arena__new_node(arena, size, location); + result = linalloc_push(&cursor_node->cursor, size, location); + } + Data alignment_data = linalloc_align(&cursor_node->cursor, arena->alignment); + result.size += alignment_data.size; + } + return(result); +} +internal void +linalloc_pop(Arena *arena, umem size){ + Base_Allocator *allocator = arena->base_allocator; + Cursor_Node *cursor_node = arena->cursor_node; + for (Cursor_Node *prev = 0; + cursor_node != 0 && size != 0; + cursor_node = prev){ + prev = cursor_node->prev; + if (size >= cursor_node->cursor.pos){ + size -= cursor_node->cursor.pos; + base_free(allocator, cursor_node); + } + else{ + linalloc_pop(&cursor_node->cursor, size); + break; + } + } + arena->cursor_node = cursor_node; +} +internal Data +linalloc_align(Arena *arena, umem alignment){ + arena->alignment = alignment; + Data data = {}; + Cursor_Node *cursor_node = arena->cursor_node; + if (cursor_node != 0){ + data = linalloc_align(&cursor_node->cursor, arena->alignment); + } + return(data); +} +internal Temp_Memory_Arena +linalloc_begin_temp(Arena *arena){ + Cursor_Node *cursor_node = arena->cursor_node; + Temp_Memory_Arena temp = {arena, cursor_node, + cursor_node == 0?0:cursor_node->cursor.pos}; + return(temp); +} +internal void +linalloc_end_temp(Temp_Memory_Arena temp){ + Base_Allocator *allocator = temp.arena->base_allocator; + Cursor_Node *cursor_node = temp.arena->cursor_node; + for (Cursor_Node *prev = 0; + cursor_node != temp.cursor_node && cursor_node != 0; + cursor_node = prev){ + prev = cursor_node->prev; + base_free(allocator, cursor_node); + } + temp.arena->cursor_node = cursor_node; + if (cursor_node != 0){ + if (temp.pos > 0){ + cursor_node->cursor.pos = temp.pos; + } + else{ + temp.arena->cursor_node = cursor_node->prev; + base_free(allocator, cursor_node); + } + } +} +internal void +linalloc_clear(Arena *arena){ + Temp_Memory_Arena temp = {arena, 0, 0}; + linalloc_end_temp(temp); +} +internal void* +linalloc_wrap_unintialized(Data data){ + return(data.data); +} +internal void* +linalloc_wrap_zero(Data data){ + block_zero(data.data, data.size); + return(data.data); +} +internal void* +linalloc_wrap_write(Data data, umem size, void *src){ + block_copy(data.data, src, clamp_top(data.size, size)); + return(data.data); +} +#define push_array(a,T,c) ((T*)linalloc_wrap_unintialized(linalloc_push((a), sizeof(T)*(c), file_name_line_number_lit_u8))) +#define push_array_zero(a,T,c) ((T*)linalloc_wrap_zero(linalloc_push((a), sizeof(T)*(c), file_name_line_number_lit_u8))) +#define push_array_write(a,T,c,s) ((T*)linalloc_wrap_write(linalloc_push((a), sizeof(T)*(c), file_name_line_number_lit_u8), sizeof(T)*(c), (s))) +#define pop_array(a,T,c) (linalloc_pop((a), sizeof(T)*(c))) +#define push_align(a,b) (linalloc_align((a), (b))) +#define push_align_zero(a,b) (linalloc_wrap_zero(linalloc_align((a), (b)))) +internal Temp_Memory +begin_temp(Cursor *cursor){ + Temp_Memory temp = {LinearAllocatorKind_Cursor}; + temp.temp_memory_cursor = linalloc_begin_temp(cursor); + return(temp); +} +internal Temp_Memory +begin_temp(Arena *arena){ + Temp_Memory temp = {LinearAllocatorKind_Arena}; + temp.temp_memory_arena = linalloc_begin_temp(arena); + return(temp); +} +internal void +end_temp(Temp_Memory temp){ + switch (temp.kind){ + case LinearAllocatorKind_Cursor: + { + linalloc_end_temp(temp.temp_memory_cursor); + }break; + case LinearAllocatorKind_Arena: + { + linalloc_end_temp(temp.temp_memory_arena); + }break; + } +} + +//////////////////////////////// + +internal void +thread_ctx_init(Thread_Context *tctx, Thread_Kind kind, Base_Allocator *allocator, + Base_Allocator *prof_allocator){ + block_zero_struct(tctx); + tctx->kind = kind; + tctx->allocator = allocator; + tctx->node_arena = make_arena(allocator, KB(4), 8); + + tctx->prof_allocator = prof_allocator; + tctx->prof_id_counter = 1; + tctx->prof_arena = make_arena(prof_allocator, KB(16)); +} + +internal void +thread_ctx_release(Thread_Context *tctx){ + for (Arena_Node *node = tctx->free_arenas; + node != 0; + node = node->next){ + linalloc_clear(&node->arena); + } + linalloc_clear(&tctx->node_arena); + block_zero_struct(tctx); +} + +internal Arena* +reserve_arena(Thread_Context *tctx, umem chunk_size, umem align){ + Arena_Node *node = tctx->free_arenas; + if (node != 0){ + sll_stack_pop(tctx->free_arenas); + } + else{ + node = push_array_zero(&tctx->node_arena, Arena_Node, 1); + } + node->arena = make_arena(tctx->allocator, chunk_size, align); + return(&node->arena); +} + +internal Arena* +reserve_arena(Thread_Context *tctx, umem chunk_size){ + return(reserve_arena(tctx, chunk_size, 8)); +} + +internal Arena* +reserve_arena(Thread_Context *tctx){ + return(reserve_arena(tctx, KB(64), 8)); +} + +internal void +release_arena(Thread_Context *tctx, Arena *arena){ + Arena_Node *node = CastFromMember(Arena_Node, arena, arena); + linalloc_clear(arena); + sll_stack_push(tctx->free_arenas, node); +} + +//////////////////////////////// + +internal void +scratch_block__init(Scratch_Block *block, Thread_Context *tctx, Scratch_Share_Code share){ + Arena *arena = tctx->sharable_scratch; + if (arena != 0){ + block->arena = arena; + block->temp = begin_temp(arena); + block->do_full_clear = false; + } + else{ + arena = reserve_arena(tctx); + block->arena = arena; + block_zero_struct(&block->temp); + block->do_full_clear = true; + } + block->tctx = tctx; + block->sharable_restore = tctx->sharable_scratch; + if (share == Scratch_Share){ + tctx->sharable_scratch = arena; + } + else{ + tctx->sharable_scratch = 0; + } +} + +global_const Scratch_Share_Code share_code_default = Scratch_DontShare; + +Scratch_Block::Scratch_Block(Thread_Context *tctx, Scratch_Share_Code share){ + scratch_block__init(this, tctx, share); +} + +Scratch_Block::Scratch_Block(Thread_Context *tctx){ + scratch_block__init(this, tctx, share_code_default); +} + +Scratch_Block::~Scratch_Block(){ + if (this->do_full_clear){ + Assert(this->tctx != 0); + release_arena(this->tctx, this->arena); + } + else{ + end_temp(this->temp); + } + if (this->tctx != 0){ + this->tctx->sharable_scratch = this->sharable_restore; + } +} + +Scratch_Block::operator Arena*(){ + return(this->arena); +} + +void +Scratch_Block::restore(void){ + if (this->do_full_clear){ + linalloc_clear(this->arena); + } + else{ + end_temp(this->temp); + } +} + +Temp_Memory_Block::Temp_Memory_Block(Temp_Memory t){ + this->temp = t; +} + +Temp_Memory_Block::Temp_Memory_Block(Arena *arena){ + this->temp = begin_temp(arena); +} + +Temp_Memory_Block::~Temp_Memory_Block(){ + end_temp(this->temp); +} + +void +Temp_Memory_Block::restore(void){ + end_temp(this->temp); +} + +//////////////////////////////// + +#define heap__sent_init(s) (s)->next=(s)->prev=(s) +#define heap__insert_next(p,n) ((n)->next=(p)->next,(n)->prev=(p),(n)->next->prev=(n),(p)->next=(n)) +#define heap__insert_prev(p,n) ((n)->prev=(p)->prev,(n)->next=(p),(n)->prev->next=(n),(p)->prev=(n)) +#define heap__remove(n) ((n)->next->prev=(n)->prev,(n)->prev->next=(n)->next) + +#if defined(DO_HEAP_CHECKS) +internal void +heap_assert_good(Heap *heap){ + if (heap->in_order.next != 0){ + Assert(heap->in_order.prev != 0); + Assert(heap->free_nodes.next != 0); + Assert(heap->free_nodes.prev != 0); + for (Heap_Basic_Node *node = &heap->in_order;;){ + Assert(node->next->prev == node); + Assert(node->prev->next == node); + node = node->next; + if (node == &heap->in_order){ + break; + } + } + for (Heap_Basic_Node *node = &heap->free_nodes;;){ + Assert(node->next->prev == node); + Assert(node->prev->next == node); + node = node->next; + if (node == &heap->free_nodes){ + break; + } + } + } +} +#else +#define heap_assert_good(heap) ((void)(heap)) +#endif + +internal void +heap_init(Heap *heap, Base_Allocator *allocator){ + heap->arena_ = make_arena(allocator); + heap->arena = &heap->arena_; + heap__sent_init(&heap->in_order); + heap__sent_init(&heap->free_nodes); + heap->used_space = 0; + heap->total_space = 0; +} + +internal void +heap_init(Heap *heap, Arena *arena){ + heap->arena = arena; + heap__sent_init(&heap->in_order); + heap__sent_init(&heap->free_nodes); + heap->used_space = 0; + heap->total_space = 0; +} + +internal Base_Allocator* +heap_get_base_allocator(Heap *heap){ + return(heap->arena->base_allocator); +} + +internal void +heap_free_all(Heap *heap){ + if (heap->arena == &heap->arena_){ + linalloc_clear(heap->arena); + } + block_zero_struct(heap); +} + +internal void +heap__extend(Heap *heap, void *memory, umem size){ + heap_assert_good(heap); + if (size >= sizeof(Heap_Node)){ + Heap_Node *new_node = (Heap_Node*)memory; + heap__insert_prev(&heap->in_order, &new_node->order); + heap__insert_next(&heap->free_nodes, &new_node->alloc); + new_node->size = size - sizeof(*new_node); + heap->total_space += size; + } + heap_assert_good(heap); +} + +internal void +heap__extend_automatic(Heap *heap, umem size){ + void *memory = push_array(heap->arena, u8, size); + heap__extend(heap, memory, size); +} + +internal void* +heap__reserve_chunk(Heap *heap, Heap_Node *node, umem size){ + u8 *ptr = (u8*)(node + 1); + Assert(node->size >= size); + umem left_over_size = node->size - size; + if (left_over_size > sizeof(*node)){ + umem new_node_size = left_over_size - sizeof(*node); + Heap_Node *new_node = (Heap_Node*)(ptr + size); + heap__insert_next(&node->order, &new_node->order); + heap__insert_next(&node->alloc, &new_node->alloc); + new_node->size = new_node_size; + } + heap__remove(&node->alloc); + node->alloc.next = 0; + node->alloc.prev = 0; + node->size = size; + heap->used_space += sizeof(*node) + size; + return(ptr); +} + +internal void* +heap_allocate(Heap *heap, umem size){ + b32 first_try = true; + for (;;){ + if (heap->in_order.next != 0){ + heap_assert_good(heap); + umem aligned_size = (size + sizeof(Heap_Node) - 1); + aligned_size = aligned_size - (aligned_size%sizeof(Heap_Node)); + for (Heap_Basic_Node *n = heap->free_nodes.next; + n != &heap->free_nodes; + n = n->next){ + Heap_Node *node = CastFromMember(Heap_Node, alloc, n); + if (node->size >= aligned_size){ + void *ptr = heap__reserve_chunk(heap, node, aligned_size); + heap_assert_good(heap); + return(ptr); + } + } + heap_assert_good(heap); + } + + if (first_try){ + umem extension_size = clamp_bot(KB(64), size*2); + heap__extend_automatic(heap, extension_size); + first_try = false; + } + else{ + break; + } + } + return(0); +} + +internal void +heap__merge(Heap *heap, Heap_Node *l, Heap_Node *r){ + if (&l->order != &heap->in_order && &r->order != &heap->in_order && + l->alloc.next != 0 && l->alloc.prev != 0 && + r->alloc.next != 0 && r->alloc.prev != 0){ + u8 *ptr = (u8*)(l + 1) + l->size; + if (PtrDif(ptr, r) == 0){ + heap__remove(&r->order); + heap__remove(&r->alloc); + heap__remove(&l->alloc); + l->size += r->size + sizeof(*r); + heap__insert_next(&heap->free_nodes, &l->alloc); + } + } +} + +internal void +heap_free(Heap *heap, void *memory){ + if (heap->in_order.next != 0 && memory != 0){ + Heap_Node *node = ((Heap_Node*)memory) - 1; + Assert(node->alloc.next == 0); + Assert(node->alloc.prev == 0); + heap->used_space -= sizeof(*node) + node->size; + heap_assert_good(heap); + heap__insert_next(&heap->free_nodes, &node->alloc); + heap_assert_good(heap); + heap__merge(heap, node, CastFromMember(Heap_Node, order, node->order.next)); + heap_assert_good(heap); + heap__merge(heap, CastFromMember(Heap_Node, order, node->order.prev), node); + heap_assert_good(heap); + } +} + +#define heap_array(heap, T, c) (T*)(heap_allocate((heap), sizeof(T)*(c))) + +//////////////////////////////// + +internal void* +base_reserve__heap(void *user_data, umem size, umem *size_out, String_Const_u8 location){ + Heap *heap = (Heap*)user_data; + void *memory = heap_allocate(heap, size); + *size_out = size; + return(memory); +} + +internal void +base_free__heap(void *user_data, void *ptr){ + Heap *heap = (Heap*)user_data; + heap_free(heap, ptr); +} + +internal Base_Allocator +base_allocator_on_heap(Heap *heap){ + return(make_base_allocator(base_reserve__heap, 0, 0, base_free__heap, 0, heap)); +} + +//////////////////////////////// + +internal Data +push_data(Arena *arena, umem size){ + Data result = {}; + result.data = push_array(arena, u8, size); + result.size = size; + return(result); +} + +internal Data +push_data_copy(Arena *arena, Data data){ + Data result = {}; + result.data = push_array_write(arena, u8, data.size, data.data); + result.size = data.size; + return(result); +} + +internal b32 +data_match(Data a, Data b){ + return(a.size == b.size && block_match(a.data, b.data, a.size)); +} + +//////////////////////////////// + +internal b32 +character_is_basic_ascii(char c){ + return(' ' <= c && c <= '~'); +} +internal b32 +character_is_basic_ascii(u8 c){ + return(' ' <= c && c <= '~'); +} +internal b32 +character_is_basic_ascii(u16 c){ + return(' ' <= c && c <= '~'); +} +internal b32 +character_is_basic_ascii(u32 c){ + return(' ' <= c && c <= '~'); +} + +internal b32 +character_is_slash(char c){ + return((c == '/') || (c == '\\')); +} +internal b32 +character_is_slash(u8 c){ + return((c == '/') || (c == '\\')); +} +internal b32 +character_is_slash(u16 c){ + return((c == '/') || (c == '\\')); +} +internal b32 +character_is_slash(u32 c){ + return((c == '/') || (c == '\\')); +} + +internal b32 +character_is_upper(char c){ + return(('A' <= c) && (c <= 'Z')); +} +internal b32 +character_is_upper(u8 c){ + return(('A' <= c) && (c <= 'Z')); +} +internal b32 +character_is_upper(u16 c){ + return(('A' <= c) && (c <= 'Z')); +} +internal b32 +character_is_upper(u32 c){ + return(('A' <= c) && (c <= 'Z')); +} + +internal b32 +character_is_lower(char c){ + return(('a' <= c) && (c <= 'z')); +} +internal b32 +character_is_lower(u8 c){ + return(('a' <= c) && (c <= 'z')); +} +internal b32 +character_is_lower(u16 c){ + return(('a' <= c) && (c <= 'z')); +} +internal b32 +character_is_lower(u32 c){ + return(('a' <= c) && (c <= 'z')); +} + +internal b32 +character_is_lower_unicode(u8 c){ + return((('a' <= c) && (c <= 'z')) || c >= 128); +} +internal b32 +character_is_lower_unicode(u16 c){ + return((('a' <= c) && (c <= 'z')) || c >= 128); +} +internal b32 +character_is_lower_unicode(u32 c){ + return((('a' <= c) && (c <= 'z')) || c >= 128); +} + +internal char +character_to_upper(char c){ + if (('a' <= c) && (c <= 'z')){ + c -= 'a' - 'A'; + } + return(c); +} +internal u8 +character_to_upper(u8 c){ + if (('a' <= c) && (c <= 'z')){ + c -= 'a' - 'A'; + } + return(c); +} +internal u16 +character_to_upper(u16 c){ + if (('a' <= c) && (c <= 'z')){ + c -= 'a' - 'A'; + } + return(c); +} +internal u32 +character_to_upper(u32 c){ + if (('a' <= c) && (c <= 'z')){ + c -= 'a' - 'A'; + } + return(c); +} +internal char +character_to_lower(char c){ + if (('A' <= c) && (c <= 'Z')){ + c += 'a' - 'A'; + } + return(c); +} +internal u8 +character_to_lower(u8 c){ + if (('A' <= c) && (c <= 'Z')){ + c += 'a' - 'A'; + } + return(c); +} +internal u16 +character_to_lower(u16 c){ + if (('A' <= c) && (c <= 'Z')){ + c += 'a' - 'A'; + } + return(c); +} +internal u32 +character_to_lower(u32 c){ + if (('A' <= c) && (c <= 'Z')){ + c += 'a' - 'A'; + } + return(c); +} + +internal b32 +character_is_whitespace(char c){ + return(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); +} +internal b32 +character_is_whitespace(u8 c){ + return(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); +} +internal b32 +character_is_whitespace(u16 c){ + return(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); +} +internal b32 +character_is_whitespace(u32 c){ + return(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v'); +} + +internal b32 +character_is_base10(char c){ + return('0' <= c && c <= '9'); +} +internal b32 +character_is_base10(u8 c){ + return('0' <= c && c <= '9'); +} +internal b32 +character_is_base10(u16 c){ + return('0' <= c && c <= '9'); +} +internal b32 +character_is_base10(u32 c){ + return('0' <= c && c <= '9'); +} + +internal b32 +character_is_base16(char c){ + return(('0' <= c && c <= '9') || ('A' <= c && c <= 'F')); +} +internal b32 +character_is_base16(u8 c){ + return(('0' <= c && c <= '9') || ('A' <= c && c <= 'F')); +} +internal b32 +character_is_base16(u16 c){ + return(('0' <= c && c <= '9') || ('A' <= c && c <= 'F')); +} +internal b32 +character_is_base16(u32 c){ + return(('0' <= c && c <= '9') || ('A' <= c && c <= 'F')); +} + +internal b32 +character_is_base64(char c){ + return(('0' <= c && c <= '9') || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + c == '_' || c == '$' || c == '?'); +} +internal b32 +character_is_base64(u8 c){ + return(('0' <= c && c <= '9') || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + c == '_' || c == '$' || c == '?'); +} +internal b32 +character_is_base64(u16 c){ + return(('0' <= c && c <= '9') || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + c == '_' || c == '$' || c == '?'); +} +internal b32 +character_is_base64(u32 c){ + return(('0' <= c && c <= '9') || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + c == '_' || c == '$' || c == '?'); +} + +internal b32 +character_is_alpha(char c){ + return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_'); +} +internal b32 +character_is_alpha(u8 c){ + return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_'); +} +internal b32 +character_is_alpha(u16 c){ + return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_'); +} +internal b32 +character_is_alpha(u32 c){ + return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_'); +} + +internal b32 +character_is_alpha_numeric(char c){ + return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_'); +} +internal b32 +character_is_alpha_numeric(u8 c){ + return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_'); +} +internal b32 +character_is_alpha_numeric(u16 c){ + return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_'); +} +internal b32 +character_is_alpha_numeric(u32 c){ + return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_'); +} + + +internal b32 +character_is_alpha_unicode(u8 c){ + return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_' || c >= 128); +} +internal b32 +character_is_alpha_unicode(u16 c){ + return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_' || c >= 128); +} +internal b32 +character_is_alpha_unicode(u32 c){ + return( (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || c == '_' || c >= 128); +} + +internal b32 +character_is_alpha_numeric_unicode(u8 c){ + return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_' || c >= 128); +} +internal b32 +character_is_alpha_numeric_unicode(u16 c){ + return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_' || c >= 128); +} +internal b32 +character_is_alpha_numeric_unicode(u32 c){ + return((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9')) || c == '_' || c >= 128); +} + internal char string_get_character(String_Const_char str, umem i){ char r = 0; diff --git a/custom/4coder_base_types.h b/custom/4coder_base_types.h index 686795ab..fe69b06f 100644 --- a/custom/4coder_base_types.h +++ b/custom/4coder_base_types.h @@ -206,6 +206,18 @@ enum{ #define Stmnt(s) do{ s }while(0) +// NOTE(allen): Assert notes: +// Break = the run time implementation of break +// - replace this to get fancier behavior on assert +// Always = assert that is not compiled out in SHIP_MODE +// - helpful for debugging specific issues +// - used rarely in normal code +// Message = unconditional asserts with an attached message +// - InvalidPath version for paths of a switch or if-else dispatch that should always be unreachable +// - NotImplemented version for stubs functions that are not yet completed +// Static = asserts that contain only compile time constants and become compilation errors +// Disambiguate = for static asserts that happen to have name conflicts + #define AssertBreak(m) (*((i32*)0) = 0xA11E) #define AssertAlways(c) Stmnt( if (!(c)) { AssertBreak(c); } ) #define AssertMessageAlways(m) AssertBreak(m) @@ -305,8 +317,8 @@ global_const f32 half_pi_f32 = 1.5707963267f; #define clamp_unsigned_to_u32(x) (u32)(clamp_top((u64)(x), (u64)u32_max)) #define clamp_unsigned_to_u64(x) (u64)(clamp_top((u64)(x), (u64)u64_max)) -#define LINE_STR__ stringify(__LINE__) -#define file_name_line_number __FILE__ ":" LINE_STR__ ":" +#define line_number_as_string stringify(__LINE__) +#define file_name_line_number __FILE__ ":" line_number_as_string ":" #define require(c) Stmnt( if (!(c)){ return(0); } ) @@ -1074,7 +1086,7 @@ enum{ //////////////////////////////// -typedef void *Base_Allocator_Reserve_Signature(void *user_data, umem size, umem *size_out); +typedef void *Base_Allocator_Reserve_Signature(void *user_data, umem size, umem *size_out, String_Const_u8 location); typedef void Base_Allocator_Commit_Signature(void *user_data, void *ptr, umem size); typedef void Base_Allocator_Uncommit_Signature(void *user_data, void *ptr, umem size); typedef void Base_Allocator_Free_Signature(void *user_data, void *ptr); diff --git a/custom/4coder_build_commands.cpp b/custom/4coder_build_commands.cpp index 96f8d04a..cc7e6dc1 100644 --- a/custom/4coder_build_commands.cpp +++ b/custom/4coder_build_commands.cpp @@ -153,10 +153,12 @@ get_or_open_build_panel(Application_Links *app){ return(view); } -static void + function void set_fancy_compilation_buffer_font(Application_Links *app){ Buffer_ID buffer = get_comp_buffer(app); - Font_Load_Location font = { string_u8_litexpr("Inconsolata-Regular.ttf"), true, }; + Font_Load_Location font = {}; + Scratch_Block scratch(app); + font.file_name = get_file_path_in_fonts_folder(scratch, string_u8_litexpr("Inconsolata-Regular.ttf")); set_buffer_face_by_font_load_location(app, buffer, &font); } diff --git a/custom/4coder_config.cpp b/custom/4coder_config.cpp index b1a71b91..17026e08 100644 --- a/custom/4coder_config.cpp +++ b/custom/4coder_config.cpp @@ -1548,7 +1548,6 @@ load_config_and_apply(Application_Links *app, Arena *out_arena, Config_Data *con //change_theme(app, config->default_theme_name.str, config->default_theme_name.size); Face_Description description = {}; - description.font.file_name = config->default_font_name; if (override_font_size != 0){ description.parameters.pt_size = override_font_size; } @@ -1556,9 +1555,10 @@ load_config_and_apply(Application_Links *app, Arena *out_arena, Config_Data *con description.parameters.pt_size = config->default_font_size; } description.parameters.hinting = config->default_font_hinting || override_hinting; - description.font.in_4coder_font_folder = true; + + description.font.file_name = config->default_font_name; if (!modify_global_face_by_description(app, description)){ - description.font.in_4coder_font_folder = false; + description.font.file_name = get_file_path_in_fonts_folder(scratch, config->default_font_name); modify_global_face_by_description(app, description); } } diff --git a/custom/4coder_font_helper.cpp b/custom/4coder_font_helper.cpp index 16033078..76225835 100644 --- a/custom/4coder_font_helper.cpp +++ b/custom/4coder_font_helper.cpp @@ -21,11 +21,7 @@ get_global_face_description(Application_Links *app){ internal b32 font_load_location_match(Font_Load_Location *a, Font_Load_Location *b){ - b32 result = false; - if (string_match(a->file_name, b->file_name) && a->in_4coder_font_folder == b->in_4coder_font_folder){ - result = true; - } - return(result); + return(string_match(a->file_name, b->file_name)); } internal b32 diff --git a/custom/4coder_malloc_allocator.cpp b/custom/4coder_malloc_allocator.cpp index 40ebfa83..6eeec41d 100644 --- a/custom/4coder_malloc_allocator.cpp +++ b/custom/4coder_malloc_allocator.cpp @@ -8,7 +8,7 @@ #include internal void* -base_reserve__malloc(void *user_data, umem size, umem *size_out){ +base_reserve__malloc(void *user_data, umem size, umem *size_out, String_Const_u8 location){ *size_out = size; return(malloc(size)); } diff --git a/custom/4coder_profile.cpp b/custom/4coder_profile.cpp index 68f41da3..3437c77d 100644 --- a/custom/4coder_profile.cpp +++ b/custom/4coder_profile.cpp @@ -57,8 +57,9 @@ profile_thread_flush(Thread_Context *tctx, Profile_Global_List *list){ Arena_Node* node = push_array(&list->node_arena, Arena_Node, 1); sll_queue_push(list->first_arena, list->last_arena, node); node->arena = tctx->prof_arena; - tctx->prof_arena = make_arena_system(KB(4)); + tctx->prof_arena = make_arena_system(KB(16)); + if (tctx->prof_first != 0){ if (thread->first_record == 0){ thread->first_record = tctx->prof_first; thread->last_record = tctx->prof_last; @@ -68,11 +69,14 @@ profile_thread_flush(Thread_Context *tctx, Profile_Global_List *list){ thread->last_record = tctx->prof_last; } thread->record_count += tctx->prof_record_count; - - tctx->prof_record_count = 0; - tctx->prof_first = 0; - tctx->prof_last = 0; + } } + else{ + linalloc_clear(&tctx->prof_arena); + } + tctx->prof_record_count = 0; + tctx->prof_first = 0; + tctx->prof_last = 0; } } diff --git a/custom/4coder_profile_inspect.cpp b/custom/4coder_profile_inspect.cpp index 9b21c44f..fe110ce1 100644 --- a/custom/4coder_profile_inspect.cpp +++ b/custom/4coder_profile_inspect.cpp @@ -476,6 +476,25 @@ profile_draw_node(Application_Links *app, View_ID view, Face_ID face_id, } } +function void +profile_memory_sort_by_count(Memory_Bucket **buckets, i32 first, i32 one_past_last){ + if (first + 1 < one_past_last){ + i32 pivot = one_past_last - 1; + i32 pivot_key = buckets[pivot]->annotation.count; + i32 j = first; + for (i32 i = first; i < pivot; i += 1){ + i32 key = buckets[i]->annotation.count; + if (key <= pivot_key){ + Swap(Memory_Bucket*, buckets[j], buckets[i]); + j += 1; + } + } + Swap(Memory_Bucket*, buckets[j], buckets[pivot]); + profile_memory_sort_by_count(buckets, first, j); + profile_memory_sort_by_count(buckets, j + 1, one_past_last); + } +} + function void profile_render(Application_Links *app, Frame_Info frame_info, View_ID view){ Scratch_Block scratch(app); @@ -552,6 +571,10 @@ profile_render(Application_Links *app, Frame_Info frame_info, View_ID view){ ProfileInspectTab_Errors); } + profile_draw_tab(app, &tab_state, inspect, + string_u8_litexpr("memory"), + ProfileInspectTab_Memory); + if (inspect->tab_id == ProfileInspectTab_Selection){ String_Const_u8 string = {}; if (inspect->selected_thread != 0){ @@ -615,6 +638,9 @@ profile_render(Application_Links *app, Frame_Info frame_info, View_ID view){ draw_rectangle_outline(app, box, 6.f, 3.f, margin); y_pos = y.max; + if (y_pos >= tabs_body.max.y1){ + break; + } } }break; @@ -663,6 +689,9 @@ profile_render(Application_Links *app, Frame_Info frame_info, View_ID view){ draw_rectangle_outline(app, box, 6.f, 3.f, margin); y_pos = y.max; + if (y_pos >= tabs_body.max.y1){ + break; + } } }break; @@ -693,9 +722,91 @@ profile_render(Application_Links *app, Frame_Info frame_info, View_ID view){ draw_rectangle_outline(app, box, 6.f, 3.f, margin); y_pos = y.max; + if (y_pos >= tabs_body.max.y1){ + break; + } } }break; + case ProfileInspectTab_Memory: + { + draw_set_clip(app, tabs_body.max); + Range_f32 x = rect_range_x(tabs_body.max); + f32 y_pos = tabs_body.max.y0; + Memory_Annotation annotation = system_memory_annotation(scratch); + + Base_Allocator *allocator = get_base_allocator_system(); + + Memory_Bucket *first_bucket = 0; + Memory_Bucket *last_bucket = 0; + i32 bucket_count = 0; + Table_Data_u64 table = make_table_Data_u64(allocator, 100); + + for (Memory_Annotation_Node *node = annotation.first, *next = 0; + node != 0; + node = next){ + next = node->next; + Data key = make_data(node->location.str, node->location.size); + Table_Lookup lookup = table_lookup(&table, key); + Memory_Bucket *bucket = 0; + if (lookup.found_match){ + u64 val = 0; + table_read(&table, lookup, &val); + bucket = (Memory_Bucket*)IntAsPtr(val); + } + else{ + bucket = push_array_zero(scratch, Memory_Bucket, 1); + sll_queue_push(first_bucket, last_bucket, bucket); + bucket_count += 1; + bucket->location = node->location; + table_insert(&table, key, PtrAsInt(bucket)); + } + sll_queue_push(bucket->annotation.first, bucket->annotation.last, node); + bucket->annotation.count += 1; + bucket->total_memory += node->size; + } + + Memory_Bucket **buckets = push_array(scratch, Memory_Bucket*, bucket_count); + i32 counter = 0; + for (Memory_Bucket *node = first_bucket; + node != 0; + node = node->next){ + buckets[counter] = node; + counter += 1; + } + + profile_memory_sort_by_count(buckets, 0, bucket_count); + + for (i32 i = bucket_count - 1; i >= 0; i -= 1){ + Memory_Bucket *node = buckets[i]; + Range_f32 y = If32_size(y_pos, block_height); + + Fancy_Line list = {}; + push_fancy_stringf(scratch, &list, fcolor_id(Stag_Pop2), "[%12llu] / %6d ", + node->total_memory, node->annotation.count); + push_fancy_stringf(scratch, &list, fcolor_id(Stag_Pop1), "%.*s", + string_expand(node->location)); + + Vec2_f32 p = V2f32(x.min + x_half_padding, + (y.min + y.max - line_height)*0.5f); + draw_fancy_line(app, face_id, fcolor_zero(), &list, p); + + Rect_f32 box = Rf32(x, y); + FColor margin = fcolor_id(Stag_Margin); + if (rect_contains_point(box, m_p)){ + inspect->location_jump_hovered = node->location; + margin = fcolor_id(Stag_Margin_Hover); + } + + y_pos = y.max; + if (y_pos >= tabs_body.max.y1){ + break; + } + } + + table_free(&table); + }break; + case ProfileInspectTab_Selection: { if (inspect->selected_thread != 0){ diff --git a/custom/4coder_profile_inspect.h b/custom/4coder_profile_inspect.h index 8da8f4ab..0855b802 100644 --- a/custom/4coder_profile_inspect.h +++ b/custom/4coder_profile_inspect.h @@ -60,6 +60,7 @@ enum{ ProfileInspectTab_Threads, ProfileInspectTab_Blocks, ProfileInspectTab_Errors, + ProfileInspectTab_Memory, ProfileInspectTab_Selection, }; @@ -89,6 +90,13 @@ struct Profile_Inspection{ global Profile_Inspection global_profile_inspection = {}; +struct Memory_Bucket{ + Memory_Bucket *next; + Memory_Annotation annotation; + String_Const_u8 location; + umem total_memory; +}; + #endif // TOP diff --git a/custom/4coder_system_allocator.cpp b/custom/4coder_system_allocator.cpp index c5953281..3e63097f 100644 --- a/custom/4coder_system_allocator.cpp +++ b/custom/4coder_system_allocator.cpp @@ -5,12 +5,12 @@ // TOP internal void* -base_reserve__system(void *user_data, umem size, umem *size_out){ +base_reserve__system(void *user_data, umem size, umem *size_out, String_Const_u8 location){ umem extra_size = 128; umem increased_size = size + extra_size; size = round_up_umem(increased_size, KB(4)); *size_out = size - extra_size; - void *ptr = system_memory_allocate(size); + void *ptr = system_memory_allocate(size, location); *(umem*)ptr = size; ptr = (u8*)ptr + extra_size; return(ptr); diff --git a/custom/4coder_system_helpers.cpp b/custom/4coder_system_helpers.cpp index b831617d..d04eaa57 100644 --- a/custom/4coder_system_helpers.cpp +++ b/custom/4coder_system_helpers.cpp @@ -4,6 +4,14 @@ // TOP +function String_Const_u8 +get_file_path_in_fonts_folder(Arena *arena, String_Const_u8 base_name){ + String_Const_u8 binary = system_get_path(arena, SystemPath_Binary); + return(push_u8_stringf(arena, "%.*sfonts/%.*s", string_expand(binary), string_expand(base_name))); +} + +//////////////////////////////// + Mutex_Lock::Mutex_Lock(System_Mutex m){ system_mutex_acquire(m); this->mutex = m; diff --git a/custom/4coder_system_types.h b/custom/4coder_system_types.h index c605c640..f2c791ab 100644 --- a/custom/4coder_system_types.h +++ b/custom/4coder_system_types.h @@ -31,6 +31,19 @@ enum{ SystemPath_Binary, }; +struct Memory_Annotation_Node{ + Memory_Annotation_Node *next; + String_Const_u8 location; + void *address; + umem size; +}; + +struct Memory_Annotation{ + Memory_Annotation_Node *first; + Memory_Annotation_Node *last; + i32 count; +}; + struct Mutex_Lock{ Mutex_Lock(System_Mutex mutex); ~Mutex_Lock(); diff --git a/custom/4coder_table.cpp b/custom/4coder_table.cpp index 6ec90f65..dd0d1db0 100644 --- a/custom/4coder_table.cpp +++ b/custom/4coder_table.cpp @@ -21,11 +21,11 @@ global_const u32 table_erased_u32_key = max_u32; //////////////////////////////// internal Table_u64_u64 -make_table_u64_u64(Base_Allocator *allocator, u32 slot_count){ +make_table_u64_u64__inner(Base_Allocator *allocator, u32 slot_count, String_Const_u8 location){ Table_u64_u64 table = {}; table.allocator = allocator; slot_count = clamp_bot(8, slot_count); - Data mem = base_allocate(allocator, slot_count*(sizeof(*table.keys) + sizeof(*table.vals))); + Data mem = base_allocate__inner(allocator, slot_count*(sizeof(*table.keys) + sizeof(*table.vals)), location); block_zero(mem.data, mem.size); table.memory = mem.data; table.keys = (u64*)table.memory; @@ -36,6 +36,8 @@ make_table_u64_u64(Base_Allocator *allocator, u32 slot_count){ return(table); } +#define make_table_u64_u64(a,s) make_table_u64_u64__inner((a),(s),file_name_line_number_lit_u8) + internal void table_free(Table_u64_u64 *table){ base_free(table->allocator, table->memory); @@ -183,11 +185,11 @@ table_clear(Table_u64_u64 *table){ //////////////////////////////// internal Table_u32_u16 -make_table_u32_u16(Base_Allocator *allocator, u32 slot_count){ +make_table_u32_u16__inner(Base_Allocator *allocator, u32 slot_count, String_Const_u8 location){ Table_u32_u16 table = {}; table.allocator = allocator; slot_count = clamp_bot(8, slot_count); - Data mem = base_allocate(allocator, slot_count*(sizeof(*table.keys) + sizeof(*table.vals))); + Data mem = base_allocate__inner(allocator, slot_count*(sizeof(*table.keys) + sizeof(*table.vals)), location); block_zero(mem.data, mem.size); table.memory = mem.data; table.keys = (u32*)table.memory; @@ -198,6 +200,8 @@ make_table_u32_u16(Base_Allocator *allocator, u32 slot_count){ return(table); } +#define make_table_u32_u16(a,s) make_table_u32_u16__inner((a),(s),file_name_line_number_lit_u8) + internal void table_free(Table_u32_u16 *table){ base_free(table->allocator, table->memory); @@ -341,11 +345,11 @@ table_clear(Table_u32_u16 *table){ //////////////////////////////// internal Table_Data_u64 -make_table_Data_u64(Base_Allocator *allocator, u32 slot_count){ +make_table_Data_u64__inner(Base_Allocator *allocator, u32 slot_count, String_Const_u8 location){ Table_Data_u64 table = {}; table.allocator = allocator; slot_count = clamp_bot(8, slot_count); - Data mem = base_allocate(allocator, slot_count*(sizeof(*table.hashes) + sizeof(*table.keys) + sizeof(*table.vals))); + Data mem = base_allocate__inner(allocator, slot_count*(sizeof(*table.hashes) + sizeof(*table.keys) + sizeof(*table.vals)), location); block_zero(mem.data, mem.size); table.memory = mem.data; table.hashes = (u64*)table.memory; @@ -357,6 +361,8 @@ make_table_Data_u64(Base_Allocator *allocator, u32 slot_count){ return(table); } +#define make_table_Data_u64(a,s) make_table_Data_u64__inner((a),(s),file_name_line_number_lit_u8) + internal void table_free(Table_Data_u64 *table){ base_free(table->allocator, table->memory); @@ -515,11 +521,11 @@ table_clear(Table_Data_u64 *table){ //////////////////////////////// internal Table_u64_Data -make_table_u64_Data(Base_Allocator *allocator, u32 slot_count){ +make_table_u64_Data__inner(Base_Allocator *allocator, u32 slot_count, String_Const_u8 location){ Table_u64_Data table = {}; table.allocator = allocator; slot_count = clamp_bot(8, slot_count); - Data mem = base_allocate(allocator, slot_count*(sizeof(*table.keys) + sizeof(*table.vals))); + Data mem = base_allocate__inner(allocator, slot_count*(sizeof(*table.keys) + sizeof(*table.vals)), location); block_zero(mem.data, mem.size); table.memory = mem.data; table.keys = (u64*)table.memory; @@ -530,6 +536,8 @@ make_table_u64_Data(Base_Allocator *allocator, u32 slot_count){ return(table); } +#define make_table_u64_Data(a,s) make_table_u64_Data__inner((a),(s),file_name_line_number_lit_u8) + internal void table_free(Table_u64_Data *table){ base_free(table->allocator, table->memory); @@ -679,11 +687,11 @@ table_clear(Table_u64_Data *table){ //////////////////////////////// internal Table_Data_Data -make_table_Data_Data(Base_Allocator *allocator, u32 slot_count){ +make_table_Data_Data__inner(Base_Allocator *allocator, u32 slot_count, String_Const_u8 location){ Table_Data_Data table = {}; table.allocator = allocator; slot_count = clamp_bot(8, slot_count); - Data mem = base_allocate(allocator, slot_count*(sizeof(*table.hashes) + sizeof(*table.keys) + sizeof(*table.vals))); + Data mem = base_allocate__inner(allocator, slot_count*(sizeof(*table.hashes) + sizeof(*table.keys) + sizeof(*table.vals)), location); block_zero(mem.data, mem.size); table.memory = mem.data; table.hashes = (u64*)table.memory; @@ -695,6 +703,8 @@ make_table_Data_Data(Base_Allocator *allocator, u32 slot_count){ return(table); } +#define make_table_Data_Data(a,s) make_table_Data_Data__inner((a),(s),file_name_line_number_lit_u8) + internal void table_free(Table_Data_Data *table){ base_free(table->allocator, table->memory); diff --git a/custom/4coder_types.h b/custom/4coder_types.h index d4b0e1eb..7eab73e5 100644 --- a/custom/4coder_types.h +++ b/custom/4coder_types.h @@ -429,7 +429,6 @@ struct Query_Bar_Group{ struct Font_Load_Location{ String_Const_u8 file_name; - b32 in_4coder_font_folder; }; struct Face_Load_Parameters{ diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index 75790606..c9500260 100644 --- a/custom/generated/command_metadata.h +++ b/custom/generated/command_metadata.h @@ -241,225 +241,225 @@ i32 source_name_len; i32 line_number; }; static Command_Metadata fcoder_metacmd_table[219] = { -{ PROC_LINKS(default_view_input_handler, 0), false, "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "c:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 56 }, -{ PROC_LINKS(profile_enable, 0), false, "profile_enable", 14, "Allow 4coder's self profiler to gather new profiling information.", 65, "c:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 207 }, -{ PROC_LINKS(profile_disable, 0), false, "profile_disable", 15, "Prevent 4coder's self profiler from gathering new profiling information.", 72, "c:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 214 }, -{ PROC_LINKS(profile_clear, 0), false, "profile_clear", 13, "Clear all profiling information from 4coder's self profiler.", 60, "c:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 221 }, -{ PROC_LINKS(seek_beginning_of_textual_line, 0), false, "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "c:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2157 }, -{ PROC_LINKS(seek_end_of_textual_line, 0), false, "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "c:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2163 }, -{ PROC_LINKS(seek_beginning_of_line, 0), false, "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "c:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2169 }, -{ PROC_LINKS(seek_end_of_line, 0), false, "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "c:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2175 }, -{ PROC_LINKS(goto_beginning_of_file, 0), false, "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "c:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2181 }, -{ PROC_LINKS(goto_end_of_file, 0), false, "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "c:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2189 }, -{ PROC_LINKS(toggle_virtual_whitespace, 0), false, "toggle_virtual_whitespace", 25, "Toggles the current buffer's virtual whitespace status.", 55, "c:\\4ed\\code\\custom\\4coder_code_index.cpp", 40, 957 }, -{ PROC_LINKS(change_active_panel, 0), false, "change_active_panel", 19, "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 284 }, -{ PROC_LINKS(change_active_panel_backwards, 0), false, "change_active_panel_backwards", 29, "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 290 }, -{ PROC_LINKS(open_panel_vsplit, 0), false, "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 300 }, -{ PROC_LINKS(open_panel_hsplit, 0), false, "open_panel_hsplit", 17, "Create a new panel by horizontally splitting the active panel.", 62, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 310 }, -{ PROC_LINKS(suppress_mouse, 0), false, "suppress_mouse", 14, "Hides the mouse and causes all mosue input (clicks, position, wheel) to be ignored.", 83, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 375 }, -{ PROC_LINKS(allow_mouse, 0), false, "allow_mouse", 11, "Shows the mouse and causes all mouse input to be processed normally.", 68, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 381 }, -{ PROC_LINKS(toggle_mouse, 0), false, "toggle_mouse", 12, "Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.", 71, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 387 }, -{ PROC_LINKS(set_mode_to_original, 0), false, "set_mode_to_original", 20, "Sets the edit mode to 4coder original.", 38, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 393 }, -{ PROC_LINKS(set_mode_to_notepad_like, 0), false, "set_mode_to_notepad_like", 24, "Sets the edit mode to Notepad like.", 35, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 399 }, -{ PROC_LINKS(toggle_highlight_line_at_cursor, 0), false, "toggle_highlight_line_at_cursor", 31, "Toggles the line highlight at the cursor.", 41, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 405 }, -{ PROC_LINKS(toggle_highlight_enclosing_scopes, 0), false, "toggle_highlight_enclosing_scopes", 33, "In code files scopes surrounding the cursor are highlighted with distinguishing colors.", 87, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 411 }, -{ PROC_LINKS(toggle_paren_matching_helper, 0), false, "toggle_paren_matching_helper", 28, "In code files matching parentheses pairs are colored with distinguishing colors.", 80, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 417 }, -{ PROC_LINKS(toggle_fullscreen, 0), false, "toggle_fullscreen", 17, "Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.", 89, "c:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 423 }, -{ PROC_LINKS(write_text_input, 0), false, "write_text_input", 16, "Inserts whatever text was used to trigger this command.", 55, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 59 }, -{ PROC_LINKS(write_space, 0), false, "write_space", 11, "Inserts an underscore.", 22, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 67 }, -{ PROC_LINKS(write_underscore, 0), false, "write_underscore", 16, "Inserts an underscore.", 22, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 73 }, -{ PROC_LINKS(delete_char, 0), false, "delete_char", 11, "Deletes the character to the right of the cursor.", 49, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 79 }, -{ PROC_LINKS(backspace_char, 0), false, "backspace_char", 14, "Deletes the character to the left of the cursor.", 48, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 96 }, -{ PROC_LINKS(set_mark, 0), false, "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 115 }, -{ PROC_LINKS(cursor_mark_swap, 0), false, "cursor_mark_swap", 16, "Swaps the position of the cursor and the mark.", 46, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 124 }, -{ PROC_LINKS(delete_range, 0), false, "delete_range", 12, "Deletes the text in the range between the cursor and the mark.", 62, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 134 }, -{ PROC_LINKS(backspace_alpha_numeric_boundary, 0), false, "backspace_alpha_numeric_boundary", 32, "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 154 }, -{ PROC_LINKS(delete_alpha_numeric_boundary, 0), false, "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 162 }, -{ PROC_LINKS(snipe_backward_whitespace_or_token_boundary, 0), false, "snipe_backward_whitespace_or_token_boundary", 43, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 179 }, -{ PROC_LINKS(snipe_forward_whitespace_or_token_boundary, 0), false, "snipe_forward_whitespace_or_token_boundary", 42, "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 187 }, -{ PROC_LINKS(center_view, 0), false, "center_view", 11, "Centers the view vertically on the line on which the cursor sits.", 65, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 197 }, -{ PROC_LINKS(left_adjust_view, 0), false, "left_adjust_view", 16, "Sets the left size of the view near the x position of the cursor.", 65, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 211 }, -{ PROC_LINKS(click_set_cursor_and_mark, 0), false, "click_set_cursor_and_mark", 25, "Sets the cursor position and mark to the mouse position.", 56, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 223 }, -{ PROC_LINKS(click_set_cursor, 0), false, "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 233 }, -{ PROC_LINKS(click_set_cursor_if_lbutton, 0), false, "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 243 }, -{ PROC_LINKS(click_set_mark, 0), false, "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 255 }, -{ PROC_LINKS(mouse_wheel_scroll, 0), false, "mouse_wheel_scroll", 18, "Reads the scroll wheel value from the mouse state and scrolls accordingly.", 74, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 265 }, -{ PROC_LINKS(move_up, 0), false, "move_up", 7, "Moves the cursor up one line.", 29, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 332 }, -{ PROC_LINKS(move_down, 0), false, "move_down", 9, "Moves the cursor down one line.", 31, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 338 }, -{ PROC_LINKS(move_up_10, 0), false, "move_up_10", 10, "Moves the cursor up ten lines.", 30, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 344 }, -{ PROC_LINKS(move_down_10, 0), false, "move_down_10", 12, "Moves the cursor down ten lines.", 32, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 350 }, -{ PROC_LINKS(move_down_textual, 0), false, "move_down_textual", 17, "Moves down to the next line of actual text, regardless of line wrapping.", 72, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 356 }, -{ PROC_LINKS(page_up, 0), false, "page_up", 7, "Scrolls the view up one view height and moves the cursor up one view height.", 76, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 366 }, -{ PROC_LINKS(page_down, 0), false, "page_down", 9, "Scrolls the view down one view height and moves the cursor down one view height.", 80, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 374 }, -{ PROC_LINKS(move_up_to_blank_line, 0), false, "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 403 }, -{ PROC_LINKS(move_down_to_blank_line, 0), false, "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 409 }, -{ PROC_LINKS(move_up_to_blank_line_skip_whitespace, 0), false, "move_up_to_blank_line_skip_whitespace", 37, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 415 }, -{ PROC_LINKS(move_down_to_blank_line_skip_whitespace, 0), false, "move_down_to_blank_line_skip_whitespace", 39, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 421 }, -{ PROC_LINKS(move_up_to_blank_line_end, 0), false, "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 427 }, -{ PROC_LINKS(move_down_to_blank_line_end, 0), false, "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 433 }, -{ PROC_LINKS(move_left, 0), false, "move_left", 9, "Moves the cursor one character to the left.", 43, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 439 }, -{ PROC_LINKS(move_right, 0), false, "move_right", 10, "Moves the cursor one character to the right.", 44, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 447 }, -{ PROC_LINKS(move_right_whitespace_boundary, 0), false, "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 465 }, -{ PROC_LINKS(move_left_whitespace_boundary, 0), false, "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 473 }, -{ PROC_LINKS(move_right_token_boundary, 0), false, "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 481 }, -{ PROC_LINKS(move_left_token_boundary, 0), false, "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 488 }, -{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), false, "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 495 }, -{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), false, "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 502 }, -{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), false, "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 509 }, -{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), false, "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 516 }, -{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), false, "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 523 }, -{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), false, "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 530 }, -{ PROC_LINKS(select_all, 0), false, "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 539 }, -{ PROC_LINKS(to_uppercase, 0), false, "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 552 }, -{ PROC_LINKS(to_lowercase, 0), false, "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 565 }, -{ PROC_LINKS(clean_all_lines, 0), false, "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 578 }, -{ PROC_LINKS(basic_change_active_panel, 0), false, "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 613 }, -{ PROC_LINKS(close_panel, 0), false, "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 621 }, -{ PROC_LINKS(show_scrollbar, 0), false, "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 630 }, -{ PROC_LINKS(hide_scrollbar, 0), false, "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 637 }, -{ PROC_LINKS(show_filebar, 0), false, "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 644 }, -{ PROC_LINKS(hide_filebar, 0), false, "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 651 }, -{ PROC_LINKS(toggle_filebar, 0), false, "toggle_filebar", 14, "Toggles the visibility status of the current view's filebar.", 60, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 658 }, -{ PROC_LINKS(toggle_fps_meter, 0), false, "toggle_fps_meter", 16, "Toggles the visibility of the FPS performance meter", 51, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 667 }, -{ PROC_LINKS(increase_face_size, 0), false, "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 673 }, -{ PROC_LINKS(decrease_face_size, 0), false, "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 684 }, -{ PROC_LINKS(mouse_wheel_change_face_size, 0), false, "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 695 }, -{ PROC_LINKS(toggle_show_whitespace, 0), false, "toggle_show_whitespace", 22, "Toggles the current buffer's whitespace visibility status.", 58, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 712 }, -{ PROC_LINKS(toggle_line_numbers, 0), false, "toggle_line_numbers", 19, "Toggles the left margin line numbers.", 37, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 721 }, -{ PROC_LINKS(toggle_line_wrap, 0), false, "toggle_line_wrap", 16, "Toggles the line wrap setting on this buffer.", 45, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 727 }, -{ PROC_LINKS(exit_4coder, 0), false, "exit_4coder", 11, "Attempts to close 4coder.", 25, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 740 }, -{ PROC_LINKS(goto_line, 0), false, "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 748 }, -{ PROC_LINKS(search, 0), false, "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 976 }, -{ PROC_LINKS(reverse_search, 0), false, "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 982 }, -{ PROC_LINKS(search_identifier, 0), false, "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 988 }, -{ PROC_LINKS(reverse_search_identifier, 0), false, "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 994 }, -{ PROC_LINKS(replace_in_range, 0), false, "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1041 }, -{ PROC_LINKS(replace_in_buffer, 0), false, "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1050 }, -{ PROC_LINKS(replace_in_all_buffers, 0), false, "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1059 }, -{ PROC_LINKS(query_replace, 0), false, "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1149 }, -{ PROC_LINKS(query_replace_identifier, 0), false, "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1170 }, -{ PROC_LINKS(query_replace_selection, 0), false, "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1186 }, -{ PROC_LINKS(save_all_dirty_buffers, 0), false, "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1222 }, -{ PROC_LINKS(delete_file_query, 0), false, "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1247 }, -{ PROC_LINKS(save_to_query, 0), false, "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1291 }, -{ PROC_LINKS(rename_file_query, 0), false, "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1324 }, -{ PROC_LINKS(make_directory_query, 0), false, "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1362 }, -{ PROC_LINKS(move_line_up, 0), false, "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1396 }, -{ PROC_LINKS(move_line_down, 0), false, "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1402 }, -{ PROC_LINKS(duplicate_line, 0), false, "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1408 }, -{ PROC_LINKS(delete_line, 0), false, "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1422 }, -{ PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1487 }, -{ PROC_LINKS(open_matching_file_cpp, 0), false, "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1519 }, -{ PROC_LINKS(view_buffer_other_panel, 0), false, "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1532 }, -{ PROC_LINKS(swap_panels, 0), false, "swap_panels", 11, "Swaps the active panel with it's sibling.", 41, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1544 }, -{ PROC_LINKS(kill_buffer, 0), false, "kill_buffer", 11, "Kills the current buffer.", 25, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1568 }, -{ PROC_LINKS(save, 0), false, "save", 4, "Saves the current buffer.", 25, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1576 }, -{ PROC_LINKS(reopen, 0), false, "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1586 }, -{ PROC_LINKS(undo, 0), false, "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1811 }, -{ PROC_LINKS(redo, 0), false, "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1824 }, -{ PROC_LINKS(undo_all_buffers, 0), false, "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1838 }, -{ PROC_LINKS(redo_all_buffers, 0), false, "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1909 }, -{ PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2010 }, -{ PROC_LINKS(default_file_externally_modified, 0), false, "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "c:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2016 }, -{ PROC_LINKS(set_eol_mode_to_crlf, 0), false, "set_eol_mode_to_crlf", 20, "Puts the buffer in crlf line ending mode.", 41, "c:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 86 }, -{ PROC_LINKS(set_eol_mode_to_lf, 0), false, "set_eol_mode_to_lf", 18, "Puts the buffer in lf line ending mode.", 39, "c:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 99 }, -{ PROC_LINKS(set_eol_mode_to_binary, 0), false, "set_eol_mode_to_binary", 22, "Puts the buffer in bin line ending mode.", 40, "c:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 112 }, -{ PROC_LINKS(set_eol_mode_from_contents, 0), false, "set_eol_mode_from_contents", 26, "Sets the buffer's line ending mode to match the contents of the buffer.", 71, "c:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 125 }, -{ PROC_LINKS(interactive_switch_buffer, 0), true, "interactive_switch_buffer", 25, "Interactively switch to an open buffer.", 39, "c:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 416 }, -{ PROC_LINKS(interactive_kill_buffer, 0), true, "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "c:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 426 }, -{ PROC_LINKS(interactive_open_or_new, 0), true, "interactive_open_or_new", 23, "Interactively open a file out of the file system.", 49, "c:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 474 }, -{ PROC_LINKS(interactive_new, 0), true, "interactive_new", 15, "Interactively creates a new file.", 33, "c:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 508 }, -{ PROC_LINKS(interactive_open, 0), true, "interactive_open", 16, "Interactively opens a file.", 27, "c:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 545 }, -{ PROC_LINKS(command_lister, 0), true, "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "c:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 579 }, -{ PROC_LINKS(auto_indent_whole_file, 0), false, "auto_indent_whole_file", 22, "Audo-indents the entire current buffer.", 39, "c:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 366 }, -{ PROC_LINKS(auto_indent_line_at_cursor, 0), false, "auto_indent_line_at_cursor", 26, "Auto-indents the line on which the cursor sits.", 47, "c:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 375 }, -{ PROC_LINKS(auto_indent_range, 0), false, "auto_indent_range", 17, "Auto-indents the range between the cursor and the mark.", 55, "c:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 385 }, -{ PROC_LINKS(write_text_and_auto_indent, 0), false, "write_text_and_auto_indent", 26, "Inserts text and auto-indents the line on which the cursor sits if any of the text contains 'layout punctuation' such as ;:{}()[]# and new lines.", 145, "c:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 395 }, -{ PROC_LINKS(list_all_locations, 0), false, "list_all_locations", 18, "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 162 }, -{ PROC_LINKS(list_all_substring_locations, 0), false, "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 168 }, -{ PROC_LINKS(list_all_locations_case_insensitive, 0), false, "list_all_locations_case_insensitive", 35, "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 174 }, -{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), false, "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 180 }, -{ PROC_LINKS(list_all_locations_of_identifier, 0), false, "list_all_locations_of_identifier", 32, "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 186 }, -{ PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), false, "list_all_locations_of_identifier_case_insensitive", 49, "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 192 }, -{ PROC_LINKS(list_all_locations_of_selection, 0), false, "list_all_locations_of_selection", 31, "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 198 }, -{ PROC_LINKS(list_all_locations_of_selection_case_insensitive, 0), false, "list_all_locations_of_selection_case_insensitive", 48, "Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.", 104, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 204 }, -{ PROC_LINKS(list_all_locations_of_type_definition, 0), false, "list_all_locations_of_type_definition", 37, "Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.", 121, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 210 }, -{ PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), false, "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 218 }, -{ PROC_LINKS(word_complete, 0), false, "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 392 }, -{ PROC_LINKS(word_complete_drop_down, 0), false, "word_complete_drop_down", 23, "Word complete with drop down menu.", 34, "c:\\4ed\\code\\custom\\4coder_search.cpp", 36, 641 }, -{ PROC_LINKS(goto_jump_at_cursor, 0), false, "goto_jump_at_cursor", 19, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in another view and changes the active panel to the view containing the jump.", 187, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 346 }, -{ PROC_LINKS(goto_jump_at_cursor_same_panel, 0), false, "goto_jump_at_cursor_same_panel", 30, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in this view, losing the compilation output or jump list.", 167, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 373 }, -{ PROC_LINKS(goto_next_jump, 0), false, "goto_next_jump", 14, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, skipping sub jump locations.", 123, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 462 }, -{ PROC_LINKS(goto_prev_jump, 0), false, "goto_prev_jump", 14, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, skipping sub jump locations.", 127, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 479 }, -{ PROC_LINKS(goto_next_jump_no_skips, 0), false, "goto_next_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, and does not skip sub jump locations.", 132, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 492 }, -{ PROC_LINKS(goto_prev_jump_no_skips, 0), false, "goto_prev_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations.", 136, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 509 }, -{ PROC_LINKS(goto_first_jump, 0), false, "goto_first_jump", 15, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer.", 95, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 523 }, -{ PROC_LINKS(goto_first_jump_same_panel_sticky, 0), false, "goto_first_jump_same_panel_sticky", 33, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer and views the buffer in the panel where the jump list was.", 153, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 540 }, -{ PROC_LINKS(if_read_only_goto_position, 0), false, "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 562 }, -{ PROC_LINKS(if_read_only_goto_position_same_panel, 0), false, "if_read_only_goto_position_same_panel", 37, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "c:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 579 }, -{ PROC_LINKS(view_jump_list_with_lister, 0), false, "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "c:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 59 }, -{ PROC_LINKS(show_the_log_graph, 0), true, "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "c:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 995 }, -{ PROC_LINKS(copy, 0), false, "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "c:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 19 }, -{ PROC_LINKS(cut, 0), false, "cut", 3, "Cut the text in the range from the cursor to the mark onto the clipboard.", 73, "c:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 28 }, -{ PROC_LINKS(paste, 0), false, "paste", 5, "At the cursor, insert the text at the top of the clipboard.", 59, "c:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 39 }, -{ PROC_LINKS(paste_next, 0), false, "paste_next", 10, "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "c:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 70 }, -{ PROC_LINKS(paste_and_indent, 0), false, "paste_and_indent", 16, "Paste from the top of clipboard and run auto-indent on the newly pasted text.", 77, "c:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 108 }, -{ PROC_LINKS(paste_next_and_indent, 0), false, "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "c:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 115 }, -{ PROC_LINKS(execute_previous_cli, 0), false, "execute_previous_cli", 20, "If the command execute_any_cli has already been used, this will execute a CLI reusing the most recent buffer name and command.", 126, "c:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 7 }, -{ PROC_LINKS(execute_any_cli, 0), false, "execute_any_cli", 15, "Queries for an output buffer name and system command, runs the system command as a CLI and prints the output to the specified buffer.", 133, "c:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 22 }, -{ PROC_LINKS(build_search, 0), false, "build_search", 12, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*.", 153, "c:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 128 }, -{ PROC_LINKS(build_in_build_panel, 0), false, "build_in_build_panel", 20, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*. Puts the *compilation* buffer in a panel at the footer of the current view.", 230, "c:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 163 }, -{ PROC_LINKS(close_build_panel, 0), false, "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "c:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 178 }, -{ PROC_LINKS(change_to_build_panel, 0), false, "change_to_build_panel", 21, "If the special build panel is open, makes the build panel the active panel.", 75, "c:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 184 }, -{ PROC_LINKS(close_all_code, 0), false, "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 843 }, -{ PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 849 }, -{ PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 855 }, -{ PROC_LINKS(load_project, 0), false, "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 863 }, -{ PROC_LINKS(project_fkey_command, 0), false, "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 871 }, -{ PROC_LINKS(project_go_to_root_directory, 0), false, "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 897 }, -{ PROC_LINKS(setup_new_project, 0), false, "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1231 }, -{ PROC_LINKS(setup_build_bat, 0), false, "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1238 }, -{ PROC_LINKS(setup_build_sh, 0), false, "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1244 }, -{ PROC_LINKS(setup_build_bat_and_sh, 0), false, "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1250 }, -{ PROC_LINKS(project_command_lister, 0), false, "project_command_lister", 22, "Open a lister of all commands in the currently loaded project.", 62, "c:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1290 }, -{ PROC_LINKS(list_all_functions_current_buffer, 0), false, "list_all_functions_current_buffer", 33, "Creates a jump list of lines of the current buffer that appear to define or declare functions.", 94, "c:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 267 }, -{ PROC_LINKS(list_all_functions_current_buffer_lister, 0), false, "list_all_functions_current_buffer_lister", 40, "Creates a lister of locations that look like function definitions and declarations in the buffer.", 97, "c:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 277 }, -{ PROC_LINKS(list_all_functions_all_buffers, 0), false, "list_all_functions_all_buffers", 30, "Creates a jump list of lines from all buffers that appear to define or declare functions.", 89, "c:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 295 }, -{ PROC_LINKS(list_all_functions_all_buffers_lister, 0), false, "list_all_functions_all_buffers_lister", 37, "Creates a lister of locations that look like function definitions and declarations all buffers.", 95, "c:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 301 }, -{ PROC_LINKS(select_surrounding_scope, 0), false, "select_surrounding_scope", 24, "Finds the scope enclosed by '{' '}' surrounding the cursor and puts the cursor and mark on the '{' and '}'.", 107, "c:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 27 }, -{ PROC_LINKS(select_surrounding_scope_maximal, 0), false, "select_surrounding_scope_maximal", 32, "Selects the top-most scope that surrounds the cursor.", 53, "c:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 39 }, -{ PROC_LINKS(select_next_scope_absolute, 0), false, "select_next_scope_absolute", 26, "Finds the first scope started by '{' after the cursor and puts the cursor and mark on the '{' and '}'.", 102, "c:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 57 }, -{ PROC_LINKS(select_next_scope_after_current, 0), false, "select_next_scope_after_current", 31, "If a scope is selected, find first scope that starts after the selected scope. Otherwise find the first scope that starts after the cursor.", 139, "c:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 66 }, -{ PROC_LINKS(select_prev_scope_absolute, 0), false, "select_prev_scope_absolute", 26, "Finds the first scope started by '{' before the cursor and puts the cursor and mark on the '{' and '}'.", 103, "c:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 82 }, -{ PROC_LINKS(select_prev_top_most_scope, 0), false, "select_prev_top_most_scope", 26, "Finds the first scope that starts before the cursor, then finds the top most scope that contains that scope.", 108, "c:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 99 }, -{ PROC_LINKS(place_in_scope, 0), false, "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "c:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 106 }, -{ PROC_LINKS(delete_current_scope, 0), false, "delete_current_scope", 20, "Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.", 99, "c:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 112 }, -{ PROC_LINKS(open_long_braces, 0), false, "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 46 }, -{ PROC_LINKS(open_long_braces_semicolon, 0), false, "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 54 }, -{ PROC_LINKS(open_long_braces_break, 0), false, "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 62 }, -{ PROC_LINKS(if0_off, 0), false, "if0_off", 7, "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 70 }, -{ PROC_LINKS(write_todo, 0), false, "write_todo", 10, "At the cursor, insert a '// TODO' comment, includes user name if it was specified in config.4coder.", 99, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 76 }, -{ PROC_LINKS(write_hack, 0), false, "write_hack", 10, "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 82 }, -{ PROC_LINKS(write_note, 0), false, "write_note", 10, "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 88 }, -{ PROC_LINKS(write_block, 0), false, "write_block", 11, "At the cursor, insert a block comment.", 38, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 94 }, -{ PROC_LINKS(write_zero_struct, 0), false, "write_zero_struct", 17, "At the cursor, insert a ' = {};'.", 33, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 100 }, -{ PROC_LINKS(comment_line, 0), false, "comment_line", 12, "Insert '//' at the beginning of the line after leading whitespace.", 66, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 125 }, -{ PROC_LINKS(uncomment_line, 0), false, "uncomment_line", 14, "If present, delete '//' at the beginning of the line after leading whitespace.", 78, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 137 }, -{ PROC_LINKS(comment_line_toggle, 0), false, "comment_line_toggle", 19, "Turns uncommented lines into commented lines and vice versa for comments starting with '//'.", 92, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 149 }, -{ PROC_LINKS(snippet_lister, 0), false, "snippet_lister", 14, "Opens a snippet lister for inserting whole pre-written snippets of text.", 72, "c:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 237 }, -{ PROC_LINKS(miblo_increment_basic, 0), false, "miblo_increment_basic", 21, "Increment an integer under the cursor by one.", 45, "c:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 29 }, -{ PROC_LINKS(miblo_decrement_basic, 0), false, "miblo_decrement_basic", 21, "Decrement an integer under the cursor by one.", 45, "c:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 44 }, -{ PROC_LINKS(miblo_increment_time_stamp, 0), false, "miblo_increment_time_stamp", 26, "Increment a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "c:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 231 }, -{ PROC_LINKS(miblo_decrement_time_stamp, 0), false, "miblo_decrement_time_stamp", 26, "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "c:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 237 }, -{ PROC_LINKS(miblo_increment_time_stamp_minute, 0), false, "miblo_increment_time_stamp_minute", 33, "Increment a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "c:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 243 }, -{ PROC_LINKS(miblo_decrement_time_stamp_minute, 0), false, "miblo_decrement_time_stamp_minute", 33, "Decrement a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "c:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 249 }, -{ PROC_LINKS(profile_inspect, 0), true, "profile_inspect", 15, "Inspect all currently collected profiling information in 4coder's self profiler.", 80, "c:\\4ed\\code\\custom\\4coder_profile_inspect.cpp", 45, 779 }, -{ PROC_LINKS(kill_tutorial, 0), false, "kill_tutorial", 13, "If there is an active tutorial, kill it.", 40, "c:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 9 }, -{ PROC_LINKS(tutorial_maximize, 0), false, "tutorial_maximize", 17, "Expand the tutorial window", 26, "c:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 20 }, -{ PROC_LINKS(tutorial_minimize, 0), false, "tutorial_minimize", 17, "Shrink the tutorial window", 26, "c:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 34 }, -{ PROC_LINKS(hms_demo_tutorial, 0), false, "hms_demo_tutorial", 17, "Tutorial for built in 4coder bindings and features.", 51, "c:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 869 }, -{ PROC_LINKS(default_startup, 0), false, "default_startup", 15, "Default command for responding to a startup event", 49, "c:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 7 }, -{ PROC_LINKS(default_try_exit, 0), false, "default_try_exit", 16, "Default command for responding to a try-exit event", 50, "c:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 22 }, +{ PROC_LINKS(default_view_input_handler, 0), false, "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 56 }, +{ PROC_LINKS(profile_enable, 0), false, "profile_enable", 14, "Allow 4coder's self profiler to gather new profiling information.", 65, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 211 }, +{ PROC_LINKS(profile_disable, 0), false, "profile_disable", 15, "Prevent 4coder's self profiler from gathering new profiling information.", 72, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 218 }, +{ PROC_LINKS(profile_clear, 0), false, "profile_clear", 13, "Clear all profiling information from 4coder's self profiler.", 60, "w:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 225 }, +{ PROC_LINKS(seek_beginning_of_textual_line, 0), false, "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2157 }, +{ PROC_LINKS(seek_end_of_textual_line, 0), false, "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2163 }, +{ PROC_LINKS(seek_beginning_of_line, 0), false, "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2169 }, +{ PROC_LINKS(seek_end_of_line, 0), false, "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2175 }, +{ PROC_LINKS(goto_beginning_of_file, 0), false, "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2181 }, +{ PROC_LINKS(goto_end_of_file, 0), false, "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "w:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2189 }, +{ PROC_LINKS(toggle_virtual_whitespace, 0), false, "toggle_virtual_whitespace", 25, "Toggles the current buffer's virtual whitespace status.", 55, "w:\\4ed\\code\\custom\\4coder_code_index.cpp", 40, 957 }, +{ PROC_LINKS(change_active_panel, 0), false, "change_active_panel", 19, "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 284 }, +{ PROC_LINKS(change_active_panel_backwards, 0), false, "change_active_panel_backwards", 29, "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 290 }, +{ PROC_LINKS(open_panel_vsplit, 0), false, "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 300 }, +{ PROC_LINKS(open_panel_hsplit, 0), false, "open_panel_hsplit", 17, "Create a new panel by horizontally splitting the active panel.", 62, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 310 }, +{ PROC_LINKS(suppress_mouse, 0), false, "suppress_mouse", 14, "Hides the mouse and causes all mosue input (clicks, position, wheel) to be ignored.", 83, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 375 }, +{ PROC_LINKS(allow_mouse, 0), false, "allow_mouse", 11, "Shows the mouse and causes all mouse input to be processed normally.", 68, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 381 }, +{ PROC_LINKS(toggle_mouse, 0), false, "toggle_mouse", 12, "Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.", 71, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 387 }, +{ PROC_LINKS(set_mode_to_original, 0), false, "set_mode_to_original", 20, "Sets the edit mode to 4coder original.", 38, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 393 }, +{ PROC_LINKS(set_mode_to_notepad_like, 0), false, "set_mode_to_notepad_like", 24, "Sets the edit mode to Notepad like.", 35, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 399 }, +{ PROC_LINKS(toggle_highlight_line_at_cursor, 0), false, "toggle_highlight_line_at_cursor", 31, "Toggles the line highlight at the cursor.", 41, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 405 }, +{ PROC_LINKS(toggle_highlight_enclosing_scopes, 0), false, "toggle_highlight_enclosing_scopes", 33, "In code files scopes surrounding the cursor are highlighted with distinguishing colors.", 87, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 411 }, +{ PROC_LINKS(toggle_paren_matching_helper, 0), false, "toggle_paren_matching_helper", 28, "In code files matching parentheses pairs are colored with distinguishing colors.", 80, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 417 }, +{ PROC_LINKS(toggle_fullscreen, 0), false, "toggle_fullscreen", 17, "Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.", 89, "w:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 423 }, +{ PROC_LINKS(write_text_input, 0), false, "write_text_input", 16, "Inserts whatever text was used to trigger this command.", 55, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 59 }, +{ PROC_LINKS(write_space, 0), false, "write_space", 11, "Inserts an underscore.", 22, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 67 }, +{ PROC_LINKS(write_underscore, 0), false, "write_underscore", 16, "Inserts an underscore.", 22, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 73 }, +{ PROC_LINKS(delete_char, 0), false, "delete_char", 11, "Deletes the character to the right of the cursor.", 49, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 79 }, +{ PROC_LINKS(backspace_char, 0), false, "backspace_char", 14, "Deletes the character to the left of the cursor.", 48, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 96 }, +{ PROC_LINKS(set_mark, 0), false, "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 115 }, +{ PROC_LINKS(cursor_mark_swap, 0), false, "cursor_mark_swap", 16, "Swaps the position of the cursor and the mark.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 124 }, +{ PROC_LINKS(delete_range, 0), false, "delete_range", 12, "Deletes the text in the range between the cursor and the mark.", 62, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 134 }, +{ PROC_LINKS(backspace_alpha_numeric_boundary, 0), false, "backspace_alpha_numeric_boundary", 32, "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 154 }, +{ PROC_LINKS(delete_alpha_numeric_boundary, 0), false, "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 162 }, +{ PROC_LINKS(snipe_backward_whitespace_or_token_boundary, 0), false, "snipe_backward_whitespace_or_token_boundary", 43, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 179 }, +{ PROC_LINKS(snipe_forward_whitespace_or_token_boundary, 0), false, "snipe_forward_whitespace_or_token_boundary", 42, "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 187 }, +{ PROC_LINKS(center_view, 0), false, "center_view", 11, "Centers the view vertically on the line on which the cursor sits.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 197 }, +{ PROC_LINKS(left_adjust_view, 0), false, "left_adjust_view", 16, "Sets the left size of the view near the x position of the cursor.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 211 }, +{ PROC_LINKS(click_set_cursor_and_mark, 0), false, "click_set_cursor_and_mark", 25, "Sets the cursor position and mark to the mouse position.", 56, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 223 }, +{ PROC_LINKS(click_set_cursor, 0), false, "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 233 }, +{ PROC_LINKS(click_set_cursor_if_lbutton, 0), false, "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 243 }, +{ PROC_LINKS(click_set_mark, 0), false, "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 255 }, +{ PROC_LINKS(mouse_wheel_scroll, 0), false, "mouse_wheel_scroll", 18, "Reads the scroll wheel value from the mouse state and scrolls accordingly.", 74, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 265 }, +{ PROC_LINKS(move_up, 0), false, "move_up", 7, "Moves the cursor up one line.", 29, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 332 }, +{ PROC_LINKS(move_down, 0), false, "move_down", 9, "Moves the cursor down one line.", 31, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 338 }, +{ PROC_LINKS(move_up_10, 0), false, "move_up_10", 10, "Moves the cursor up ten lines.", 30, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 344 }, +{ PROC_LINKS(move_down_10, 0), false, "move_down_10", 12, "Moves the cursor down ten lines.", 32, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 350 }, +{ PROC_LINKS(move_down_textual, 0), false, "move_down_textual", 17, "Moves down to the next line of actual text, regardless of line wrapping.", 72, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 356 }, +{ PROC_LINKS(page_up, 0), false, "page_up", 7, "Scrolls the view up one view height and moves the cursor up one view height.", 76, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 366 }, +{ PROC_LINKS(page_down, 0), false, "page_down", 9, "Scrolls the view down one view height and moves the cursor down one view height.", 80, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 374 }, +{ PROC_LINKS(move_up_to_blank_line, 0), false, "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 403 }, +{ PROC_LINKS(move_down_to_blank_line, 0), false, "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 409 }, +{ PROC_LINKS(move_up_to_blank_line_skip_whitespace, 0), false, "move_up_to_blank_line_skip_whitespace", 37, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 415 }, +{ PROC_LINKS(move_down_to_blank_line_skip_whitespace, 0), false, "move_down_to_blank_line_skip_whitespace", 39, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 421 }, +{ PROC_LINKS(move_up_to_blank_line_end, 0), false, "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 427 }, +{ PROC_LINKS(move_down_to_blank_line_end, 0), false, "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 433 }, +{ PROC_LINKS(move_left, 0), false, "move_left", 9, "Moves the cursor one character to the left.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 439 }, +{ PROC_LINKS(move_right, 0), false, "move_right", 10, "Moves the cursor one character to the right.", 44, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 447 }, +{ PROC_LINKS(move_right_whitespace_boundary, 0), false, "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 465 }, +{ PROC_LINKS(move_left_whitespace_boundary, 0), false, "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 473 }, +{ PROC_LINKS(move_right_token_boundary, 0), false, "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 481 }, +{ PROC_LINKS(move_left_token_boundary, 0), false, "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 488 }, +{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), false, "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 495 }, +{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), false, "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 502 }, +{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), false, "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 509 }, +{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), false, "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 516 }, +{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), false, "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 523 }, +{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), false, "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 530 }, +{ PROC_LINKS(select_all, 0), false, "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 539 }, +{ PROC_LINKS(to_uppercase, 0), false, "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 552 }, +{ PROC_LINKS(to_lowercase, 0), false, "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 565 }, +{ PROC_LINKS(clean_all_lines, 0), false, "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 578 }, +{ PROC_LINKS(basic_change_active_panel, 0), false, "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 613 }, +{ PROC_LINKS(close_panel, 0), false, "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 621 }, +{ PROC_LINKS(show_scrollbar, 0), false, "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 630 }, +{ PROC_LINKS(hide_scrollbar, 0), false, "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 637 }, +{ PROC_LINKS(show_filebar, 0), false, "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 644 }, +{ PROC_LINKS(hide_filebar, 0), false, "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 651 }, +{ PROC_LINKS(toggle_filebar, 0), false, "toggle_filebar", 14, "Toggles the visibility status of the current view's filebar.", 60, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 658 }, +{ PROC_LINKS(toggle_fps_meter, 0), false, "toggle_fps_meter", 16, "Toggles the visibility of the FPS performance meter", 51, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 667 }, +{ PROC_LINKS(increase_face_size, 0), false, "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 673 }, +{ PROC_LINKS(decrease_face_size, 0), false, "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 684 }, +{ PROC_LINKS(mouse_wheel_change_face_size, 0), false, "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 695 }, +{ PROC_LINKS(toggle_show_whitespace, 0), false, "toggle_show_whitespace", 22, "Toggles the current buffer's whitespace visibility status.", 58, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 712 }, +{ PROC_LINKS(toggle_line_numbers, 0), false, "toggle_line_numbers", 19, "Toggles the left margin line numbers.", 37, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 721 }, +{ PROC_LINKS(toggle_line_wrap, 0), false, "toggle_line_wrap", 16, "Toggles the line wrap setting on this buffer.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 727 }, +{ PROC_LINKS(exit_4coder, 0), false, "exit_4coder", 11, "Attempts to close 4coder.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 740 }, +{ PROC_LINKS(goto_line, 0), false, "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 748 }, +{ PROC_LINKS(search, 0), false, "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 976 }, +{ PROC_LINKS(reverse_search, 0), false, "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 982 }, +{ PROC_LINKS(search_identifier, 0), false, "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 988 }, +{ PROC_LINKS(reverse_search_identifier, 0), false, "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 994 }, +{ PROC_LINKS(replace_in_range, 0), false, "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1041 }, +{ PROC_LINKS(replace_in_buffer, 0), false, "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1050 }, +{ PROC_LINKS(replace_in_all_buffers, 0), false, "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1059 }, +{ PROC_LINKS(query_replace, 0), false, "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1149 }, +{ PROC_LINKS(query_replace_identifier, 0), false, "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1170 }, +{ PROC_LINKS(query_replace_selection, 0), false, "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1186 }, +{ PROC_LINKS(save_all_dirty_buffers, 0), false, "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1222 }, +{ PROC_LINKS(delete_file_query, 0), false, "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1247 }, +{ PROC_LINKS(save_to_query, 0), false, "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1291 }, +{ PROC_LINKS(rename_file_query, 0), false, "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1324 }, +{ PROC_LINKS(make_directory_query, 0), false, "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1362 }, +{ PROC_LINKS(move_line_up, 0), false, "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1396 }, +{ PROC_LINKS(move_line_down, 0), false, "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1402 }, +{ PROC_LINKS(duplicate_line, 0), false, "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1408 }, +{ PROC_LINKS(delete_line, 0), false, "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1422 }, +{ PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1487 }, +{ PROC_LINKS(open_matching_file_cpp, 0), false, "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1519 }, +{ PROC_LINKS(view_buffer_other_panel, 0), false, "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1532 }, +{ PROC_LINKS(swap_panels, 0), false, "swap_panels", 11, "Swaps the active panel with it's sibling.", 41, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1544 }, +{ PROC_LINKS(kill_buffer, 0), false, "kill_buffer", 11, "Kills the current buffer.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1568 }, +{ PROC_LINKS(save, 0), false, "save", 4, "Saves the current buffer.", 25, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1576 }, +{ PROC_LINKS(reopen, 0), false, "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1586 }, +{ PROC_LINKS(undo, 0), false, "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1811 }, +{ PROC_LINKS(redo, 0), false, "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1824 }, +{ PROC_LINKS(undo_all_buffers, 0), false, "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1838 }, +{ PROC_LINKS(redo_all_buffers, 0), false, "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1909 }, +{ PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2010 }, +{ PROC_LINKS(default_file_externally_modified, 0), false, "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "w:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 2016 }, +{ PROC_LINKS(set_eol_mode_to_crlf, 0), false, "set_eol_mode_to_crlf", 20, "Puts the buffer in crlf line ending mode.", 41, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 86 }, +{ PROC_LINKS(set_eol_mode_to_lf, 0), false, "set_eol_mode_to_lf", 18, "Puts the buffer in lf line ending mode.", 39, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 99 }, +{ PROC_LINKS(set_eol_mode_to_binary, 0), false, "set_eol_mode_to_binary", 22, "Puts the buffer in bin line ending mode.", 40, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 112 }, +{ PROC_LINKS(set_eol_mode_from_contents, 0), false, "set_eol_mode_from_contents", 26, "Sets the buffer's line ending mode to match the contents of the buffer.", 71, "w:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 125 }, +{ PROC_LINKS(interactive_switch_buffer, 0), true, "interactive_switch_buffer", 25, "Interactively switch to an open buffer.", 39, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 416 }, +{ PROC_LINKS(interactive_kill_buffer, 0), true, "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 426 }, +{ PROC_LINKS(interactive_open_or_new, 0), true, "interactive_open_or_new", 23, "Interactively open a file out of the file system.", 49, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 474 }, +{ PROC_LINKS(interactive_new, 0), true, "interactive_new", 15, "Interactively creates a new file.", 33, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 508 }, +{ PROC_LINKS(interactive_open, 0), true, "interactive_open", 16, "Interactively opens a file.", 27, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 545 }, +{ PROC_LINKS(command_lister, 0), true, "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "w:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 579 }, +{ PROC_LINKS(auto_indent_whole_file, 0), false, "auto_indent_whole_file", 22, "Audo-indents the entire current buffer.", 39, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 366 }, +{ PROC_LINKS(auto_indent_line_at_cursor, 0), false, "auto_indent_line_at_cursor", 26, "Auto-indents the line on which the cursor sits.", 47, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 375 }, +{ PROC_LINKS(auto_indent_range, 0), false, "auto_indent_range", 17, "Auto-indents the range between the cursor and the mark.", 55, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 385 }, +{ PROC_LINKS(write_text_and_auto_indent, 0), false, "write_text_and_auto_indent", 26, "Inserts text and auto-indents the line on which the cursor sits if any of the text contains 'layout punctuation' such as ;:{}()[]# and new lines.", 145, "w:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 395 }, +{ PROC_LINKS(list_all_locations, 0), false, "list_all_locations", 18, "Queries the user for a string and lists all exact case-sensitive matches found in all open buffers.", 99, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 162 }, +{ PROC_LINKS(list_all_substring_locations, 0), false, "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 168 }, +{ PROC_LINKS(list_all_locations_case_insensitive, 0), false, "list_all_locations_case_insensitive", 35, "Queries the user for a string and lists all exact case-insensitive matches found in all open buffers.", 101, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 174 }, +{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), false, "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 180 }, +{ PROC_LINKS(list_all_locations_of_identifier, 0), false, "list_all_locations_of_identifier", 32, "Reads a token or word under the cursor and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 186 }, +{ PROC_LINKS(list_all_locations_of_identifier_case_insensitive, 0), false, "list_all_locations_of_identifier_case_insensitive", 49, "Reads a token or word under the cursor and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 192 }, +{ PROC_LINKS(list_all_locations_of_selection, 0), false, "list_all_locations_of_selection", 31, "Reads the string in the selected range and lists all exact case-sensitive mathces in all open buffers.", 102, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 198 }, +{ PROC_LINKS(list_all_locations_of_selection_case_insensitive, 0), false, "list_all_locations_of_selection_case_insensitive", 48, "Reads the string in the selected range and lists all exact case-insensitive mathces in all open buffers.", 104, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 204 }, +{ PROC_LINKS(list_all_locations_of_type_definition, 0), false, "list_all_locations_of_type_definition", 37, "Queries user for string, lists all locations of strings that appear to define a type whose name matches the input string.", 121, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 210 }, +{ PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), false, "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 218 }, +{ PROC_LINKS(word_complete, 0), false, "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 392 }, +{ PROC_LINKS(word_complete_drop_down, 0), false, "word_complete_drop_down", 23, "Word complete with drop down menu.", 34, "w:\\4ed\\code\\custom\\4coder_search.cpp", 36, 641 }, +{ PROC_LINKS(goto_jump_at_cursor, 0), false, "goto_jump_at_cursor", 19, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in another view and changes the active panel to the view containing the jump.", 187, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 346 }, +{ PROC_LINKS(goto_jump_at_cursor_same_panel, 0), false, "goto_jump_at_cursor_same_panel", 30, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in this view, losing the compilation output or jump list.", 167, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 373 }, +{ PROC_LINKS(goto_next_jump, 0), false, "goto_next_jump", 14, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, skipping sub jump locations.", 123, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 462 }, +{ PROC_LINKS(goto_prev_jump, 0), false, "goto_prev_jump", 14, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, skipping sub jump locations.", 127, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 479 }, +{ PROC_LINKS(goto_next_jump_no_skips, 0), false, "goto_next_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, and does not skip sub jump locations.", 132, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 492 }, +{ PROC_LINKS(goto_prev_jump_no_skips, 0), false, "goto_prev_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations.", 136, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 509 }, +{ PROC_LINKS(goto_first_jump, 0), false, "goto_first_jump", 15, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer.", 95, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 523 }, +{ PROC_LINKS(goto_first_jump_same_panel_sticky, 0), false, "goto_first_jump_same_panel_sticky", 33, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer and views the buffer in the panel where the jump list was.", 153, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 540 }, +{ PROC_LINKS(if_read_only_goto_position, 0), false, "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 562 }, +{ PROC_LINKS(if_read_only_goto_position_same_panel, 0), false, "if_read_only_goto_position_same_panel", 37, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "w:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 579 }, +{ PROC_LINKS(view_jump_list_with_lister, 0), false, "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "w:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 59 }, +{ PROC_LINKS(show_the_log_graph, 0), true, "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 995 }, +{ PROC_LINKS(copy, 0), false, "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 19 }, +{ PROC_LINKS(cut, 0), false, "cut", 3, "Cut the text in the range from the cursor to the mark onto the clipboard.", 73, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 28 }, +{ PROC_LINKS(paste, 0), false, "paste", 5, "At the cursor, insert the text at the top of the clipboard.", 59, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 39 }, +{ PROC_LINKS(paste_next, 0), false, "paste_next", 10, "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 70 }, +{ PROC_LINKS(paste_and_indent, 0), false, "paste_and_indent", 16, "Paste from the top of clipboard and run auto-indent on the newly pasted text.", 77, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 108 }, +{ PROC_LINKS(paste_next_and_indent, 0), false, "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "w:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 115 }, +{ PROC_LINKS(execute_previous_cli, 0), false, "execute_previous_cli", 20, "If the command execute_any_cli has already been used, this will execute a CLI reusing the most recent buffer name and command.", 126, "w:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 7 }, +{ PROC_LINKS(execute_any_cli, 0), false, "execute_any_cli", 15, "Queries for an output buffer name and system command, runs the system command as a CLI and prints the output to the specified buffer.", 133, "w:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 22 }, +{ PROC_LINKS(build_search, 0), false, "build_search", 12, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*.", 153, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 128 }, +{ PROC_LINKS(build_in_build_panel, 0), false, "build_in_build_panel", 20, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*. Puts the *compilation* buffer in a panel at the footer of the current view.", 230, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 165 }, +{ PROC_LINKS(close_build_panel, 0), false, "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 180 }, +{ PROC_LINKS(change_to_build_panel, 0), false, "change_to_build_panel", 21, "If the special build panel is open, makes the build panel the active panel.", 75, "w:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 186 }, +{ PROC_LINKS(close_all_code, 0), false, "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 843 }, +{ PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 849 }, +{ PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 855 }, +{ PROC_LINKS(load_project, 0), false, "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 863 }, +{ PROC_LINKS(project_fkey_command, 0), false, "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 871 }, +{ PROC_LINKS(project_go_to_root_directory, 0), false, "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 897 }, +{ PROC_LINKS(setup_new_project, 0), false, "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1231 }, +{ PROC_LINKS(setup_build_bat, 0), false, "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1238 }, +{ PROC_LINKS(setup_build_sh, 0), false, "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1244 }, +{ PROC_LINKS(setup_build_bat_and_sh, 0), false, "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1250 }, +{ PROC_LINKS(project_command_lister, 0), false, "project_command_lister", 22, "Open a lister of all commands in the currently loaded project.", 62, "w:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1290 }, +{ PROC_LINKS(list_all_functions_current_buffer, 0), false, "list_all_functions_current_buffer", 33, "Creates a jump list of lines of the current buffer that appear to define or declare functions.", 94, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 267 }, +{ PROC_LINKS(list_all_functions_current_buffer_lister, 0), false, "list_all_functions_current_buffer_lister", 40, "Creates a lister of locations that look like function definitions and declarations in the buffer.", 97, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 277 }, +{ PROC_LINKS(list_all_functions_all_buffers, 0), false, "list_all_functions_all_buffers", 30, "Creates a jump list of lines from all buffers that appear to define or declare functions.", 89, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 295 }, +{ PROC_LINKS(list_all_functions_all_buffers_lister, 0), false, "list_all_functions_all_buffers_lister", 37, "Creates a lister of locations that look like function definitions and declarations all buffers.", 95, "w:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 301 }, +{ PROC_LINKS(select_surrounding_scope, 0), false, "select_surrounding_scope", 24, "Finds the scope enclosed by '{' '}' surrounding the cursor and puts the cursor and mark on the '{' and '}'.", 107, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 27 }, +{ PROC_LINKS(select_surrounding_scope_maximal, 0), false, "select_surrounding_scope_maximal", 32, "Selects the top-most scope that surrounds the cursor.", 53, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 39 }, +{ PROC_LINKS(select_next_scope_absolute, 0), false, "select_next_scope_absolute", 26, "Finds the first scope started by '{' after the cursor and puts the cursor and mark on the '{' and '}'.", 102, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 57 }, +{ PROC_LINKS(select_next_scope_after_current, 0), false, "select_next_scope_after_current", 31, "If a scope is selected, find first scope that starts after the selected scope. Otherwise find the first scope that starts after the cursor.", 139, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 66 }, +{ PROC_LINKS(select_prev_scope_absolute, 0), false, "select_prev_scope_absolute", 26, "Finds the first scope started by '{' before the cursor and puts the cursor and mark on the '{' and '}'.", 103, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 82 }, +{ PROC_LINKS(select_prev_top_most_scope, 0), false, "select_prev_top_most_scope", 26, "Finds the first scope that starts before the cursor, then finds the top most scope that contains that scope.", 108, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 99 }, +{ PROC_LINKS(place_in_scope, 0), false, "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 106 }, +{ PROC_LINKS(delete_current_scope, 0), false, "delete_current_scope", 20, "Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.", 99, "w:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 112 }, +{ PROC_LINKS(open_long_braces, 0), false, "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 46 }, +{ PROC_LINKS(open_long_braces_semicolon, 0), false, "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 54 }, +{ PROC_LINKS(open_long_braces_break, 0), false, "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 62 }, +{ PROC_LINKS(if0_off, 0), false, "if0_off", 7, "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 70 }, +{ PROC_LINKS(write_todo, 0), false, "write_todo", 10, "At the cursor, insert a '// TODO' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 76 }, +{ PROC_LINKS(write_hack, 0), false, "write_hack", 10, "At the cursor, insert a '// HACK' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 82 }, +{ PROC_LINKS(write_note, 0), false, "write_note", 10, "At the cursor, insert a '// NOTE' comment, includes user name if it was specified in config.4coder.", 99, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 88 }, +{ PROC_LINKS(write_block, 0), false, "write_block", 11, "At the cursor, insert a block comment.", 38, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 94 }, +{ PROC_LINKS(write_zero_struct, 0), false, "write_zero_struct", 17, "At the cursor, insert a ' = {};'.", 33, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 100 }, +{ PROC_LINKS(comment_line, 0), false, "comment_line", 12, "Insert '//' at the beginning of the line after leading whitespace.", 66, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 125 }, +{ PROC_LINKS(uncomment_line, 0), false, "uncomment_line", 14, "If present, delete '//' at the beginning of the line after leading whitespace.", 78, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 137 }, +{ PROC_LINKS(comment_line_toggle, 0), false, "comment_line_toggle", 19, "Turns uncommented lines into commented lines and vice versa for comments starting with '//'.", 92, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 149 }, +{ PROC_LINKS(snippet_lister, 0), false, "snippet_lister", 14, "Opens a snippet lister for inserting whole pre-written snippets of text.", 72, "w:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 237 }, +{ PROC_LINKS(miblo_increment_basic, 0), false, "miblo_increment_basic", 21, "Increment an integer under the cursor by one.", 45, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 29 }, +{ PROC_LINKS(miblo_decrement_basic, 0), false, "miblo_decrement_basic", 21, "Decrement an integer under the cursor by one.", 45, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 44 }, +{ PROC_LINKS(miblo_increment_time_stamp, 0), false, "miblo_increment_time_stamp", 26, "Increment a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 231 }, +{ PROC_LINKS(miblo_decrement_time_stamp, 0), false, "miblo_decrement_time_stamp", 26, "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 237 }, +{ PROC_LINKS(miblo_increment_time_stamp_minute, 0), false, "miblo_increment_time_stamp_minute", 33, "Increment a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 243 }, +{ PROC_LINKS(miblo_decrement_time_stamp_minute, 0), false, "miblo_decrement_time_stamp_minute", 33, "Decrement a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "w:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 249 }, +{ PROC_LINKS(profile_inspect, 0), true, "profile_inspect", 15, "Inspect all currently collected profiling information in 4coder's self profiler.", 80, "w:\\4ed\\code\\custom\\4coder_profile_inspect.cpp", 45, 890 }, +{ PROC_LINKS(kill_tutorial, 0), false, "kill_tutorial", 13, "If there is an active tutorial, kill it.", 40, "w:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 9 }, +{ PROC_LINKS(tutorial_maximize, 0), false, "tutorial_maximize", 17, "Expand the tutorial window", 26, "w:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 20 }, +{ PROC_LINKS(tutorial_minimize, 0), false, "tutorial_minimize", 17, "Shrink the tutorial window", 26, "w:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 34 }, +{ PROC_LINKS(hms_demo_tutorial, 0), false, "hms_demo_tutorial", 17, "Tutorial for built in 4coder bindings and features.", 51, "w:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 869 }, +{ PROC_LINKS(default_startup, 0), false, "default_startup", 15, "Default command for responding to a startup event", 49, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 7 }, +{ PROC_LINKS(default_try_exit, 0), false, "default_try_exit", 16, "Default command for responding to a try-exit event", 50, "w:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 22 }, }; static i32 fcoder_metacmd_ID_default_view_input_handler = 0; static i32 fcoder_metacmd_ID_profile_enable = 1; diff --git a/custom/generated/system_api.cpp b/custom/generated/system_api.cpp index 5b190f6b..155bee65 100644 --- a/custom/generated/system_api.cpp +++ b/custom/generated/system_api.cpp @@ -42,6 +42,7 @@ vtable->condition_variable_free = system_condition_variable_free; vtable->memory_allocate = system_memory_allocate; vtable->memory_set_protection = system_memory_set_protection; vtable->memory_free = system_memory_free; +vtable->memory_annotation = system_memory_annotation; vtable->show_mouse_cursor = system_show_mouse_cursor; vtable->set_fullscreen = system_set_fullscreen; vtable->is_fullscreen = system_is_fullscreen; @@ -92,6 +93,7 @@ system_condition_variable_free = vtable->condition_variable_free; system_memory_allocate = vtable->memory_allocate; system_memory_set_protection = vtable->memory_set_protection; system_memory_free = vtable->memory_free; +system_memory_annotation = vtable->memory_annotation; system_show_mouse_cursor = vtable->show_mouse_cursor; system_set_fullscreen = vtable->set_fullscreen; system_is_fullscreen = vtable->is_fullscreen; diff --git a/custom/generated/system_api.h b/custom/generated/system_api.h index 5b72162d..19be05af 100644 --- a/custom/generated/system_api.h +++ b/custom/generated/system_api.h @@ -37,9 +37,10 @@ #define system_condition_variable_wait_sig() void system_condition_variable_wait(System_Condition_Variable cv, System_Mutex mutex) #define system_condition_variable_signal_sig() void system_condition_variable_signal(System_Condition_Variable cv) #define system_condition_variable_free_sig() void system_condition_variable_free(System_Condition_Variable cv) -#define system_memory_allocate_sig() void* system_memory_allocate(umem size) +#define system_memory_allocate_sig() void* system_memory_allocate(umem size, String_Const_u8 location) #define system_memory_set_protection_sig() b32 system_memory_set_protection(void* ptr, umem size, u32 flags) #define system_memory_free_sig() void system_memory_free(void* ptr, umem size) +#define system_memory_annotation_sig() Memory_Annotation system_memory_annotation(Arena* arena) #define system_show_mouse_cursor_sig() void system_show_mouse_cursor(i32 show) #define system_set_fullscreen_sig() b32 system_set_fullscreen(b32 full_screen) #define system_is_fullscreen_sig() b32 system_is_fullscreen(void) @@ -83,9 +84,10 @@ typedef System_Condition_Variable system_condition_variable_make_type(void); typedef void system_condition_variable_wait_type(System_Condition_Variable cv, System_Mutex mutex); typedef void system_condition_variable_signal_type(System_Condition_Variable cv); typedef void system_condition_variable_free_type(System_Condition_Variable cv); -typedef void* system_memory_allocate_type(umem size); +typedef void* system_memory_allocate_type(umem size, String_Const_u8 location); typedef b32 system_memory_set_protection_type(void* ptr, umem size, u32 flags); typedef void system_memory_free_type(void* ptr, umem size); +typedef Memory_Annotation system_memory_annotation_type(Arena* arena); typedef void system_show_mouse_cursor_type(i32 show); typedef b32 system_set_fullscreen_type(b32 full_screen); typedef b32 system_is_fullscreen_type(void); @@ -133,6 +135,7 @@ system_condition_variable_free_type *condition_variable_free; system_memory_allocate_type *memory_allocate; system_memory_set_protection_type *memory_set_protection; system_memory_free_type *memory_free; +system_memory_annotation_type *memory_annotation; system_show_mouse_cursor_type *show_mouse_cursor; system_set_fullscreen_type *set_fullscreen; system_is_fullscreen_type *is_fullscreen; @@ -178,9 +181,10 @@ internal System_Condition_Variable system_condition_variable_make(void); internal void system_condition_variable_wait(System_Condition_Variable cv, System_Mutex mutex); internal void system_condition_variable_signal(System_Condition_Variable cv); internal void system_condition_variable_free(System_Condition_Variable cv); -internal void* system_memory_allocate(umem size); +internal void* system_memory_allocate(umem size, String_Const_u8 location); internal b32 system_memory_set_protection(void* ptr, umem size, u32 flags); internal void system_memory_free(void* ptr, umem size); +internal Memory_Annotation system_memory_annotation(Arena* arena); internal void system_show_mouse_cursor(i32 show); internal b32 system_set_fullscreen(b32 full_screen); internal b32 system_is_fullscreen(void); @@ -229,6 +233,7 @@ global system_condition_variable_free_type *system_condition_variable_free = 0; global system_memory_allocate_type *system_memory_allocate = 0; global system_memory_set_protection_type *system_memory_set_protection = 0; global system_memory_free_type *system_memory_free = 0; +global system_memory_annotation_type *system_memory_annotation = 0; global system_show_mouse_cursor_type *system_show_mouse_cursor = 0; global system_set_fullscreen_type *system_set_fullscreen = 0; global system_is_fullscreen_type *system_is_fullscreen = 0; diff --git a/custom/generated/system_api_master_list.h b/custom/generated/system_api_master_list.h index 57cef0fe..8332a293 100644 --- a/custom/generated/system_api_master_list.h +++ b/custom/generated/system_api_master_list.h @@ -37,9 +37,10 @@ api(system) function System_Condition_Variable condition_variable_make(void); api(system) function void condition_variable_wait(System_Condition_Variable cv, System_Mutex mutex); api(system) function void condition_variable_signal(System_Condition_Variable cv); api(system) function void condition_variable_free(System_Condition_Variable cv); -api(system) function void* memory_allocate(umem size); +api(system) function void* memory_allocate(umem size, String_Const_u8 location); api(system) function b32 memory_set_protection(void* ptr, umem size, u32 flags); api(system) function void memory_free(void* ptr, umem size); +api(system) function Memory_Annotation memory_annotation(Arena* arena); api(system) function void show_mouse_cursor(i32 show); api(system) function b32 set_fullscreen(b32 full_screen); api(system) function b32 is_fullscreen(void); diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index e2fc3e4a..d9a6e035 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -739,7 +739,7 @@ win32_alloc_object(Win32_Object_Kind kind){ } if (result == 0){ i32 count = 512; - Win32_Object *objects = (Win32_Object*)system_memory_allocate(count*sizeof(Win32_Object)); + Win32_Object *objects = (Win32_Object*)system_memory_allocate(count*sizeof(Win32_Object), file_name_line_number_lit_u8); objects[0].node.prev = &win32vars.free_win32_objects; win32vars.free_win32_objects.next = &objects[0].node; for (i32 i = 1; i < count; i += 1){ @@ -1457,6 +1457,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS i32 argc = __argc; char **argv = __argv; + InitializeCriticalSection(&memory_tracker_mutex); + // NOTE(allen): context setup Thread_Context _tctx = {}; thread_ctx_init(&_tctx, ThreadKind_Main, get_base_allocator_system(), get_base_allocator_system()); @@ -1476,7 +1478,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS // NOTE(allen): memory win32vars.frame_arena = reserve_arena(win32vars.tctx); // TODO(allen): *arena; - target.arena = make_arena_system(); + target.arena = make_arena_system(KB(256)); win32vars.cursor_show = MouseCursorShow_Always; win32vars.prev_cursor_show = MouseCursorShow_Always; diff --git a/platform_win32/win32_4ed_functions.cpp b/platform_win32/win32_4ed_functions.cpp index b2521db4..2f7c038e 100644 --- a/platform_win32/win32_4ed_functions.cpp +++ b/platform_win32/win32_4ed_functions.cpp @@ -24,21 +24,54 @@ system_file_can_be_made(Arena *scratch, u8 *filename){ // Memory // +struct Memory_Annotation_Tracker_Node{ + Memory_Annotation_Tracker_Node *next; + Memory_Annotation_Tracker_Node *prev; + String_Const_u8 location; + umem size; +}; + +struct Memory_Annotation_Tracker{ + Memory_Annotation_Tracker_Node *first; + Memory_Annotation_Tracker_Node *last; + i32 count; +}; + +global Memory_Annotation_Tracker memory_tracker = {}; +global CRITICAL_SECTION memory_tracker_mutex; + internal void* -win32_memory_allocate_extended(void *base, umem size){ - void *result = VirtualAlloc(base, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - return(result); +win32_memory_allocate_extended(void *base, umem size, String_Const_u8 location){ + umem adjusted_size = size + 64; + void *result = VirtualAlloc(base, adjusted_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + Memory_Annotation_Tracker_Node *node = (Memory_Annotation_Tracker_Node*)result; + EnterCriticalSection(&memory_tracker_mutex); + zdll_push_back(memory_tracker.first, memory_tracker.last, node); + memory_tracker.count += 1; + LeaveCriticalSection(&memory_tracker_mutex); + node->location = location; + node->size = size; + return(node + 1); +} + +internal void +win32_memory_free_extended(void *ptr){ + Memory_Annotation_Tracker_Node *node = (Memory_Annotation_Tracker_Node*)ptr; + node -= 1; + EnterCriticalSection(&memory_tracker_mutex); + zdll_remove(memory_tracker.first, memory_tracker.last, node); + memory_tracker.count -= 1; + LeaveCriticalSection(&memory_tracker_mutex); + VirtualFree(node, 0, MEM_RELEASE); } internal system_memory_allocate_sig(){ - return(win32_memory_allocate_extended(0, size)); + return(win32_memory_allocate_extended(0, size, location)); } internal system_memory_set_protection_sig(){ - b32 result = false; - DWORD old_protect = 0; DWORD protect = 0; switch (flags & 0x7){ @@ -52,13 +85,37 @@ system_memory_set_protection_sig(){ case MemProtect_Execute|MemProtect_Write|MemProtect_Read: protect = PAGE_EXECUTE_READWRITE; break; } - VirtualProtect(ptr, size, protect, &old_protect); + Memory_Annotation_Tracker_Node *node = (Memory_Annotation_Tracker_Node*)ptr; + node -= 1; + + DWORD old_protect = 0; + b32 result = VirtualProtect(node, size, protect, &old_protect); return(result); } internal system_memory_free_sig(){ - VirtualFree(ptr, 0, MEM_RELEASE); + win32_memory_free_extended(ptr); +} + +internal +system_memory_annotation_sig(){ + Memory_Annotation result = {}; + EnterCriticalSection(&memory_tracker_mutex); + + for (Memory_Annotation_Tracker_Node *node = memory_tracker.first; + node != 0; + node = node->next){ + Memory_Annotation_Node *r_node = push_array(arena, Memory_Annotation_Node, 1); + sll_queue_push(result.first, result.last, r_node); + result.count += 1; + r_node->location = node->location; + r_node->address = node + 1; + r_node->size = node->size; + } + + LeaveCriticalSection(&memory_tracker_mutex); + return(result); } // @@ -83,7 +140,7 @@ system_get_path_sig(){ if (!has_stashed_4ed_path){ has_stashed_4ed_path = true; local_const i32 binary_path_capacity = KB(32); - u8 *memory = (u8*)system_memory_allocate(binary_path_capacity); + u8 *memory = (u8*)system_memory_allocate(binary_path_capacity, string_u8_litexpr(file_name_line_number)); i32 size = GetModuleFileName_utf8(arena, 0, memory, binary_path_capacity); Assert(size <= binary_path_capacity - 1); win32vars.binary_path = SCu8(memory, size); @@ -478,7 +535,7 @@ system_open_color_picker_sig(){ // NOTE(casey): Because this is going to be used by a semi-permanent thread, we need to // copy it to system memory where it can live as long as it wants, no matter what we do // over here on the 4coder threads. - Color_Picker *perm = (Color_Picker*)system_memory_allocate(sizeof(Color_Picker)); + Color_Picker *perm = (Color_Picker*)system_memory_allocate(sizeof(Color_Picker), string_u8_litexpr(file_name_line_number)); *perm = *picker; HANDLE ThreadHandle = CreateThread(0, 0, color_picker_thread, perm, 0, 0);