/* 4coder_config.cpp - Parsing *.4coder files. */ // TOP static CString_Array get_code_extensions(Extension_List *list){ CString_Array array = {}; array.strings = default_extensions; array.count = ArrayCount(default_extensions); if (list->count != 0){ array.strings = list->exts; array.count = list->count; } return(array); } static void parse_extension_line_to_extension_list(String str, Extension_List *list){ i32 mode = 0; i32 j = 0, k = 0; for (i32 i = 0; i < str.size; ++i){ switch (mode){ case 0: { if (str.str[i] == '.'){ mode = 1; list->exts[k++] = &list->space[j]; } }break; case 1: { if (str.str[i] == '.'){ list->space[j++] = 0; list->exts[k++] = &list->space[j]; } else{ list->space[j++] = str.str[i]; } }break; } } list->space[j++] = 0; list->count = k; } //////////////////////////////// static Error_Location get_error_location(char *base, char *pos){ Error_Location location = {}; location.line_number = 1; location.column_number = 1; for (char *ptr = base; ptr < pos; ptr += 1){ if (*ptr == '\n'){ location.line_number += 1; location.column_number = 1; } else{ location.column_number += 1; } } return(location); } static String config_stringize_errors(Partition *arena, Config *parsed){ String result = {}; if (parsed->errors.first != 0){ result.str = push_array(arena, char, 0); result.memory_size = part_remaining(arena); for (Config_Error *error = parsed->errors.first; error != 0; error = error->next){ Error_Location location = get_error_location(parsed->data.str, error->pos); append(&result, error->file_name); append(&result, ":"); append_int_to_str(&result, location.line_number); append(&result, ":"); append_int_to_str(&result, location.column_number); append(&result, ": "); append(&result, error->text); append(&result, "\n"); } result.memory_size = result.size; push_array(arena, char, result.size); } return(result); } //////////////////////////////// static void config_parser__advance_to_next(Config_Parser *ctx){ Cpp_Token *t = ctx->token; Cpp_Token *e = ctx->end; for (t += 1; t < e && t->type == CPP_TOKEN_COMMENT; t += 1); ctx->token = t; } static Config_Parser make_config_parser(Partition *arena, String file_name, String data, Cpp_Token_Array array){ Config_Parser ctx = {}; ctx.start = array.tokens; ctx.token = ctx.start - 1; ctx.end = ctx.start + array.count; ctx.file_name = file_name; ctx.data = data; ctx.arena = arena; config_parser__advance_to_next(&ctx); return(ctx); } static b32 config_parser__recognize_token(Config_Parser *ctx, Cpp_Token_Type type){ b32 result = false; if (ctx->start <= ctx->token && ctx->token < ctx->end){ result = (ctx->token->type == type); } else if (type == CPP_TOKEN_EOF){ result = true; } return(result); } static b32 config_parser__recognize_token_category(Config_Parser *ctx, Cpp_Token_Category category){ b32 result = false; if (ctx->start <= ctx->token && ctx->token < ctx->end){ result = (cpp_token_category_from_type(ctx->token->type) == category); } else if (category == CPP_TOKEN_CAT_EOF){ result = true; } return(result); } static String config_parser__get_lexeme(Config_Parser *ctx){ String lexeme = {}; if (ctx->start <= ctx->token && ctx->token < ctx->end){ lexeme = make_string(ctx->data.str + ctx->token->start, ctx->token->size); } return(lexeme); } static Config_Integer config_parser__get_int(Config_Parser *ctx){ Config_Integer config_integer = {}; String str = config_parser__get_lexeme(ctx); if (match(substr(str, 0, 2), "0x")){ config_integer.is_signed = false; config_integer.uinteger = hexstr_to_int(substr_tail(str, 2)); } else{ config_integer.is_signed = true; config_integer.integer = str_to_int(str); } return(config_integer); } static b32 config_parser__get_boolean(Config_Parser *ctx){ String str = config_parser__get_lexeme(ctx); return(match(str, "true")); } static b32 config_parser__recognize_text(Config_Parser *ctx, String text){ b32 result = false; String lexeme = config_parser__get_lexeme(ctx); if (lexeme.str != 0 && match(lexeme, text)){ result = true; } return(result); } static b32 config_parser__match_token(Config_Parser *ctx, Cpp_Token_Type type){ b32 result = config_parser__recognize_token(ctx, type); if (result){ config_parser__advance_to_next(ctx); } return(result); } static b32 config_parser__match_text(Config_Parser *ctx, String text){ b32 result = config_parser__recognize_text(ctx, text); if (result){ config_parser__advance_to_next(ctx); } return(result); } static Config *config_parser__config (Config_Parser *ctx); static i32 *config_parser__version (Config_Parser *ctx); static Config_Assignment *config_parser__assignment(Config_Parser *ctx); static Config_LValue *config_parser__lvalue (Config_Parser *ctx); static Config_RValue *config_parser__rvalue (Config_Parser *ctx); static Config_Compound *config_parser__compound (Config_Parser *ctx); static Config_Compound_Element *config_parser__element (Config_Parser *ctx); static Config* text_data_and_token_array_to_parse_data(Partition *arena, String file_name, String data, Cpp_Token_Array array){ Temp_Memory restore_point = begin_temp_memory(arena); Config_Parser ctx = make_config_parser(arena, file_name, data, array); Config *config = config_parser__config(&ctx); if (config == 0){ end_temp_memory(restore_point); } return(config); } // TODO(allen): Move to string library static String config_begin_string(Partition *arena){ String str; str.str = push_array(arena, char, 0); str.size = 0; str.memory_size = arena->max - arena->pos; return(str); } static void config_end_string(Partition *arena, String *str){ str->memory_size = str->size; push_array(arena, char, str->size); } static Config_Error* config_error_push(Partition *arena, Config_Error_List *list, String file_name, char *pos, char *error_text){ Config_Error *error = push_array(arena, Config_Error, 1); zdll_push_back(list->first, list->last, error); list->count += 1; error->file_name = file_name; error->pos = pos; error->text = config_begin_string(arena); append(&error->text, error_text); config_end_string(arena, &error->text); return(error); } static char* config_parser__get_pos(Config_Parser *ctx){ return(ctx->data.str + ctx->token->start); } static void config_parser__log_error_pos(Config_Parser *ctx, char *pos, char *error_text){ config_error_push(ctx->arena, &ctx->errors, ctx->file_name, pos, error_text); } static void config_parser__log_error(Config_Parser *ctx, char *error_text){ config_parser__log_error_pos(ctx, config_parser__get_pos(ctx), error_text); } static Config* config_parser__config(Config_Parser *ctx){ i32 *version = config_parser__version(ctx); Config_Assignment *first = 0; Config_Assignment *last = 0; i32 count = 0; for (;!config_parser__recognize_token(ctx, CPP_TOKEN_EOF);){ Config_Assignment *assignment = config_parser__assignment(ctx); if (assignment != 0){ zdll_push_back(first, last, assignment); count += 1; } } Config *config = push_array(ctx->arena, Config, 1); memset(config, 0, sizeof(*config)); config->version = version; config->first = first; config->last = last; config->count = count; config->errors = ctx->errors; config->file_name = ctx->file_name; config->data = ctx->data; return(config); } static void config_parser__recover_parse(Config_Parser *ctx){ for (;;){ if (config_parser__match_token(ctx, CPP_TOKEN_SEMICOLON)){ break; } if (config_parser__recognize_token(ctx, CPP_TOKEN_EOF)){ break; } config_parser__advance_to_next(ctx); } } static i32* config_parser__version(Config_Parser *ctx){ require(config_parser__match_text(ctx, make_lit_string("version"))); if (!config_parser__match_token(ctx, CPP_TOKEN_PARENTHESE_OPEN)){ config_parser__log_error(ctx, "expected token '(' for version specifier: 'version(#)'"); config_parser__recover_parse(ctx); return(0); } if (!config_parser__recognize_token(ctx, CPP_TOKEN_INTEGER_CONSTANT)){ config_parser__log_error(ctx, "expected an integer constant for version specifier: 'version(#)'"); config_parser__recover_parse(ctx); return(0); } Config_Integer value = config_parser__get_int(ctx); config_parser__advance_to_next(ctx); if (!config_parser__match_token(ctx, CPP_TOKEN_PARENTHESE_CLOSE)){ config_parser__log_error(ctx, "expected token ')' for version specifier: 'version(#)'"); config_parser__recover_parse(ctx); return(0); } if (!config_parser__match_token(ctx, CPP_TOKEN_SEMICOLON)){ config_parser__log_error(ctx, "expected token ';' for version specifier: 'version(#)'"); config_parser__recover_parse(ctx); return(0); } i32 *ptr = push_array(ctx->arena, i32, 1); *ptr = value.integer; return(ptr); } static Config_Assignment* config_parser__assignment(Config_Parser *ctx){ char *pos = config_parser__get_pos(ctx); Config_LValue *l = config_parser__lvalue(ctx); if (l == 0){ config_parser__log_error(ctx, "expected an l-value; l-value formats: 'identifier', 'identifier[#]'"); config_parser__recover_parse(ctx); return(0); } if (!config_parser__match_token(ctx, CPP_TOKEN_EQ)){ config_parser__log_error(ctx, "expected token '=' for assignment: 'l-value = r-value;'"); config_parser__recover_parse(ctx); return(0); } Config_RValue *r = config_parser__rvalue(ctx); if (r == 0){ config_parser__log_error(ctx, "expected an r-value; r-value formats:\n" "\tconstants (true, false, integers, hexadecimal integers, strings, characters)\n" "\tany l-value that is set in the file\n" "\tcompound: '{ compound-element, compound-element, compound-element ...}'\n" "\ta compound-element is an r-value, and can have a layout specifier\n" "\tcompound-element with layout specifier: .name = r-value, .integer = r-value"); config_parser__recover_parse(ctx); return(0); } if (!config_parser__match_token(ctx, CPP_TOKEN_SEMICOLON)){ config_parser__log_error(ctx, "expected token ';' for assignment: 'l-value = r-value;'"); config_parser__recover_parse(ctx); return(0); } Config_Assignment *assignment = push_array(ctx->arena, Config_Assignment, 1); memset(assignment, 0, sizeof(*assignment)); assignment->pos = pos; assignment->l = l; assignment->r = r; return(assignment); } static Config_LValue* config_parser__lvalue(Config_Parser *ctx){ require(config_parser__recognize_token(ctx, CPP_TOKEN_IDENTIFIER)); String identifier = config_parser__get_lexeme(ctx); config_parser__advance_to_next(ctx); i32 index = 0; if (config_parser__match_token(ctx, CPP_TOKEN_BRACKET_OPEN)){ require(config_parser__recognize_token(ctx, CPP_TOKEN_INTEGER_CONSTANT)); Config_Integer value = config_parser__get_int(ctx); index = value.integer; config_parser__advance_to_next(ctx); require(config_parser__match_token(ctx, CPP_TOKEN_BRACKET_CLOSE)); } Config_LValue *lvalue = push_array(ctx->arena, Config_LValue, 1); memset(lvalue, 0, sizeof(*lvalue)); lvalue->identifier = identifier; lvalue->index = index; return(lvalue); } static Config_RValue* config_parser__rvalue(Config_Parser *ctx){ if (config_parser__recognize_token(ctx, CPP_TOKEN_IDENTIFIER)){ Config_LValue *l = config_parser__lvalue(ctx); require(l != 0); Config_RValue *rvalue = push_array(ctx->arena, Config_RValue, 1); memset(rvalue, 0, sizeof(*rvalue)); rvalue->type = ConfigRValueType_LValue; rvalue->lvalue = l; return(rvalue); } else if (config_parser__recognize_token(ctx, CPP_TOKEN_BRACE_OPEN)){ config_parser__advance_to_next(ctx); Config_Compound *compound = config_parser__compound(ctx); require(compound != 0); Config_RValue *rvalue = push_array(ctx->arena, Config_RValue, 1); memset(rvalue, 0, sizeof(*rvalue)); rvalue->type = ConfigRValueType_Compound; rvalue->compound = compound; return(rvalue); } else if (config_parser__recognize_token_category(ctx, CPP_TOKEN_CAT_BOOLEAN_CONSTANT)){ b32 b = config_parser__get_boolean(ctx); config_parser__advance_to_next(ctx); Config_RValue *rvalue = push_array(ctx->arena, Config_RValue, 1); memset(rvalue, 0, sizeof(*rvalue)); rvalue->type = ConfigRValueType_Boolean; rvalue->boolean = b; return(rvalue); } else if (config_parser__recognize_token(ctx, CPP_TOKEN_INTEGER_CONSTANT)){ Config_Integer value = config_parser__get_int(ctx); config_parser__advance_to_next(ctx); Config_RValue *rvalue = push_array(ctx->arena, Config_RValue, 1); memset(rvalue, 0, sizeof(*rvalue)); rvalue->type = ConfigRValueType_Integer; if (value.is_signed){ rvalue->integer = value.integer; } else{ rvalue->uinteger = value.uinteger; } return(rvalue); } else if (config_parser__recognize_token(ctx, CPP_TOKEN_STRING_CONSTANT)){ String s = config_parser__get_lexeme(ctx); config_parser__advance_to_next(ctx); char *space = push_array(ctx->arena, char, s.size + 1); push_align(ctx->arena, 8); s = substr(s, 1, s.size - 2); string_interpret_escapes(s, space); Config_RValue *rvalue = push_array(ctx->arena, Config_RValue, 1); memset(rvalue, 0, sizeof(*rvalue)); rvalue->type = ConfigRValueType_String; rvalue->string = make_string_slowly(space); return(rvalue); } else if (config_parser__recognize_token(ctx, CPP_TOKEN_CHARACTER_CONSTANT)){ String s = config_parser__get_lexeme(ctx); config_parser__advance_to_next(ctx); char *space = push_array(ctx->arena, char, s.size + 1); push_align(ctx->arena, 8); s = substr(s, 1, s.size - 2); string_interpret_escapes(s, space); Config_RValue *rvalue = push_array(ctx->arena, Config_RValue, 1); memset(rvalue, 0, sizeof(*rvalue)); rvalue->type = ConfigRValueType_Character; rvalue->character = space[0]; return(rvalue); } return(0); } static void config_parser__compound__check(Config_Parser *ctx, Config_Compound *compound){ b32 implicit_index_allowed = true; for (Config_Compound_Element *node = compound->first; node != 0; node = node->next){ if (node->l.type != ConfigLayoutType_Unset){ implicit_index_allowed = false; } else if (!implicit_index_allowed){ config_parser__log_error_pos(ctx, node->l.pos, "encountered unlabeled member after one or more labeled members"); } } } static Config_Compound* config_parser__compound(Config_Parser *ctx){ Config_Compound_Element *first = 0; Config_Compound_Element *last = 0; i32 count = 0; Config_Compound_Element *element = config_parser__element(ctx); require(element != 0); zdll_push_back(first, last, element); count += 1; for (;config_parser__match_token(ctx, CPP_TOKEN_COMMA);){ if (config_parser__recognize_token(ctx, CPP_TOKEN_BRACE_CLOSE)){ break; } element = config_parser__element(ctx); require(element != 0); zdll_push_back(first, last, element); count += 1; } require(config_parser__match_token(ctx, CPP_TOKEN_BRACE_CLOSE)); Config_Compound *compound = push_array(ctx->arena, Config_Compound, 1); memset(compound, 0, sizeof(*compound)); compound->first = first; compound->last = last; compound->count = count; config_parser__compound__check(ctx, compound); return(compound); } static Config_Compound_Element* config_parser__element(Config_Parser *ctx){ Config_Layout layout = {}; layout.pos = config_parser__get_pos(ctx); if (config_parser__match_token(ctx, CPP_TOKEN_DOT)){ if (config_parser__recognize_token(ctx, CPP_TOKEN_IDENTIFIER)){ layout.type = ConfigLayoutType_Identifier; layout.identifier = config_parser__get_lexeme(ctx); config_parser__advance_to_next(ctx); } else if (config_parser__recognize_token(ctx, CPP_TOKEN_INTEGER_CONSTANT)){ layout.type = ConfigLayoutType_Integer; Config_Integer value = config_parser__get_int(ctx); layout.integer = value.integer; config_parser__advance_to_next(ctx); } else{ return(0); } require(config_parser__match_token(ctx, CPP_TOKEN_EQ)); } Config_RValue *rvalue = config_parser__rvalue(ctx); require(rvalue != 0); Config_Compound_Element *element = push_array(ctx->arena, Config_Compound_Element, 1); memset(element, 0, sizeof(*element)); element->l = layout; element->r = rvalue; return(element); } //////////////////////////////// static Config_Error* config_add_error(Partition *arena, Config *config, char *pos, char *error_text){ return(config_error_push(arena, &config->errors, config->file_name, pos, error_text)); } //////////////////////////////// static Config_Assignment* config_lookup_assignment(Config *config, String var_name, i32 subscript){ Config_Assignment *assignment; for (assignment = config->first; assignment != 0; assignment = assignment->next){ Config_LValue *l = assignment->l; if (l != 0 && match(l->identifier, var_name) && l->index == subscript){ break; } } return(assignment); } static Config_Get_Result config_var(Config *config, String var_name, i32 subscript); static Config_Get_Result config_evaluate_rvalue(Config *config, Config_Assignment *assignment, Config_RValue *r){ Config_Get_Result result = {}; if (r != 0 && !assignment->visited){ if (r->type == ConfigRValueType_LValue){ assignment->visited = true; Config_LValue *l = r->lvalue; result = config_var(config, l->identifier, l->index); assignment->visited = false; } else{ result.success = true; result.pos = assignment->pos; result.type = r->type; switch (r->type){ case ConfigRValueType_Boolean: { result.boolean = r->boolean; }break; case ConfigRValueType_Integer: { result.integer = r->integer; }break; case ConfigRValueType_String: { result.string = r->string; }break; case ConfigRValueType_Character: { result.character = r->character; }break; case ConfigRValueType_Compound: { result.compound = r->compound; }break; } } } return(result); } static Config_Get_Result config_var(Config *config, String var_name, i32 subscript){ Config_Get_Result result = {}; Config_Assignment *assignment = config_lookup_assignment(config, var_name, subscript); if (assignment != 0){ result = config_evaluate_rvalue(config, assignment, assignment->r); } return(result); } static Config_Get_Result config_compound_member(Config *config, Config_Compound *compound, String var_name, i32 index){ Config_Get_Result result = {}; i32 implicit_index = 0; b32 implicit_index_is_valid = true; for (Config_Compound_Element *element = compound->first; element != 0; element = element->next, implicit_index += 1){ b32 element_matches_query = false; switch (element->l.type){ case ConfigLayoutType_Unset: { if (implicit_index_is_valid && index == implicit_index){ element_matches_query = true; } }break; case ConfigLayoutType_Identifier: { implicit_index_is_valid = false; if (match(element->l.identifier, var_name)){ element_matches_query = true; } }break; case ConfigLayoutType_Integer: { implicit_index_is_valid = false; if (element->l.integer == index){ element_matches_query = true; } }break; } if (element_matches_query){ Config_Assignment dummy_assignment = {}; dummy_assignment.pos = element->l.pos; result = config_evaluate_rvalue(config, &dummy_assignment, element->r); break; } } return(result); } static Config_Iteration_Step_Result typed_array_iteration_step(Config *parsed, Config_Compound *compound, Config_RValue_Type type, i32 index); static i32 typed_array_get_count(Config *parsed, Config_Compound *compound, Config_RValue_Type type); static Config_Get_Result_List typed_array_reference_list(Partition *arena, Config *parsed, Config_Compound *compound, Config_RValue_Type type); #define config_fixed_string_var(c,v,s,o,a) config_placed_string_var((c),(v),(s),(o),(a),sizeof(a)) //////////////////////////////// static b32 config_has_var(Config *config, String var_name, i32 subscript){ Config_Get_Result result = config_var(config, var_name, subscript); b32 success = result.success && result.type == ConfigRValueType_NoType; return(success); } static b32 config_has_var(Config *config, char *var_name, i32 subscript){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_var(config, var_name_str, subscript); b32 success = result.success && result.type == ConfigRValueType_NoType; return(success); } static b32 config_bool_var(Config *config, String var_name, i32 subscript, b32* var_out){ Config_Get_Result result = config_var(config, var_name, subscript); b32 success = result.success && result.type == ConfigRValueType_Boolean; if (success){ *var_out = result.boolean; } return(success); } static b32 config_bool_var(Config *config, char *var_name, i32 subscript, b32* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_var(config, var_name_str, subscript); b32 success = result.success && result.type == ConfigRValueType_Boolean; if (success){ *var_out = result.boolean; } return(success); } static b32 config_int_var(Config *config, String var_name, i32 subscript, i32* var_out){ Config_Get_Result result = config_var(config, var_name, subscript); b32 success = result.success && result.type == ConfigRValueType_Integer; if (success){ *var_out = result.integer; } return(success); } static b32 config_int_var(Config *config, char *var_name, i32 subscript, i32* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_var(config, var_name_str, subscript); b32 success = result.success && result.type == ConfigRValueType_Integer; if (success){ *var_out = result.integer; } return(success); } static b32 config_uint_var(Config *config, String var_name, i32 subscript, u32* var_out){ Config_Get_Result result = config_var(config, var_name, subscript); b32 success = result.success && result.type == ConfigRValueType_Integer; if (success){ *var_out = result.uinteger; } return(success); } static b32 config_uint_var(Config *config, char *var_name, i32 subscript, u32* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_var(config, var_name_str, subscript); b32 success = result.success && result.type == ConfigRValueType_Integer; if (success){ *var_out = result.uinteger; } return(success); } static b32 config_string_var(Config *config, String var_name, i32 subscript, String* var_out){ Config_Get_Result result = config_var(config, var_name, subscript); b32 success = result.success && result.type == ConfigRValueType_String; if (success){ *var_out = result.string; } return(success); } static b32 config_string_var(Config *config, char *var_name, i32 subscript, String* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_var(config, var_name_str, subscript); b32 success = result.success && result.type == ConfigRValueType_String; if (success){ *var_out = result.string; } return(success); } static b32 config_placed_string_var(Config *config, String var_name, i32 subscript, String* var_out, char *space, i32 space_size){ Config_Get_Result result = config_var(config, var_name, subscript); b32 success = result.success && result.type == ConfigRValueType_String; if (success){ *var_out = result.string; } if (success){ String str = *var_out; *var_out = make_string_cap(space, 0, space_size); copy(var_out, str); } return(success); } static b32 config_placed_string_var(Config *config, char *var_name, i32 subscript, String* var_out, char *space, i32 space_size){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_var(config, var_name_str, subscript); b32 success = result.success && result.type == ConfigRValueType_String; if (success){ *var_out = result.string; } if (success){ String str = *var_out; *var_out = make_string_cap(space, 0, space_size); copy(var_out, str); } return(success); } static b32 config_char_var(Config *config, String var_name, i32 subscript, char* var_out){ Config_Get_Result result = config_var(config, var_name, subscript); b32 success = result.success && result.type == ConfigRValueType_Character; if (success){ *var_out = result.character; } return(success); } static b32 config_char_var(Config *config, char *var_name, i32 subscript, char* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_var(config, var_name_str, subscript); b32 success = result.success && result.type == ConfigRValueType_Character; if (success){ *var_out = result.character; } return(success); } static b32 config_compound_var(Config *config, String var_name, i32 subscript, Config_Compound** var_out){ Config_Get_Result result = config_var(config, var_name, subscript); b32 success = result.success && result.type == ConfigRValueType_Compound; if (success){ *var_out = result.compound; } return(success); } static b32 config_compound_var(Config *config, char *var_name, i32 subscript, Config_Compound** var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_var(config, var_name_str, subscript); b32 success = result.success && result.type == ConfigRValueType_Compound; if (success){ *var_out = result.compound; } return(success); } static b32 config_compound_has_member(Config *config, Config_Compound *compound, String var_name, i32 index){ Config_Get_Result result = config_compound_member(config, compound, var_name, index); b32 success = result.success && result.type == ConfigRValueType_NoType; return(success); } static b32 config_compound_has_member(Config *config, Config_Compound *compound, char *var_name, i32 index){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_compound_member(config, compound, var_name_str, index); b32 success = result.success && result.type == ConfigRValueType_NoType; return(success); } static b32 config_compound_bool_member(Config *config, Config_Compound *compound, String var_name, i32 index, b32* var_out){ Config_Get_Result result = config_compound_member(config, compound, var_name, index); b32 success = result.success && result.type == ConfigRValueType_Boolean; if (success){ *var_out = result.boolean; } return(success); } static b32 config_compound_bool_member(Config *config, Config_Compound *compound, char *var_name, i32 index, b32* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_compound_member(config, compound, var_name_str, index); b32 success = result.success && result.type == ConfigRValueType_Boolean; if (success){ *var_out = result.boolean; } return(success); } static b32 config_compound_int_member(Config *config, Config_Compound *compound, String var_name, i32 index, i32* var_out){ Config_Get_Result result = config_compound_member(config, compound, var_name, index); b32 success = result.success && result.type == ConfigRValueType_Integer; if (success){ *var_out = result.integer; } return(success); } static b32 config_compound_int_member(Config *config, Config_Compound *compound, char *var_name, i32 index, i32* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_compound_member(config, compound, var_name_str, index); b32 success = result.success && result.type == ConfigRValueType_Integer; if (success){ *var_out = result.integer; } return(success); } static b32 config_compound_uint_member(Config *config, Config_Compound *compound, String var_name, i32 index, u32* var_out){ Config_Get_Result result = config_compound_member(config, compound, var_name, index); b32 success = result.success && result.type == ConfigRValueType_Integer; if (success){ *var_out = result.uinteger; } return(success); } static b32 config_compound_uint_member(Config *config, Config_Compound *compound, char *var_name, i32 index, u32* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_compound_member(config, compound, var_name_str, index); b32 success = result.success && result.type == ConfigRValueType_Integer; if (success){ *var_out = result.uinteger; } return(success); } static b32 config_compound_string_member(Config *config, Config_Compound *compound, String var_name, i32 index, String* var_out){ Config_Get_Result result = config_compound_member(config, compound, var_name, index); b32 success = result.success && result.type == ConfigRValueType_String; if (success){ *var_out = result.string; } return(success); } static b32 config_compound_string_member(Config *config, Config_Compound *compound, char *var_name, i32 index, String* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_compound_member(config, compound, var_name_str, index); b32 success = result.success && result.type == ConfigRValueType_String; if (success){ *var_out = result.string; } return(success); } static b32 config_compound_placed_string_member(Config *config, Config_Compound *compound, String var_name, i32 index, String* var_out, char *space, i32 space_size){ Config_Get_Result result = config_compound_member(config, compound, var_name, index); b32 success = result.success && result.type == ConfigRValueType_String; if (success){ *var_out = result.string; } if (success){ String str = *var_out; *var_out = make_string_cap(space, 0, space_size); copy(var_out, str); } return(success); } static b32 config_compound_placed_string_member(Config *config, Config_Compound *compound, char *var_name, i32 index, String* var_out, char *space, i32 space_size){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_compound_member(config, compound, var_name_str, index); b32 success = result.success && result.type == ConfigRValueType_String; if (success){ *var_out = result.string; } if (success){ String str = *var_out; *var_out = make_string_cap(space, 0, space_size); copy(var_out, str); } return(success); } static b32 config_compound_char_member(Config *config, Config_Compound *compound, String var_name, i32 index, char* var_out){ Config_Get_Result result = config_compound_member(config, compound, var_name, index); b32 success = result.success && result.type == ConfigRValueType_Character; if (success){ *var_out = result.character; } return(success); } static b32 config_compound_char_member(Config *config, Config_Compound *compound, char *var_name, i32 index, char* var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_compound_member(config, compound, var_name_str, index); b32 success = result.success && result.type == ConfigRValueType_Character; if (success){ *var_out = result.character; } return(success); } static b32 config_compound_compound_member(Config *config, Config_Compound *compound, String var_name, i32 index, Config_Compound** var_out){ Config_Get_Result result = config_compound_member(config, compound, var_name, index); b32 success = result.success && result.type == ConfigRValueType_Compound; if (success){ *var_out = result.compound; } return(success); } static b32 config_compound_compound_member(Config *config, Config_Compound *compound, char *var_name, i32 index, Config_Compound** var_out){ String var_name_str = make_string_slowly(var_name); Config_Get_Result result = config_compound_member(config, compound, var_name_str, index); b32 success = result.success && result.type == ConfigRValueType_Compound; if (success){ *var_out = result.compound; } return(success); } static Iteration_Step_Result typed_has_array_iteration_step(Config *config, Config_Compound *compound, i32 index){ Config_Iteration_Step_Result result = typed_array_iteration_step(config, compound, ConfigRValueType_NoType, index); return(result.step); } static Iteration_Step_Result typed_bool_array_iteration_step(Config *config, Config_Compound *compound, i32 index, b32* var_out){ Config_Iteration_Step_Result result = typed_array_iteration_step(config, compound, ConfigRValueType_Boolean, index); b32 success = (result.step == Iteration_Good); if (success){ *var_out = result.get.boolean; } return(result.step); } static Iteration_Step_Result typed_int_array_iteration_step(Config *config, Config_Compound *compound, i32 index, i32* var_out){ Config_Iteration_Step_Result result = typed_array_iteration_step(config, compound, ConfigRValueType_Integer, index); b32 success = (result.step == Iteration_Good); if (success){ *var_out = result.get.integer; } return(result.step); } static Iteration_Step_Result typed_uint_array_iteration_step(Config *config, Config_Compound *compound, i32 index, u32* var_out){ Config_Iteration_Step_Result result = typed_array_iteration_step(config, compound, ConfigRValueType_Integer, index); b32 success = (result.step == Iteration_Good); if (success){ *var_out = result.get.uinteger; } return(result.step); } static Iteration_Step_Result typed_string_array_iteration_step(Config *config, Config_Compound *compound, i32 index, String* var_out){ Config_Iteration_Step_Result result = typed_array_iteration_step(config, compound, ConfigRValueType_String, index); b32 success = (result.step == Iteration_Good); if (success){ *var_out = result.get.string; } return(result.step); } static Iteration_Step_Result typed_placed_string_array_iteration_step(Config *config, Config_Compound *compound, i32 index, String* var_out , char *space, i32 space_size){ Config_Iteration_Step_Result result = typed_array_iteration_step(config, compound, ConfigRValueType_String, index); b32 success = (result.step == Iteration_Good); if (success){ *var_out = result.get.string; } if (success){ String str = *var_out; *var_out = make_string_cap(space, 0, space_size); copy(var_out, str); } return(result.step); } static Iteration_Step_Result typed_char_array_iteration_step(Config *config, Config_Compound *compound, i32 index, char* var_out){ Config_Iteration_Step_Result result = typed_array_iteration_step(config, compound, ConfigRValueType_Character, index); b32 success = (result.step == Iteration_Good); if (success){ *var_out = result.get.character; } return(result.step); } static Iteration_Step_Result typed_compound_array_iteration_step(Config *config, Config_Compound *compound, i32 index, Config_Compound** var_out){ Config_Iteration_Step_Result result = typed_array_iteration_step(config, compound, ConfigRValueType_Compound, index); b32 success = (result.step == Iteration_Good); if (success){ *var_out = result.get.compound; } return(result.step); } static i32 typed_bool_array_get_count(Config *config, Config_Compound *compound){ i32 count = typed_array_get_count(config, compound, ConfigRValueType_Boolean); return(count); } static i32 typed_int_array_get_count(Config *config, Config_Compound *compound){ i32 count = typed_array_get_count(config, compound, ConfigRValueType_Integer); return(count); } static i32 typed_float_array_get_count(Config *config, Config_Compound *compound){ i32 count = typed_array_get_count(config, compound, ConfigRValueType_Float); return(count); } static i32 typed_string_array_get_count(Config *config, Config_Compound *compound){ i32 count = typed_array_get_count(config, compound, ConfigRValueType_String); return(count); } static i32 typed_character_array_get_count(Config *config, Config_Compound *compound){ i32 count = typed_array_get_count(config, compound, ConfigRValueType_Character); return(count); } static i32 typed_compound_array_get_count(Config *config, Config_Compound *compound){ i32 count = typed_array_get_count(config, compound, ConfigRValueType_Compound); return(count); } static i32 typed_no_type_array_get_count(Config *config, Config_Compound *compound){ i32 count = typed_array_get_count(config, compound, ConfigRValueType_NoType); return(count); } static Config_Get_Result_List typed_bool_array_reference_list(Partition *arena, Config *config, Config_Compound *compound){ Config_Get_Result_List list = typed_array_reference_list(arena, config, compound, ConfigRValueType_Boolean); return(list); } static Config_Get_Result_List typed_int_array_reference_list(Partition *arena, Config *config, Config_Compound *compound){ Config_Get_Result_List list = typed_array_reference_list(arena, config, compound, ConfigRValueType_Integer); return(list); } static Config_Get_Result_List typed_float_array_reference_list(Partition *arena, Config *config, Config_Compound *compound){ Config_Get_Result_List list = typed_array_reference_list(arena, config, compound, ConfigRValueType_Float); return(list); } static Config_Get_Result_List typed_string_array_reference_list(Partition *arena, Config *config, Config_Compound *compound){ Config_Get_Result_List list = typed_array_reference_list(arena, config, compound, ConfigRValueType_String); return(list); } static Config_Get_Result_List typed_character_array_reference_list(Partition *arena, Config *config, Config_Compound *compound){ Config_Get_Result_List list = typed_array_reference_list(arena, config, compound, ConfigRValueType_Character); return(list); } static Config_Get_Result_List typed_compound_array_reference_list(Partition *arena, Config *config, Config_Compound *compound){ Config_Get_Result_List list = typed_array_reference_list(arena, config, compound, ConfigRValueType_Compound); return(list); } static Config_Get_Result_List typed_no_type_array_reference_list(Partition *arena, Config *config, Config_Compound *compound){ Config_Get_Result_List list = typed_array_reference_list(arena, config, compound, ConfigRValueType_NoType); return(list); } //////////////////////////////// static Config_Iteration_Step_Result typed_array_iteration_step(Config *parsed, Config_Compound *compound, Config_RValue_Type type, i32 index){ Config_Iteration_Step_Result result = {}; result.step = Iteration_Quit; Config_Get_Result get_result = config_compound_member(parsed, compound, make_lit_string("~"), index); if (get_result.success){ if (get_result.type == type || type == ConfigRValueType_NoType){ result.step = Iteration_Good; result.get = get_result; } else{ result.step = Iteration_Skip; } } return(result); } static i32 typed_array_get_count(Config *parsed, Config_Compound *compound, Config_RValue_Type type){ i32 count = 0; for (i32 i = 0;; ++i){ Config_Iteration_Step_Result result = typed_array_iteration_step(parsed, compound, type, i); if (result.step == Iteration_Skip){ continue; } else if (result.step == Iteration_Quit){ break; } count += 1; } return(count); } static Config_Get_Result_List typed_array_reference_list(Partition *arena, Config *parsed, Config_Compound *compound, Config_RValue_Type type){ Config_Get_Result_List list = {}; for (i32 i = 0;; ++i){ Config_Iteration_Step_Result result = typed_array_iteration_step(parsed, compound, type, i); if (result.step == Iteration_Skip){ continue; } else if (result.step == Iteration_Quit){ break; } Config_Get_Result_Node *node = push_array(arena, Config_Get_Result_Node, 1); node->result = result.get; zdll_push_back(list.first, list.last, node); list.count += 1; } return(list); } //////////////////////////////// static void change_mapping(Application_Links *app, String mapping){ b32 did_remap = false; for (i32 i = 0; i < named_map_count; ++i){ if (match(mapping, named_maps[i].name)){ did_remap = true; exec_command(app, named_maps[i].remap_command); break; } } if (!did_remap){ print_message(app, literal("Leaving bindings unaltered.\n")); } } static void change_mode(Application_Links *app, String mode){ fcoder_mode = FCoderMode_Original; if (match(mode, "4coder")){ fcoder_mode = FCoderMode_Original; } else if (match(mode, "notepad-like")){ begin_notepad_mode(app); } else{ print_message(app, literal("Unknown mode.\n")); } } //////////////////////////////// static Cpp_Token_Array text_data_to_token_array(Partition *arena, String data){ b32 success = false; i32 max_count = (1 << 20)/sizeof(Cpp_Token); Temp_Memory restore_point = begin_temp_memory(arena); Cpp_Token_Array array = {}; array.tokens = push_array(arena, Cpp_Token, max_count); if (array.tokens != 0){ array.max_count = max_count; Cpp_Keyword_Table kw_table = {}; Cpp_Keyword_Table pp_table = {}; if (lexer_keywords_default_init(arena, &kw_table, &pp_table)){ Cpp_Lex_Data S = cpp_lex_data_init(false, kw_table, pp_table); Cpp_Lex_Result result = cpp_lex_step(&S, data.str, data.size + 1, HAS_NULL_TERM, &array, NO_OUT_LIMIT); if (result == LexResult_Finished){ success = true; } } } if (!success){ memset(&array, 0, sizeof(array)); end_temp_memory(restore_point); } return(array); } static Config* text_data_to_parsed_data(Partition *arena, String file_name, String data){ Config *parsed = 0; Temp_Memory restore_point = begin_temp_memory(arena); Cpp_Token_Array array = text_data_to_token_array(arena, data); if (array.tokens != 0){ parsed = text_data_and_token_array_to_parse_data(arena, file_name, data, array); if (parsed == 0){ end_temp_memory(restore_point); } } return(parsed); } //////////////////////////////// static void config_init_default(Config_Data *config){ config->user_name = make_fixed_width_string(config->user_name_space); copy(&config->user_name, ""); memset(&config->code_exts, 0, sizeof(config->code_exts)); config->current_mapping = make_fixed_width_string(config->current_mapping_space); copy(&config->current_mapping, ""); config->mode = make_fixed_width_string(config->mode_space); copy(&config->mode, "4coder"); config->use_scroll_bars = false; config->use_file_bars = true; config->use_line_highlight = true; config->use_scope_highlight = true; config->use_paren_helper = true; config->use_comment_keyword = true; config->enable_virtual_whitespace = true; config->enable_code_wrapping = true; config->automatically_adjust_wrapping = true; config->automatically_indent_text_on_save = true; config->automatically_save_changes_on_build = true; config->automatically_load_project = false; config->indent_with_tabs = false; config->indent_width = 4; config->default_wrap_width = 672; config->default_min_base_width = 550; config->default_theme_name = make_fixed_width_string(config->default_theme_name_space); copy(&config->default_theme_name, "4coder"); config->highlight_line_at_cursor = true; config->default_font_name = make_fixed_width_string(config->default_font_name_space); copy(&config->default_font_name, ""); config->default_font_size = 16; config->default_font_hinting = false; config->default_compiler_bat = make_fixed_width_string(config->default_compiler_bat_space); copy(&config->default_compiler_bat, "cl"); config->default_flags_bat = make_fixed_width_string(config->default_flags_bat_space); copy(&config->default_flags_bat, ""); config->default_compiler_sh = make_fixed_width_string(config->default_compiler_sh_space); copy(&config->default_compiler_sh, "g++"); config->default_flags_sh = make_fixed_width_string(config->default_flags_sh_space); copy(&config->default_flags_sh, ""); config->lalt_lctrl_is_altgr = false; } static Config* config_parse__data(Partition *arena, String file_name, String data, Config_Data *config){ config_init_default(config); b32 success = false; Config *parsed = text_data_to_parsed_data(arena, file_name, data); if (parsed != 0){ success = true; config_fixed_string_var(parsed, "user_name", 0, &config->user_name, config->user_name_space); String str; if (config_string_var(parsed, "treat_as_code", 0, &str)){ parse_extension_line_to_extension_list(str, &config->code_exts); } config_fixed_string_var(parsed, "mapping", 0, &config->current_mapping, config->current_mapping_space); config_fixed_string_var(parsed, "mode", 0, &config->mode, config->mode_space); config_bool_var(parsed, "use_scroll_bars", 0, &config->use_scroll_bars); config_bool_var(parsed, "use_file_bars", 0, &config->use_file_bars); config_bool_var(parsed, "use_line_highlight", 0, &config->use_line_highlight); config_bool_var(parsed, "use_scope_highlight", 0, &config->use_scope_highlight); config_bool_var(parsed, "use_paren_helper", 0, &config->use_paren_helper); config_bool_var(parsed, "use_comment_keyword", 0, &config->use_comment_keyword); config_bool_var(parsed, "enable_virtual_whitespace", 0, &config->enable_virtual_whitespace); config_bool_var(parsed, "enable_code_wrapping", 0, &config->enable_code_wrapping); config_bool_var(parsed, "automatically_adjust_wrapping", 0, &config->automatically_adjust_wrapping); config_bool_var(parsed, "automatically_indent_text_on_save", 0, &config->automatically_indent_text_on_save); config_bool_var(parsed, "automatically_save_changes_on_build", 0, &config->automatically_save_changes_on_build); config_bool_var(parsed, "automatically_load_project", 0, &config->automatically_load_project); config_bool_var(parsed, "indent_with_tabs", 0, &config->indent_with_tabs); config_int_var(parsed, "indent_width", 0, &config->indent_width); config_int_var(parsed, "default_wrap_width", 0, &config->default_wrap_width); config_int_var(parsed, "default_min_base_width", 0, &config->default_min_base_width); config_fixed_string_var(parsed, "default_theme_name", 0, &config->default_theme_name, config->default_theme_name_space); config_bool_var(parsed, "highlight_line_at_cursor", 0, &config->highlight_line_at_cursor); config_fixed_string_var(parsed, "default_font_name", 0, &config->default_font_name, config->default_font_name_space); config_int_var(parsed, "default_font_size", 0, &config->default_font_size); config_bool_var(parsed, "default_font_hinting", 0, &config->default_font_hinting); config_fixed_string_var(parsed, "default_compiler_bat", 0, &config->default_compiler_bat, config->default_compiler_bat_space); config_fixed_string_var(parsed, "default_flags_bat", 0, &config->default_flags_bat, config->default_flags_bat_space); config_fixed_string_var(parsed, "default_compiler_sh", 0, &config->default_compiler_sh, config->default_compiler_sh_space); config_fixed_string_var(parsed, "default_flags_sh", 0, &config->default_flags_sh, config->default_flags_sh_space); config_bool_var(parsed, "lalt_lctrl_is_altgr", 0, &config->lalt_lctrl_is_altgr); } if (!success){ config_init_default(config); } return(parsed); } static Config* config_parse__file_handle(Partition *arena, String file_name, FILE *file, Config_Data *config){ Config *parsed = 0; String data = dump_file_handle(arena, file); if (data.str != 0){ parsed = config_parse__data(arena, file_name, data, config); } else{ config_init_default(config); } return(parsed); } static Config* config_parse__file_name(Application_Links *app, Partition *arena, char *file_name, Config_Data *config){ Config *parsed = 0; b32 success = false; FILE *file = open_file_try_current_path_then_binary_path(app, file_name); if (file != 0){ String data = dump_file_handle(arena, file); fclose(file); if (data.str != 0){ parsed = config_parse__data(arena, make_string_slowly(file_name), data, config); success = true; } } if (!success){ config_init_default(config); } return(parsed); } #if 0 static void init_theme_zero(Theme *theme){ for (i32 i = 0; i < Stag_COUNT; ++i){ theme->colors[i] = 0; } } static Config* theme_parse__data(Partition *arena, String file_name, String data, Theme_Data *theme){ theme->name = make_fixed_width_string(theme->space); copy(&theme->name, "unnamed"); init_theme_zero(&theme->theme); Config *parsed = text_data_to_parsed_data(arena, file_name, data); if (parsed != 0){ config_fixed_string_var(parsed, "name", 0, &theme->name, theme->space); for (i32 i = 0; i < Stag_COUNT; ++i){ char *name = style_tag_names[i]; u32 color = 0; if (!config_uint_var(parsed, name, 0, &color)){ color = 0xFFFF00FF; } theme->theme.colors[i] = color; } } return(parsed); } static Config* theme_parse__file_handle(Partition *arena, String file_name, FILE *file, Theme_Data *theme){ String data = dump_file_handle(arena, file); Config *parsed = 0; if (data.str != 0){ parsed = theme_parse__data(arena, file_name, data, theme); } return(parsed); } static Config* theme_parse__file_name(Application_Links *app, Partition *arena, char *file_name, Theme_Data *theme){ Config *parsed = 0; FILE *file = open_file_try_current_path_then_binary_path(app, file_name); if (file != 0){ String data = dump_file_handle(arena, file); fclose(file); parsed = theme_parse__data(arena, make_string_slowly(file_name), data, theme); } if (parsed == 0){ char space[256]; String str = make_fixed_width_string(space); append(&str, "Did not find "); append(&str, file_name); append(&str, ", color scheme not loaded"); print_message(app, str.str, str.size); } return(parsed); } #endif //////////////////////////////// static void config_feedback_bool(String *space, char *name, b32 val){ append(space, name); append(space, " = "); append(space, (char*)(val?"true":"false")); append(space, ";\n"); } static void config_feedback_string(String *space, char *name, String val){ if (val.size > 0){ append(space, name); append(space, " = \""); append(space, val); append(space, "\";\n"); } } static void config_feedback_string(String *space, char *name, char *val){ config_feedback_string(space, name, make_string_slowly(val)); } static void config_feedback_extension_list(String *space, char *name, Extension_List *list){ if (list->count > 0){ append(space, name); append(space, " = \""); for (i32 i = 0; i < list->count; ++i){ append(space, "."); append(space, list->exts[i]); } append(space, "\";\n"); } } static void config_feedback_int(String *space, char *name, i32 val){ append(space, name); append(space, " = "); append_int_to_str(space, val); append(space, ";\n"); } //////////////////////////////// static void load_config_and_apply(Application_Links *app, Partition *scratch, Config_Data *config, i32 override_font_size, b32 override_hinting){ Temp_Memory temp = begin_temp_memory(scratch); Config *parsed = config_parse__file_name(app, scratch, "config.4coder", config); if (parsed != 0){ // Top print_message(app, literal("Loaded config file:\n")); // Errors String error_text = config_stringize_errors(scratch, parsed); if (error_text.str != 0){ print_message(app, error_text.str, error_text.size); } // Values Temp_Memory temp2 = begin_temp_memory(scratch); String space = string_push(scratch, part_remaining(scratch)); { config_feedback_string(&space, "user_name", config->user_name); config_feedback_extension_list(&space, "treat_as_code", &config->code_exts); config_feedback_string(&space, "current_mapping", config->current_mapping); config_feedback_string(&space, "mode", config->mode); config_feedback_bool(&space, "use_scroll_bars", config->use_scroll_bars); config_feedback_bool(&space, "use_file_bars", config->use_file_bars); config_feedback_bool(&space, "use_line_highlight", config->use_line_highlight); config_feedback_bool(&space, "use_scope_highlight", config->use_scope_highlight); config_feedback_bool(&space, "use_paren_helper", config->use_paren_helper); config_feedback_bool(&space, "use_comment_keyword", config->use_comment_keyword); config_feedback_bool(&space, "enable_virtual_whitespace", config->enable_virtual_whitespace); config_feedback_bool(&space, "enable_code_wrapping", config->enable_code_wrapping); config_feedback_bool(&space, "automatically_indent_text_on_save", config->automatically_indent_text_on_save); config_feedback_bool(&space, "automatically_save_changes_on_build", config->automatically_save_changes_on_build); config_feedback_bool(&space, "automatically_adjust_wrapping", config->automatically_adjust_wrapping); config_feedback_bool(&space, "automatically_load_project", config->automatically_load_project); config_feedback_bool(&space, "indent_with_tabs", config->indent_with_tabs); config_feedback_int(&space, "indent_width", config->indent_width); config_feedback_int(&space, "default_wrap_width", config->default_wrap_width); config_feedback_int(&space, "default_min_base_width", config->default_min_base_width); config_feedback_string(&space, "default_theme_name", config->default_theme_name); config_feedback_bool(&space, "highlight_line_at_cursor", config->highlight_line_at_cursor); config_feedback_string(&space, "default_font_name", config->default_font_name); config_feedback_int(&space, "default_font_size", config->default_font_size); config_feedback_bool(&space, "default_font_hinting", config->default_font_hinting); config_feedback_string(&space, "default_compiler_bat", config->default_compiler_bat); config_feedback_string(&space, "default_flags_bat", config->default_flags_bat); config_feedback_string(&space, "default_compiler_sh", config->default_compiler_sh); config_feedback_string(&space, "default_flags_sh", config->default_flags_sh); config_feedback_bool(&space, "lalt_lctrl_is_altgr", config->lalt_lctrl_is_altgr); } append(&space, "\n"); print_message(app, space.str, space.size); end_temp_memory(temp2); // Apply config change_mapping(app, config->current_mapping); change_mode(app, config->mode); highlight_line_at_cursor = config->use_line_highlight; do_matching_enclosure_highlight = config->use_scope_highlight; do_matching_paren_highlight = config->use_paren_helper; do_colored_comment_keywords = config->use_comment_keyword; adjust_all_buffer_wrap_widths(app, config->default_wrap_width, config->default_min_base_width); global_set_setting(app, GlobalSetting_LAltLCtrlIsAltGr, config->lalt_lctrl_is_altgr); //change_theme(app, config->default_theme_name.str, config->default_theme_name.size); highlight_line_at_cursor = config->highlight_line_at_cursor; Face_Description description = {}; i32 len = config->default_font_name.size; char *name_ptr = config->default_font_name.str; if (len > sizeof(description.font.name) - 1){ len = sizeof(description.font.name) - 1; } memcpy(description.font.name, name_ptr, len); description.font.name[len] = 0; if (override_font_size != 0){ description.pt_size = override_font_size; } else{ description.pt_size = config->default_font_size; } description.hinting = config->default_font_hinting || override_hinting; change_global_face_by_description(app, description, true); } end_temp_memory(temp); } #if 0 static void load_theme_file_into_live_set(Application_Links *app, Partition *scratch, char *file_name){ Temp_Memory temp = begin_temp_memory(scratch); Theme_Data theme = {}; Config *config = theme_parse__file_name(app, scratch, file_name, &theme); String error_text = config_stringize_errors(scratch, config); print_message(app, error_text.str, error_text.size); end_temp_memory(temp); create_theme(app, &theme.theme, theme.name.str, theme.name.size); } static void load_folder_of_themes_into_live_set(Application_Links *app, Partition *scratch, char *folder_name){ char path_space[512]; String path = make_fixed_width_string(path_space); path.size = get_4ed_path(app, path_space, sizeof(path_space)); append(&path, folder_name); if (path.size < path.memory_size){ File_List list = get_file_list(app, path.str, path.size); for (u32 i = 0; i < list.count; ++i){ File_Info *info = &list.infos[i]; if (info->folder){ continue; } String info_file_name = make_string(info->filename, info->filename_len); char file_name_space[512]; String file_name = make_fixed_width_string(file_name_space); copy(&file_name, path); append(&file_name, "/"); append(&file_name, info_file_name); if (terminate_with_null(&file_name)){ load_theme_file_into_live_set(app, scratch, file_name.str); } } free_file_list(app, list); } } #endif // BOTTOM