From 69349fd74996782c11fea2643148716bdc9bced5 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Tue, 21 Jun 2016 10:00:07 -0400 Subject: [PATCH] cripsy new FT fonts in windows --- 4coder_default_bindings.cpp | 23 ++-- 4coder_default_include.cpp | 75 ++++++------- 4ed_api_implementation.cpp | 7 +- README.txt | 2 +- SUPERREADME.txt | 2 +- build_all.bat | 5 +- power/4coder_experiments.cpp | 2 +- win32_4ed.cpp | 16 ++- win32_ft_font.cpp | 198 ++++++++++++++--------------------- 9 files changed, 137 insertions(+), 193 deletions(-) diff --git a/4coder_default_bindings.cpp b/4coder_default_bindings.cpp index 517d1bd4..c04e2bb2 100644 --- a/4coder_default_bindings.cpp +++ b/4coder_default_bindings.cpp @@ -8,10 +8,7 @@ // 2^24 of them so don't be wasteful! enum My_Maps{ my_code_map, - // for testing - my_html_map, - my_empty_map1, - my_empty_map2, + my_maps_count }; @@ -115,7 +112,9 @@ CUSTOM_COMMAND_SIG(build_at_launch_location){ HOOK_SIG(my_start){ exec_command(app, cmdid_open_panel_vsplit); + exec_command(app, cmdid_hide_scrollbar); exec_command(app, cmdid_change_active_panel); + exec_command(app, cmdid_hide_scrollbar); app->change_theme(app, literal("4coder")); app->change_font(app, literal("liberation sans")); @@ -146,10 +145,10 @@ HOOK_SIG(my_file_settings){ unsigned int access = AccessProtected|AccessHidden; Buffer_Summary buffer = app->get_parameter_buffer(app, 0, access); assert(buffer.exists); - + int treat_as_code = 0; int wrap_lines = 1; - + if (buffer.file_name && buffer.size < (16 << 20)){ String ext = file_extension(make_string(buffer.file_name, buffer.file_name_len)); if (match(ext, make_lit_string("cpp"))) treat_as_code = 1; @@ -157,14 +156,14 @@ HOOK_SIG(my_file_settings){ else if (match(ext, make_lit_string("c"))) treat_as_code = 1; else if (match(ext, make_lit_string("hpp"))) treat_as_code = 1; } - + if (treat_as_code){ wrap_lines = 0; } if (buffer.file_name[0] == '*'){ wrap_lines = 0; } - + // NOTE(allen|a4.0.5): Unlike previous versions the command cmdid_set_settings // no longer automatically effects the active buffer. This command will actually be // phased out in favor of an app call soon. @@ -207,14 +206,6 @@ default_keys(Bind_Helper *context){ end_map(context); - begin_map(context, my_empty_map1); - inherit_map(context, mapid_nomap); - end_map(context); - - begin_map(context, my_empty_map2); - inherit_map(context, mapid_nomap); - end_map(context); - begin_map(context, my_code_map); // NOTE(allen|a3.1): Set this map (my_code_map == mapid_user_custom) to diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index de878b2e..fa96355a 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -233,15 +233,17 @@ clipboard_copy(Application_Links *app, int start, int end, Buffer_Summary *buffe Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int result = false; - if (0 <= start && start <= end && end <= buffer.size){ - int size = (end - start); - char *str = (char*)app->memory; - - if (size <= app->memory_size){ - app->buffer_read_range(app, &buffer, start, end, str); - app->clipboard_post(app, str, size); - if (buffer_out){*buffer_out = buffer;} - result = true; + if (buffer.exists){ + if (0 <= start && start <= end && end <= buffer.size){ + int size = (end - start); + char *str = (char*)app->memory; + + if (size <= app->memory_size){ + app->buffer_read_range(app, &buffer, start, end, str); + app->clipboard_post(app, str, size); + if (buffer_out){*buffer_out = buffer;} + result = true; + } } } @@ -254,9 +256,11 @@ clipboard_cut(Application_Links *app, int start, int end, Buffer_Summary *buffer Buffer_Summary buffer = {0}; int result = false; - if (clipboard_copy(app, start, end, &buffer, access)){ - app->buffer_replace_range(app, &buffer, start, end, 0, 0); - if (buffer_out){*buffer_out = buffer;} + if (buffer.exists){ + if (clipboard_copy(app, start, end, &buffer, access)){ + app->buffer_replace_range(app, &buffer, start, end, 0, 0); + if (buffer_out){*buffer_out = buffer;} + } } return(result); @@ -691,16 +695,16 @@ CUSTOM_COMMAND_SIG(if0_off){ View_Summary view; Buffer_Summary buffer; - + char text1[] = "\n#if 0"; int size1 = sizeof(text1) - 1; - + char text2[] = "#endif\n"; int size2 = sizeof(text2) - 1; - + Range range; int pos; - + view = app->get_active_view(app, access); buffer = app->get_buffer(app, view.buffer_id, access); @@ -1077,7 +1081,7 @@ CUSTOM_COMMAND_SIG(close_all_code){ int buffers_to_close[2048]; int buffers_to_close_count = 0; - unsigned int access = AccessProtected|AccessHidden; + unsigned int access = AccessAll; for (buffer = app->get_buffer_first(app, access); buffer.exists; app->get_buffer_next(app, &buffer, access)){ @@ -1106,11 +1110,11 @@ CUSTOM_COMMAND_SIG(open_all_code){ String dir = make_string(app->memory, 0, app->memory_size); dir.size = app->directory_get_hot(app, dir.str, dir.memory_size); int dir_size = dir.size; - + // NOTE(allen|a3.4.4): Here we get the list of files in this directory. // Notice that we free_file_list at the end. File_List list = app->get_file_list(app, dir.str, dir.size); - + for (int i = 0; i < list.count; ++i){ File_Info *info = list.infos + i; if (!info->folder){ @@ -1150,14 +1154,9 @@ CUSTOM_COMMAND_SIG(execute_any_cli){ hot_directory = make_fixed_width_string(hot_directory_space); hot_directory.size = app->directory_get_hot(app, hot_directory.str, hot_directory.memory_size); - unsigned int access = AccessProtected|AccessHidden; + unsigned int access = AccessAll; View_Summary view = app->get_active_view(app, access); - // TODO(allen): Make this work without null terminators - terminate_with_null(&bar_out.string); - terminate_with_null(&bar_cmd.string); - terminate_with_null(&hot_directory); - app->exec_system_command(app, &view, buffer_identifier(bar_out.string.str, bar_out.string.size), hot_directory.str, hot_directory.size, @@ -1174,7 +1173,7 @@ CUSTOM_COMMAND_SIG(execute_previous_cli){ hot_directory = make_string_slowly(hot_directory_space); if (out_buffer.size > 0 && cmd.size > 0 && hot_directory.size > 0){ - unsigned int access = AccessProtected|AccessHidden; + unsigned int access = AccessAll; View_Summary view = app->get_active_view(app, access); app->exec_system_command(app, &view, @@ -1194,15 +1193,15 @@ CUSTOM_COMMAND_SIG(execute_arbitrary_command){ char space[1024]; bar.prompt = make_lit_string("Command: "); bar.string = make_fixed_width_string(space); - + if (!query_user_string(app, &bar)) return; - + // NOTE(allen): Here I chose to end this query bar because when I call another // command it might ALSO have query bars and I don't want this one hanging // around at that point. Since the bar exists on my stack the result of the query // is still available in bar.string though. app->end_query_bar(app, &bar, 0); - + if (match(bar.string, make_lit_string("open all code"))){ exec_command(app, open_all_code); } @@ -1263,7 +1262,7 @@ CUSTOM_COMMAND_SIG(build_search){ // // This doesn't actually change the hot directory of 4coder, it's only effect is to // modify the string you passed in to reflect the change in directory if that change was possible. - + int keep_going = 1; int old_size; int size = app->memory_size/2; @@ -1272,41 +1271,35 @@ CUSTOM_COMMAND_SIG(build_search){ dir.size = app->directory_get_hot(app, dir.str, dir.memory_size); String command = make_string((char*)app->memory + size, 0, size); - append(&command, '"'); while (keep_going){ - append(&command, dir); - old_size = dir.size; append(&dir, "build.bat"); if (app->file_exists(app, dir.str, dir.size)){ dir.size = old_size; - append(&command, "build"); append(&command, '"'); + append(&command, dir); + append(&command, "build\""); - unsigned int access = AccessOpen; + unsigned int access = AccessAll; View_Summary view = app->get_active_view(app, access); - terminate_with_null(&dir); - terminate_with_null(&command); - app->exec_system_command(app, &view, buffer_identifier(literal("*compilation*")), dir.str, dir.size, command.str, command.size, CLI_OverlapWithConflict); - return; + break; } dir.size = old_size; if (app->directory_cd(app, dir.str, &dir.size, dir.memory_size, literal("..")) == 0){ keep_going = 0; + app->print_message(app, literal("couldn't find build.bat\n")); } } - - app->print_message(app, literal("couldn't find build.bat\n")); } CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){ diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index cc5cf204..21038fab 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -229,10 +229,7 @@ EXEC_SYSTEM_COMMAND_SIG(external_exec_system_command){ if (file){ i32 proc_count = vars->cli_processes.count; - View_Iter iter; - i32 i; - - for (i = 0; i < proc_count; ++i){ + for (i32 i = 0; i < proc_count; ++i){ if (procs[i].out_file == file){ if (flags & CLI_OverlapWithConflict){ procs[i].out_file = 0; @@ -249,7 +246,7 @@ EXEC_SYSTEM_COMMAND_SIG(external_exec_system_command){ file->settings.unimportant = 1; if (!(flags & CLI_AlwaysBindToView)){ - iter = file_view_iter_init(&models->layout, file, 0); + View_Iter iter = file_view_iter_init(&models->layout, file, 0); if (file_view_iter_good(iter)){ bind_to_new_view = 0; } diff --git a/README.txt b/README.txt index 8373a073..0450d84c 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -Distribution Date: 11.6.2016 (dd.mm.yyyy) +Distribution Date: 20.6.2016 (dd.mm.yyyy) Thank you for contributing to the 4coder project! diff --git a/SUPERREADME.txt b/SUPERREADME.txt index 8b18bc56..927332aa 100644 --- a/SUPERREADME.txt +++ b/SUPERREADME.txt @@ -1,4 +1,4 @@ -Distribution Date: 11.6.2016 (dd.mm.yyyy) +Distribution Date: 20.6.2016 (dd.mm.yyyy) Thank you for contributing to the 4coder project! diff --git a/build_all.bat b/build_all.bat index f1aac017..b5a59566 100644 --- a/build_all.bat +++ b/build_all.bat @@ -4,8 +4,9 @@ call "ctime" -begin 4ed_data.ctm set OPTS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd4610 /wd4390 /WX set OPTS=%OPTS% /GR- /EHa- /nologo /FC -set INCLUDES=/I..\foreign +set INCLUDES=/I..\foreign /I..\foreign\freetype2 set LIBS=user32.lib winmm.lib gdi32.lib opengl32.lib +set LIBS=%LIBS% ..\foreign\freetype.lib set ICON=..\res\icon.res set DEFINES= set FirstError=0 @@ -31,7 +32,7 @@ set EXPORTS=/EXPORT:app_get_functions cl %OPTS% %INCLUDES% %DEFINES% ..\code\4ed_app_target.cpp %* /Fe4ed_app /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS% if %ERRORLEVEL% neq 0 (set FirstError=1) -cl %OPTS% %INCLUDES% %DEFINES% ..\code\win32_4ed.cpp %LIBS% %ICON% %* /Fe4ed +cl %OPTS% %INCLUDES% %DEFINES% ..\code\win32_4ed.cpp %LIBS% %ICON% %* /Fe4ed /link /NODEFAULTLIB:library if %ERRORLEVEL% neq 0 (set FirstError=1) call "print_size.bat" 4ed_app.dll diff --git a/power/4coder_experiments.cpp b/power/4coder_experiments.cpp index 1068d7bd..5c23e086 100644 --- a/power/4coder_experiments.cpp +++ b/power/4coder_experiments.cpp @@ -2,7 +2,7 @@ // TOP #define NO_BINDING -#include "../4coder_default_bindings.cpp" +#include "4coder_default_bindings.cpp" #include diff --git a/win32_4ed.cpp b/win32_4ed.cpp index 9f28d93b..b0023e0c 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -25,12 +25,13 @@ #include #include +#include #include "system_shared.h" #define SUPPORT_DPI 1 #define USE_WIN32_FONTS 0 -#define USE_FT_FONTS 0 +#define USE_FT_FONTS 1 #define FPS 60 #define frame_useconds (1000000 / FPS) @@ -1170,6 +1171,7 @@ Font_Load_Sig(system_draw_font_load){ } i32 oversample = 2; + AllowLocal(oversample); #if SUPPORT_DPI pt_size = ROUND32(pt_size * size_change(win32vars.dpi_x, win32vars.dpi_y)); @@ -1189,7 +1191,11 @@ Font_Load_Sig(system_draw_font_load){ #elif USE_FT_FONTS - success = win32_ft_font_load(); + success = win32_ft_font_load(&win32vars.font_part, + font_out, + filename, + pt_size, + tab_width); #else @@ -1721,13 +1727,13 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ #define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 #define GL_DEBUG_OUTPUT 0x92E0 -typedef void GLDEBUGPROC_TYPE(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, char * message, GLvoid * userParam); -typedef GLDEBUGPROC_TYPE * GLDEBUGPROC; +//typedef void GLDEBUGPROC_TYPE(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char * message, const GLvoid * userParam); +//typedef GLDEBUGPROC_TYPE * GLDEBUGPROC; typedef void glDebugMessageControl_type(GLenum source, GLenum type, GLenum severity, GLsizei count, GLuint * ids, GLboolean enabled); typedef void glDebugMessageCallback_type(GLDEBUGPROC callback, void * userParam); internal void -OpenGLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, char *message, void *userParam) +OpenGLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam) { OutputDebugStringA(message); OutputDebugStringA("\n"); diff --git a/win32_ft_font.cpp b/win32_ft_font.cpp index bc8fa1c2..6c324e16 100644 --- a/win32_ft_font.cpp +++ b/win32_ft_font.cpp @@ -7,62 +7,11 @@ #undef internal -#include #include #include FT_FREETYPE_H #include FT_LCD_FILTER_H #define internal static -//TODO(inso): put in linuxvars -static FcConfig* fc; - -internal char* -linux_get_sys_font(char* name, i32 pt_size){ - char* result = 0; - - if(!fc){ - fc = FcInitLoadConfigAndFonts(); - } - - FcPattern* pat = FcPatternBuild( - NULL, - FC_POSTSCRIPT_NAME, FcTypeString, name, - FC_SIZE, FcTypeDouble, (double)pt_size, - FC_FONTFORMAT, FcTypeString, "TrueType", - NULL - ); - - FcConfigSubstitute(fc, pat, FcMatchPattern); - FcDefaultSubstitute(pat); - - FcResult res; - FcPattern* font = FcFontMatch(fc, pat, &res); - FcChar8* fname = 0; - - if(font){ - FcPatternGetString(font, FC_FILE, 0, &fname); - if(fname){ - result = strdup((char*)fname); - fprintf(stderr, "Got system font from FontConfig: %s\n", result); - } - FcPatternDestroy(font); - } - - FcPatternDestroy(pat); - - if(!result){ - char space[1024]; - String str = make_fixed_width_string(space); - if(sysshared_to_binary_path(&str, name)){ - result = strdup(space); - } else { - result = strdup(name); - } - } - - return result; -} - internal u32 next_pow_of_2(u32 v){ --v; @@ -78,25 +27,23 @@ next_pow_of_2(u32 v){ #define ENABLE_LCD_FILTER 0 internal b32 -win32_ft_font_load(Render_Font *rf, char *name, i32 pt_size, i32 tab_width){ - -#if 0 - char* filename = linux_get_sys_font(name, pt_size); -#else - char* filename = (char*)malloc(256); +win32_ft_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 tab_width){ + + Temp_Memory temp = begin_temp_memory(part); + + char* filename = push_array(part, char, 256); String str = make_string(filename, 0, 256); sysshared_to_binary_path(&str, name); -#endif - + memset(rf, 0, sizeof(*rf)); - + //TODO(inso): put stuff in linuxvars / init in main FT_Library ft; FT_Face face; b32 use_lcd_filter = 0; - + FT_Init_FreeType(&ft); - + //NOTE(inso): i'm not sure the LCD filter looks better, and it doesn't work perfectly with the coloring stuff #if ENABLE_LCD_FILTER if(FT_Library_SetLcdFilter(ft, FT_LCD_FILTER_DEFAULT) == 0){ @@ -105,138 +52,147 @@ win32_ft_font_load(Render_Font *rf, char *name, i32 pt_size, i32 tab_width){ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } #endif - + FT_New_Face(ft, filename, 0, &face); - + // set size & metrics FT_Size_RequestRec_ size = {}; - size.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; + size.type = FT_SIZE_REQUEST_TYPE_NOMINAL; size.height = pt_size << 6; FT_Request_Size(face, &size); - + rf->loaded = 1; - rf->ascent = face->size->metrics.ascender / 64.0f; - rf->descent = face->size->metrics.descender / 64.0f; - rf->advance = face->size->metrics.max_advance / 64.0f; - rf->height = face->size->metrics.height / 64.0f; + rf->ascent = CEIL32 (face->size->metrics.ascender / 64.0f); + rf->descent = FLOOR32 (face->size->metrics.descender / 64.0f); + rf->advance = CEIL32 (face->size->metrics.max_advance / 64.0f); + rf->height = CEIL32 (face->size->metrics.height / 64.0f); rf->line_skip = rf->height - (rf->ascent - rf->descent); - + + rf->height -= rf->line_skip; + rf->line_skip = 0; + int max_glyph_w = face->size->metrics.x_ppem; int max_glyph_h = rf->height; int tex_width = 64; int tex_height = 0; - + // estimate upper bound on texture width do { tex_width *= 2; float glyphs_per_row = ceilf(tex_width / (float) max_glyph_w); float rows = ceilf(NUM_GLYPHS / glyphs_per_row); - tex_height = rows * (max_glyph_h + 2); + tex_height = CEIL32(rows * (max_glyph_h + 2)); } while(tex_height > tex_width); - + tex_height = next_pow_of_2(tex_height); - + int pen_x = 0; int pen_y = 0; - - u32* pixels = (u32*) calloc(tex_width * tex_height, sizeof(u32)); - + + u32* pixels = push_array(part, u32, tex_width * tex_height); + memset(pixels, 0, tex_width * tex_height * sizeof(u32)); + // XXX: test if AUTOHINT looks better or not const u32 ft_extra_flags = use_lcd_filter ? FT_LOAD_TARGET_LCD : FT_LOAD_FORCE_AUTOHINT; - + for(int i = 0; i < NUM_GLYPHS; ++i){ if(FT_Load_Char(face, i, FT_LOAD_RENDER | ft_extra_flags) != 0) continue; - + int w = face->glyph->bitmap.width; int h = face->glyph->bitmap.rows; - + // lcd filter produces RGB bitmaps, need to account for the extra components if(use_lcd_filter){ w /= 3; } - + // move to next line if necessary if(pen_x + w >= tex_width){ pen_x = 0; pen_y += (max_glyph_h + 2); } - + // set all this stuff the renderer needs - stbtt_packedchar* c = rf->chardata + i; - - c->x0 = pen_x; - c->y0 = pen_y; - c->x1 = pen_x + w; - c->y1 = pen_y + h + 1; - - c->xoff = face->glyph->bitmap_left; - c->yoff = -face->glyph->bitmap_top; - + Glyph_Data* c = rf->glyphs + i; + + c->x0 = (f32)(pen_x); + c->y0 = (f32)(pen_y); + c->x1 = (f32)(pen_x + w); + c->y1 = (f32)(pen_y + h + 1); + + c->xoff = (f32)(face->glyph->bitmap_left); + c->yoff = (f32)(rf->ascent - face->glyph->bitmap_top); + c->xoff2 = w + c->xoff; c->yoff2 = h + c->yoff + 1; - - c->xadvance = face->glyph->advance.x >> 6; - - rf->advance_data[i] = c->xadvance; + + rf->advance_data[i] = (f32)(face->glyph->advance.x >> 6); + rf->glyphs[i].exists = 1; - - + + int pitch = face->glyph->bitmap.pitch; - + // write to texture atlas for(int j = 0; j < h; ++j){ for(int i = 0; i < w; ++i){ int x = pen_x + i; int y = pen_y + j; - + if(use_lcd_filter){ u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3]; u8 g = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1]; u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2]; - u8 a = (r + g + b) / 3.0f; - + u8 a = (u8)ROUND32((r + g + b) / 3.0f); + pixels[y * tex_width + x] = (a << 24) | (r << 16) | (g << 8) | b; } else { pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x1010101; } } } - - pen_x = c->x1 + 1; + + pen_x = CEIL32(c->x1 + 1); } - - rf->chardata['\r'] = rf->chardata[' ']; - rf->chardata['\n'] = rf->chardata[' ']; - rf->chardata['\t'] = rf->chardata[' ']; - rf->chardata['\t'].xadvance *= tab_width; - + + Glyph_Data space_glyph = rf->glyphs[' ']; + f32 space_width = rf->advance_data[' ']; + + rf->glyphs['\r'] = space_glyph; + rf->advance_data['\r'] = space_width*tab_width; + + rf->glyphs['\n'] = space_glyph; + rf->advance_data['\n'] = space_width*tab_width; + + rf->glyphs['\t'] = space_glyph; + rf->advance_data['\t'] = space_width*tab_width; + FT_Done_FreeType(ft); - + tex_height = next_pow_of_2(pen_y + max_glyph_h + 2); - + rf->tex_width = tex_width; rf->tex_height = tex_height; - + // upload texture glGenTextures(1, &rf->tex); glBindTexture(GL_TEXTURE_2D, rf->tex); - + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - + if(use_lcd_filter){ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_INT, pixels); } - + glBindTexture(GL_TEXTURE_2D, 0); - - free(pixels); - free(filename); - + + end_temp_memory(temp); + return 1; }