Load fonts from new search list

This commit is contained in:
Allen Webster 2021-01-16 16:14:12 -08:00
parent f1b0bd0522
commit 655e5892f6
14 changed files with 55 additions and 35 deletions

View File

@ -249,10 +249,17 @@ App_Init_Sig(app_init){
// NOTE(allen): style setup // NOTE(allen): style setup
{ {
Scratch_Block scratch(tctx, arena); Scratch_Block scratch(tctx, arena);
String8 binary_path = system_get_path(scratch, SystemPath_Binary);
String8 full_path = push_u8_stringf(arena, "%.*sfonts/liberation-mono.ttf", string_expand(binary_path));
Face_Description description = {}; Face_Description description = {};
description.font.file_name = get_file_path_in_fonts_folder(scratch, string_u8_litexpr("liberation-mono.ttf")); description.font.file_name = full_path;
description.parameters.pt_size = 12; description.parameters.pt_size = 12;
Face *new_face = font_set_new_face(&models->font_set, &description); Face *new_face = font_set_new_face(&models->font_set, &description);
if (new_face == 0){
system_error_box("Could not load the required fallback font");
}
models->global_face_id = new_face->id; models->global_face_id = new_face->id;
} }

View File

@ -15,6 +15,11 @@ function API_Definition*
define_api(Arena *arena){ define_api(Arena *arena){
API_Definition *api = begin_api(arena, "system"); API_Definition *api = begin_api(arena, "system");
{
API_Call *call = api_call(arena, api, "error_box", "void");
api_param(arena, call, "char*", "msg");
}
{ {
API_Call *call = api_call(arena, api, "get_path", "String_Const_u8"); API_Call *call = api_call(arena, api, "get_path", "String_Const_u8");
api_param(arena, call, "Arena*", "arena"); api_param(arena, call, "Arena*", "arena");

View File

@ -153,7 +153,7 @@ set_fancy_compilation_buffer_font(Application_Links *app){
Buffer_ID buffer = get_comp_buffer(app); Buffer_ID buffer = get_comp_buffer(app);
Font_Load_Location font = {}; Font_Load_Location font = {};
Scratch_Block scratch(app); Scratch_Block scratch(app);
font.file_name = get_file_path_in_fonts_folder(scratch, string_u8_litexpr("Inconsolata-Regular.ttf")); font.file_name = def_search_normal_full_path(scratch, str8_lit("fonts/Inconsolata-Regular.ttf"));
set_buffer_face_by_font_load_location(app, buffer, &font); set_buffer_face_by_font_load_location(app, buffer, &font);
} }

View File

@ -8,7 +8,7 @@
// NOTE(allen): Config Search List // NOTE(allen): Config Search List
function void function void
def_search_normal_load_list(Arena *arena, List_String_Const_u8 *list){ def_search_normal_load_list(Arena *arena, String8List *list){
Variable_Handle prj_var = vars_read_key(vars_get_root(), vars_save_string_lit("prj_config")); Variable_Handle prj_var = vars_read_key(vars_get_root(), vars_save_string_lit("prj_config"));
String_Const_u8 prj_dir = prj_path_from_project(arena, prj_var); String_Const_u8 prj_dir = prj_path_from_project(arena, prj_var);
if (prj_dir.size > 0){ if (prj_dir.size > 0){
@ -18,10 +18,18 @@ def_search_normal_load_list(Arena *arena, List_String_Const_u8 *list){
def_search_list_add_system_path(arena, list, SystemPath_Binary); def_search_list_add_system_path(arena, list, SystemPath_Binary);
} }
function String8
def_search_normal_full_path(Arena *arena, String8 relative){
String8List list = {};
def_search_normal_load_list(arena, &list);
String8 result = def_search_get_full_path(arena, &list, relative);
return(result);
}
function FILE* function FILE*
def_search_normal_fopen(Arena *arena, char *file_name, char *opt){ def_search_normal_fopen(Arena *arena, char *file_name, char *opt){
Temp_Memory_Block block(arena); Temp_Memory_Block block(arena);
List_String_Const_u8 list = {}; String8List list = {};
def_search_normal_load_list(arena, &list); def_search_normal_load_list(arena, &list);
FILE *file = def_search_fopen(arena, &list, file_name, opt); FILE *file = def_search_fopen(arena, &list, file_name, opt);
return(file); return(file);
@ -1539,7 +1547,8 @@ load_config_and_apply(Application_Links *app, Arena *out_arena, i32 override_fon
description.font.file_name = default_font_name; description.font.file_name = default_font_name;
if (!modify_global_face_by_description(app, description)){ if (!modify_global_face_by_description(app, description)){
description.font.file_name = get_file_path_in_fonts_folder(scratch, default_font_name); String8 name_in_fonts_folder = push_u8_stringf(scratch, "fonts/%.*s", string_expand(default_font_name));
description.font.file_name = def_search_normal_full_path(scratch, name_in_fonts_folder);
modify_global_face_by_description(app, description); modify_global_face_by_description(app, description);
} }

View File

@ -175,8 +175,9 @@ struct Config_Get_Result_List{
//////////////////////////////// ////////////////////////////////
// NOTE(allen): Config Search List // NOTE(allen): Config Search List
function void def_search_normal_load_list(Arena *arena, List_String_Const_u8 *list); function void def_search_normal_load_list(Arena *arena, String8List *list);
function String8 def_search_normal_full_path(Arena *arena, String8 relative);
function FILE *def_search_normal_fopen(Arena *arena, char *file_name, char *opt); function FILE *def_search_normal_fopen(Arena *arena, char *file_name, char *opt);
//////////////////////////////// ////////////////////////////////

View File

@ -4,14 +4,6 @@
// TOP // 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){ Mutex_Lock::Mutex_Lock(System_Mutex m){
system_mutex_acquire(m); system_mutex_acquire(m);
this->mutex = m; this->mutex = m;

View File

@ -326,7 +326,7 @@ static Command_Metadata fcoder_metacmd_table[252] = {
{ 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(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(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_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(exit_4coder, 0), false, "exit_4coder", 11, "Attempts to close 4coder.", 25, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 846 }, { PROC_LINKS(exit_4coder, 0), false, "exit_4coder", 11, "Attempts to close 4coder.", 25, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 846 },
{ PROC_LINKS(go_to_user_directory, 0), false, "go_to_user_directory", 20, "Go to the 4coder user directory", 31, "W:\\4ed\\code\\custom\\4coder_config.cpp", 36, 1639 }, { PROC_LINKS(go_to_user_directory, 0), false, "go_to_user_directory", 20, "Go to the 4coder user directory", 31, "W:\\4ed\\code\\custom\\4coder_config.cpp", 36, 1648 },
{ 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, 2247 }, { 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, 2247 },
{ 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, 2255 }, { 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, 2255 },
{ 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, 525 }, { 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, 525 },
@ -375,7 +375,7 @@ static Command_Metadata fcoder_metacmd_table[252] = {
{ 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, 174 }, { 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, 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, 186 }, { 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, 186 },
{ 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, 823 }, { 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, 823 },
{ PROC_LINKS(load_theme_current_buffer, 0), false, "load_theme_current_buffer", 25, "Parse the current buffer as a theme file and add the theme to the theme list. If the buffer has a .4coder postfix in it's name, it is removed when the name is saved.", 165, "W:\\4ed\\code\\custom\\4coder_config.cpp", 36, 1595 }, { PROC_LINKS(load_theme_current_buffer, 0), false, "load_theme_current_buffer", 25, "Parse the current buffer as a theme file and add the theme to the theme list. If the buffer has a .4coder postfix in it's name, it is removed when the name is saved.", 165, "W:\\4ed\\code\\custom\\4coder_config.cpp", 36, 1604 },
{ PROC_LINKS(load_themes_default_folder, 0), false, "load_themes_default_folder", 26, "Loads all the theme files in the default theme folder.", 54, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 535 }, { PROC_LINKS(load_themes_default_folder, 0), false, "load_themes_default_folder", 26, "Loads all the theme files in the default theme folder.", 54, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 535 },
{ PROC_LINKS(load_themes_hot_directory, 0), false, "load_themes_hot_directory", 25, "Loads all the theme files in the current hot directory.", 55, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 547 }, { PROC_LINKS(load_themes_hot_directory, 0), false, "load_themes_hot_directory", 25, "Loads all the theme files in the current hot directory.", 55, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 547 },
{ 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, 1495 }, { 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, 1495 },

View File

@ -1,5 +1,6 @@
function void function void
system_api_fill_vtable(API_VTable_system *vtable){ system_api_fill_vtable(API_VTable_system *vtable){
vtable->error_box = system_error_box;
vtable->get_path = system_get_path; vtable->get_path = system_get_path;
vtable->get_canonical = system_get_canonical; vtable->get_canonical = system_get_canonical;
vtable->get_file_list = system_get_file_list; vtable->get_file_list = system_get_file_list;
@ -60,6 +61,7 @@ vtable->set_destination_mixer = system_set_destination_mixer;
#if defined(DYNAMIC_LINK_API) #if defined(DYNAMIC_LINK_API)
function void function void
system_api_read_vtable(API_VTable_system *vtable){ system_api_read_vtable(API_VTable_system *vtable){
system_error_box = vtable->error_box;
system_get_path = vtable->get_path; system_get_path = vtable->get_path;
system_get_canonical = vtable->get_canonical; system_get_canonical = vtable->get_canonical;
system_get_file_list = vtable->get_file_list; system_get_file_list = vtable->get_file_list;

View File

@ -1,3 +1,4 @@
#define system_error_box_sig() void system_error_box(char* msg)
#define system_get_path_sig() String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code) #define system_get_path_sig() String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code)
#define system_get_canonical_sig() String_Const_u8 system_get_canonical(Arena* arena, String_Const_u8 name) #define system_get_canonical_sig() String_Const_u8 system_get_canonical(Arena* arena, String_Const_u8 name)
#define system_get_file_list_sig() File_List system_get_file_list(Arena* arena, String_Const_u8 directory) #define system_get_file_list_sig() File_List system_get_file_list(Arena* arena, String_Const_u8 directory)
@ -54,6 +55,7 @@
#define system_set_key_mode_sig() void system_set_key_mode(Key_Mode mode) #define system_set_key_mode_sig() void system_set_key_mode(Key_Mode mode)
#define system_set_source_mixer_sig() void system_set_source_mixer(void* ctx, Audio_Mix_Sources_Function* mix_func) #define system_set_source_mixer_sig() void system_set_source_mixer(void* ctx, Audio_Mix_Sources_Function* mix_func)
#define system_set_destination_mixer_sig() void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func) #define system_set_destination_mixer_sig() void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func)
typedef void system_error_box_type(char* msg);
typedef String_Const_u8 system_get_path_type(Arena* arena, System_Path_Code path_code); typedef String_Const_u8 system_get_path_type(Arena* arena, System_Path_Code path_code);
typedef String_Const_u8 system_get_canonical_type(Arena* arena, String_Const_u8 name); typedef String_Const_u8 system_get_canonical_type(Arena* arena, String_Const_u8 name);
typedef File_List system_get_file_list_type(Arena* arena, String_Const_u8 directory); typedef File_List system_get_file_list_type(Arena* arena, String_Const_u8 directory);
@ -111,6 +113,7 @@ typedef void system_set_key_mode_type(Key_Mode mode);
typedef void system_set_source_mixer_type(void* ctx, Audio_Mix_Sources_Function* mix_func); typedef void system_set_source_mixer_type(void* ctx, Audio_Mix_Sources_Function* mix_func);
typedef void system_set_destination_mixer_type(Audio_Mix_Destination_Function* mix_func); typedef void system_set_destination_mixer_type(Audio_Mix_Destination_Function* mix_func);
struct API_VTable_system{ struct API_VTable_system{
system_error_box_type *error_box;
system_get_path_type *get_path; system_get_path_type *get_path;
system_get_canonical_type *get_canonical; system_get_canonical_type *get_canonical;
system_get_file_list_type *get_file_list; system_get_file_list_type *get_file_list;
@ -169,6 +172,7 @@ system_set_source_mixer_type *set_source_mixer;
system_set_destination_mixer_type *set_destination_mixer; system_set_destination_mixer_type *set_destination_mixer;
}; };
#if defined(STATIC_LINK_API) #if defined(STATIC_LINK_API)
internal void system_error_box(char* msg);
internal String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code); internal String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code);
internal String_Const_u8 system_get_canonical(Arena* arena, String_Const_u8 name); internal String_Const_u8 system_get_canonical(Arena* arena, String_Const_u8 name);
internal File_List system_get_file_list(Arena* arena, String_Const_u8 directory); internal File_List system_get_file_list(Arena* arena, String_Const_u8 directory);
@ -227,6 +231,7 @@ internal void system_set_source_mixer(void* ctx, Audio_Mix_Sources_Function* mix
internal void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func); internal void system_set_destination_mixer(Audio_Mix_Destination_Function* mix_func);
#undef STATIC_LINK_API #undef STATIC_LINK_API
#elif defined(DYNAMIC_LINK_API) #elif defined(DYNAMIC_LINK_API)
global system_error_box_type *system_error_box = 0;
global system_get_path_type *system_get_path = 0; global system_get_path_type *system_get_path = 0;
global system_get_canonical_type *system_get_canonical = 0; global system_get_canonical_type *system_get_canonical = 0;
global system_get_file_list_type *system_get_file_list = 0; global system_get_file_list_type *system_get_file_list = 0;

View File

@ -2,6 +2,10 @@ function API_Definition*
system_api_construct(Arena *arena){ system_api_construct(Arena *arena){
API_Definition *result = begin_api(arena, "system"); API_Definition *result = begin_api(arena, "system");
{ {
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("error_box"), string_u8_litexpr("void"), string_u8_litexpr(""));
api_param(arena, call, "char*", "msg");
}
{
API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_path"), string_u8_litexpr("String_Const_u8"), string_u8_litexpr("")); API_Call *call = api_call_with_location(arena, result, string_u8_litexpr("get_path"), string_u8_litexpr("String_Const_u8"), string_u8_litexpr(""));
api_param(arena, call, "Arena*", "arena"); api_param(arena, call, "Arena*", "arena");
api_param(arena, call, "System_Path_Code", "path_code"); api_param(arena, call, "System_Path_Code", "path_code");

View File

@ -1,3 +1,4 @@
api(system) function void error_box(char* msg);
api(system) function String_Const_u8 get_path(Arena* arena, System_Path_Code path_code); api(system) function String_Const_u8 get_path(Arena* arena, System_Path_Code path_code);
api(system) function String_Const_u8 get_canonical(Arena* arena, String_Const_u8 name); api(system) function String_Const_u8 get_canonical(Arena* arena, String_Const_u8 name);
api(system) function File_List get_file_list(Arena* arena, String_Const_u8 directory); api(system) function File_List get_file_list(Arena* arena, String_Const_u8 directory);

View File

@ -12,7 +12,7 @@
// HACK(allen): // NOTE(inso): this was a quick hack, might need some cleanup. // HACK(allen): // NOTE(inso): this was a quick hack, might need some cleanup.
internal void internal void
system_error_box(char *msg, b32 shutdown = true){ system_error_box(char *msg){
fprintf(stderr, "Fatal Error: %s\n", msg); fprintf(stderr, "Fatal Error: %s\n", msg);
//LOGF("Fatal Error: %s\n", msg); //LOGF("Fatal Error: %s\n", msg);
@ -181,9 +181,7 @@ XDrawString(dpy, w, gc1, (x) , (y) , (str), (len))
} }
#undef DRAW_STR #undef DRAW_STR
if (shutdown){
exit(1); exit(1);
}
} }
// BOTTOM // BOTTOM

View File

@ -10,12 +10,10 @@
// TOP // TOP
internal void internal void
system_error_box(char *msg, b32 shutdown = true){ system_error_box(char *msg){
//LOGF("error box: %s\n", msg); //LOGF("error box: %s\n", msg);
osx_error_dialogue(msg); osx_error_dialogue(msg);
if (shutdown){
exit(1); exit(1);
}
} }
// BOTTOM // BOTTOM

View File

@ -212,11 +212,9 @@ global Render_Target target;
//////////////////////////////// ////////////////////////////////
internal void internal void
system_error_box(Arena *scratch, char *msg, b32 shutdown = true){ system_error_box(char *msg){
MessageBox_utf8(scratch, 0, (u8*)msg, (u8*)"Error", 0); MessageBoxA(0, msg, "Error", MB_OK);
if (shutdown){ ExitProcess(1);
exit(1);
}
} }
//////////////////////////////// ////////////////////////////////
@ -229,7 +227,7 @@ win32_output_error_string(Arena *scratch, b32 use_error_box){
char *str_ptr = (char*)&str; char *str_ptr = (char*)&str;
if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, error, 0, str_ptr, 0, 0)){ if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, error, 0, str_ptr, 0, 0)){
if (use_error_box){ if (use_error_box){
system_error_box(scratch, str, false); system_error_box(str);
} }
} }
} }
@ -1704,12 +1702,12 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
} }
else{ else{
char msg[] = "Failed to get application code from '4ed_app.dll'."; char msg[] = "Failed to get application code from '4ed_app.dll'.";
system_error_box(scratch, msg); system_error_box(msg);
} }
} }
else{ else{
char msg[] = "Could not load '4ed_app.dll'. This file should be in the same directory as the main '4ed' executable."; char msg[] = "Could not load '4ed_app.dll'. This file should be in the same directory as the main '4ed' executable.";
system_error_box(scratch, msg); system_error_box(msg);
} }
} }
@ -1782,15 +1780,15 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
} }
if (!has_library){ if (!has_library){
system_error_box(scratch, custom_not_found_msg); system_error_box(custom_not_found_msg);
} }
custom.get_version = (_Get_Version_Type*)system_get_proc(custom_library, "get_version"); custom.get_version = (_Get_Version_Type*)system_get_proc(custom_library, "get_version");
if (custom.get_version == 0 || custom.get_version(MAJOR, MINOR, PATCH) == 0){ if (custom.get_version == 0 || custom.get_version(MAJOR, MINOR, PATCH) == 0){
system_error_box(scratch, custom_fail_version_msg); system_error_box(custom_fail_version_msg);
} }
custom.init_apis = (_Init_APIs_Type*)system_get_proc(custom_library, "init_apis"); custom.init_apis = (_Init_APIs_Type*)system_get_proc(custom_library, "init_apis");
if (custom.init_apis == 0){ if (custom.init_apis == 0){
system_error_box(scratch, custom_fail_init_apis); system_error_box(custom_fail_init_apis);
} }
} }