Cleanup; removed 4coder_utf8 library; rewrote win32 u8 <-> u16 layer
							parent
							
								
									6705bc8de5
								
							
						
					
					
						commit
						fae0bc1222
					
				| 
						 | 
					@ -999,6 +999,12 @@ struct Character_Consume_Result{
 | 
				
			||||||
    u32 codepoint;
 | 
					    u32 codepoint;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					global u32 surrogate_min = 0xD800;
 | 
				
			||||||
 | 
					global u32 surrogate_max = 0xDFFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					global u32 nonchar_min = 0xFDD0;
 | 
				
			||||||
 | 
					global u32 nonchar_max = 0xFDEF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Data{
 | 
					struct Data{
 | 
				
			||||||
    u8 *data;
 | 
					    u8 *data;
 | 
				
			||||||
    umem size;
 | 
					    umem size;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,6 @@
 | 
				
			||||||
#include "4coder_stringf.cpp"
 | 
					#include "4coder_stringf.cpp"
 | 
				
			||||||
#include "4coder_app_links_allocator.cpp"
 | 
					#include "4coder_app_links_allocator.cpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "4coder_lib/4coder_utf8.h"
 | 
					 | 
				
			||||||
#include "4coder_table.h"
 | 
					#include "4coder_table.h"
 | 
				
			||||||
#include "4coder_token.h"
 | 
					#include "4coder_token.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -248,12 +248,12 @@ i32 line_number;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
static Command_Metadata fcoder_metacmd_table[226] = {
 | 
					static Command_Metadata fcoder_metacmd_table[226] = {
 | 
				
			||||||
{ PROC_LINKS(set_bindings_mac_default, 0), "set_bindings_mac_default", 24,  "Remap keybindings using the 'mac-default' mapping rule.", 55, "w:\\4ed\\code\\4coder_remapping_commands.cpp", 41, 62 },
 | 
					{ PROC_LINKS(set_bindings_mac_default, 0), "set_bindings_mac_default", 24,  "Remap keybindings using the 'mac-default' mapping rule.", 55, "w:\\4ed\\code\\4coder_remapping_commands.cpp", 41, 62 },
 | 
				
			||||||
{ PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30,  "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2160 },
 | 
					{ PROC_LINKS(seek_beginning_of_textual_line, 0), "seek_beginning_of_textual_line", 30,  "Seeks the cursor to the beginning of the line across all text.", 62, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2152 },
 | 
				
			||||||
{ PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24,  "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2166 },
 | 
					{ PROC_LINKS(seek_end_of_textual_line, 0), "seek_end_of_textual_line", 24,  "Seeks the cursor to the end of the line across all text.", 56, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2158 },
 | 
				
			||||||
{ PROC_LINKS(seek_beginning_of_line, 0), "seek_beginning_of_line", 22,  "Seeks the cursor to the beginning of the visual line.", 53, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2172 },
 | 
					{ PROC_LINKS(seek_beginning_of_line, 0), "seek_beginning_of_line", 22,  "Seeks the cursor to the beginning of the visual line.", 53, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2164 },
 | 
				
			||||||
{ PROC_LINKS(seek_end_of_line, 0), "seek_end_of_line", 16,  "Seeks the cursor to the end of the visual line.", 47, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2178 },
 | 
					{ PROC_LINKS(seek_end_of_line, 0), "seek_end_of_line", 16,  "Seeks the cursor to the end of the visual line.", 47, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2170 },
 | 
				
			||||||
{ PROC_LINKS(goto_beginning_of_file, 0), "goto_beginning_of_file", 22,  "Sets the cursor to the beginning of the file.", 45, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2184 },
 | 
					{ PROC_LINKS(goto_beginning_of_file, 0), "goto_beginning_of_file", 22,  "Sets the cursor to the beginning of the file.", 45, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2176 },
 | 
				
			||||||
{ PROC_LINKS(goto_end_of_file, 0), "goto_end_of_file", 16,  "Sets the cursor to the end of the file.", 39, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2192 },
 | 
					{ PROC_LINKS(goto_end_of_file, 0), "goto_end_of_file", 16,  "Sets the cursor to the end of the file.", 39, "w:\\4ed\\code\\4coder_helper.cpp", 29, 2184 },
 | 
				
			||||||
{ PROC_LINKS(change_active_panel, 0), "change_active_panel", 19,  "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 196 },
 | 
					{ PROC_LINKS(change_active_panel, 0), "change_active_panel", 19,  "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 196 },
 | 
				
			||||||
{ PROC_LINKS(change_active_panel_backwards, 0), "change_active_panel_backwards", 29,  "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 206 },
 | 
					{ PROC_LINKS(change_active_panel_backwards, 0), "change_active_panel_backwards", 29,  "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 206 },
 | 
				
			||||||
{ PROC_LINKS(open_panel_vsplit, 0), "open_panel_vsplit", 17,  "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 216 },
 | 
					{ PROC_LINKS(open_panel_vsplit, 0), "open_panel_vsplit", 17,  "Create a new panel by vertically splitting the active panel.", 60, "w:\\4ed\\code\\4coder_default_framework.cpp", 40, 216 },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,9 +276,9 @@ end_bind_helper_get_buffer(Bind_Helper *helper){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal u32
 | 
					internal u32
 | 
				
			||||||
get_key_code(char *buffer){
 | 
					get_key_code(char *buffer){
 | 
				
			||||||
    u32 ignore;
 | 
					    String_Const_u8 str = SCu8(buffer);
 | 
				
			||||||
    u32 result = utf8_to_u32_length_unchecked((u8*)buffer, &ignore);
 | 
					    Character_Consume_Result consume = utf8_consume(str.str, str.size);
 | 
				
			||||||
    return(result);
 | 
					    return(consume.codepoint);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
////////////////////////////////
 | 
					////////////////////////////////
 | 
				
			||||||
| 
						 | 
					@ -1559,21 +1559,13 @@ key_is_unmodified(Key_Event_Data *key){
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal u32
 | 
					internal u32
 | 
				
			||||||
to_writable_character(User_Input in, uint8_t *character){
 | 
					to_writable_character(User_Input in, u8 *space){
 | 
				
			||||||
    u32 result = 0;
 | 
					    return(utf8_write(space, in.key.character));
 | 
				
			||||||
    if (in.key.character != 0){
 | 
					 | 
				
			||||||
        u32_to_utf8_unchecked(in.key.character, character, &result);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal u32
 | 
					internal u32
 | 
				
			||||||
to_writable_character(Key_Event_Data key, uint8_t *character){
 | 
					to_writable_character(Key_Event_Data key, u8 *space){
 | 
				
			||||||
    u32 result = 0;
 | 
					    return(utf8_write(space, key.character));
 | 
				
			||||||
    if (key.character != 0){
 | 
					 | 
				
			||||||
        u32_to_utf8_unchecked(key.character, character, &result);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal String_Const_u8
 | 
					internal String_Const_u8
 | 
				
			||||||
| 
						 | 
					@ -1617,7 +1609,7 @@ query_user_general(Application_Links *app, Query_Bar *bar, b32 force_number){
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        uint8_t character[4];
 | 
					        u8 character[4];
 | 
				
			||||||
        u32 length = 0;
 | 
					        u32 length = 0;
 | 
				
			||||||
        b32 good_character = false;
 | 
					        b32 good_character = false;
 | 
				
			||||||
        if (key_is_unmodified(&in.key)){
 | 
					        if (key_is_unmodified(&in.key)){
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,395 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Mr. 4th Dimention - Allen Webster
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * 17.02.2017
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Code for converting to and from utf8 to ANSI and utf16 text encodings.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TOP
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if !defined(FED_UTF8_CONVERSION_H)
 | 
					 | 
				
			||||||
#define FED_UTF8_CONVERSION_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u32 cp_min_by_utf8_length[] = {
 | 
					 | 
				
			||||||
    0x0,
 | 
					 | 
				
			||||||
    0x0,
 | 
					 | 
				
			||||||
    0x80,
 | 
					 | 
				
			||||||
    0x800,
 | 
					 | 
				
			||||||
    0x10000,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u32 surrogate_min = 0xD800;
 | 
					 | 
				
			||||||
static u32 surrogate_max = 0xDFFF;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u32 nonchar_min = 0xFDD0;
 | 
					 | 
				
			||||||
static u32 nonchar_max = 0xFDEF;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static b32
 | 
					 | 
				
			||||||
codepoint_is_whitespace(u32 codepoint){
 | 
					 | 
				
			||||||
    b32 result = false;
 | 
					 | 
				
			||||||
    if (codepoint == ' ' || codepoint == '\r' || codepoint == '\n' || codepoint == '\t'){
 | 
					 | 
				
			||||||
        result = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u32
 | 
					 | 
				
			||||||
utf8_to_u32_length_unchecked(u8 *buffer, u32 *length_out){
 | 
					 | 
				
			||||||
    u32 result = 0;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (buffer[0] < 0x80){
 | 
					 | 
				
			||||||
        result = (u32)buffer[0];
 | 
					 | 
				
			||||||
        *length_out = 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (buffer[0] < 0xE0){
 | 
					 | 
				
			||||||
        result = ((u32)((buffer[0])&0x1F)) << 6;
 | 
					 | 
				
			||||||
        result |= ((u32)((buffer[1])&0x3F));
 | 
					 | 
				
			||||||
        *length_out = 2;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (buffer[0] < 0xF0){
 | 
					 | 
				
			||||||
        result = ((u32)((buffer[0])&0x0F)) << 12;
 | 
					 | 
				
			||||||
        result |= ((u32)((buffer[1])&0x3F)) << 6;
 | 
					 | 
				
			||||||
        result |= ((u32)((buffer[2])&0x3F));
 | 
					 | 
				
			||||||
        *length_out = 3;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else{
 | 
					 | 
				
			||||||
        result = ((u32)((buffer[0])&0x07)) << 18;
 | 
					 | 
				
			||||||
        result |= ((u32)((buffer[1])&0x3F)) << 12;
 | 
					 | 
				
			||||||
        result |= ((u32)((buffer[2])&0x3F)) << 6;
 | 
					 | 
				
			||||||
        result |= ((u32)((buffer[3])&0x3F));
 | 
					 | 
				
			||||||
        *length_out = 4;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (result < cp_min_by_utf8_length[*length_out] || (result >= surrogate_min && result <= surrogate_max)){
 | 
					 | 
				
			||||||
        result = 0;
 | 
					 | 
				
			||||||
        *length_out = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u32
 | 
					 | 
				
			||||||
utf8_to_u32_unchecked(u8 *buffer){
 | 
					 | 
				
			||||||
    u32 ignore;
 | 
					 | 
				
			||||||
    u32 result = utf8_to_u32_length_unchecked(buffer, &ignore);
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u32
 | 
					 | 
				
			||||||
utf8_to_u32(u8 **buffer_ptr, u8 *end){
 | 
					 | 
				
			||||||
    u8 *buffer = *buffer_ptr;
 | 
					 | 
				
			||||||
    u32 limit = (u32)(end - buffer);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    u32 length = 0;
 | 
					 | 
				
			||||||
    if (buffer[0] < 0x80){
 | 
					 | 
				
			||||||
        length = 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (buffer[0] < 0xC0){
 | 
					 | 
				
			||||||
        length = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (buffer[0] < 0xE0){
 | 
					 | 
				
			||||||
        length = 2;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (buffer[0] < 0xF0){
 | 
					 | 
				
			||||||
        length = 3;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (buffer[0] < 0xF8){
 | 
					 | 
				
			||||||
        length = 4;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else{
 | 
					 | 
				
			||||||
        length = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for (u32 i = 1; i < length; ++i){
 | 
					 | 
				
			||||||
        if ((buffer[i] & 0xC0) != 0x80){
 | 
					 | 
				
			||||||
            length = 0;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    u32 result = 0;
 | 
					 | 
				
			||||||
    if (length != 0 && length <= limit){
 | 
					 | 
				
			||||||
        switch (length){
 | 
					 | 
				
			||||||
            case 1:
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                result = (u32)buffer[0];
 | 
					 | 
				
			||||||
            }break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            case 2:
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                result = ((u32)((buffer[0])&0x1F)) << 6;
 | 
					 | 
				
			||||||
                result |= ((u32)((buffer[1])&0x3F));
 | 
					 | 
				
			||||||
            }break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            case 3:
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                result = ((u32)((buffer[0])&0x0F)) << 12;
 | 
					 | 
				
			||||||
                result |= ((u32)((buffer[1])&0x3F)) << 6;
 | 
					 | 
				
			||||||
                result |= ((u32)((buffer[2])&0x3F));
 | 
					 | 
				
			||||||
            }break;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            case 4:
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                result = ((u32)((buffer[0])&0x07)) << 18;
 | 
					 | 
				
			||||||
                result |= ((u32)((buffer[1])&0x3F)) << 12;
 | 
					 | 
				
			||||||
                result |= ((u32)((buffer[2])&0x3F)) << 6;
 | 
					 | 
				
			||||||
                result |= ((u32)((buffer[3])&0x3F));
 | 
					 | 
				
			||||||
            }break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (result < cp_min_by_utf8_length[length] || (result >= surrogate_min && result <= surrogate_max)){
 | 
					 | 
				
			||||||
            result = 0;
 | 
					 | 
				
			||||||
            length = 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        *buffer_ptr = buffer + length;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else{
 | 
					 | 
				
			||||||
        *buffer_ptr = end;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return(result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
u32_to_utf8_unchecked(u32 codepoint, u8 *buffer, u32 *length_out){
 | 
					 | 
				
			||||||
    if (codepoint <= 0x7F){
 | 
					 | 
				
			||||||
        buffer[0] = (u8)codepoint;
 | 
					 | 
				
			||||||
        *length_out = 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (codepoint <= 0x7FF){
 | 
					 | 
				
			||||||
        buffer[0] = (u8)(0xC0 | (codepoint >> 6));
 | 
					 | 
				
			||||||
        buffer[1] = (u8)(0x80 | (codepoint & 0x3F));
 | 
					 | 
				
			||||||
        *length_out = 2;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (codepoint <= 0xFFFF){
 | 
					 | 
				
			||||||
        buffer[0] = (u8)(0xE0 | (codepoint >> 12));
 | 
					 | 
				
			||||||
        buffer[1] = (u8)(0x80 | ((codepoint >> 6) & 0x3F));
 | 
					 | 
				
			||||||
        buffer[2] = (u8)(0x80 | (codepoint & 0x3F));
 | 
					 | 
				
			||||||
        *length_out = 3;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (codepoint <= 0x10FFFF){
 | 
					 | 
				
			||||||
        codepoint &= 0x001FFFFF;
 | 
					 | 
				
			||||||
        buffer[0] = (u8)(0xF0 | (codepoint >> 18));
 | 
					 | 
				
			||||||
        buffer[1] = (u8)(0x80 | ((codepoint >> 12) & 0x3F));
 | 
					 | 
				
			||||||
        buffer[2] = (u8)(0x80 | ((codepoint >> 6) & 0x3F));
 | 
					 | 
				
			||||||
        buffer[3] = (u8)(0x80 | (codepoint & 0x3F));
 | 
					 | 
				
			||||||
        *length_out = 4;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else{
 | 
					 | 
				
			||||||
        *length_out = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static umem
 | 
					 | 
				
			||||||
utf8_to_utf16_minimal_checking(u16 *dst, umem max_wchars, u8 *src, umem length, b32 *error){
 | 
					 | 
				
			||||||
    u8 *s = src;
 | 
					 | 
				
			||||||
    u8 *s_end = s + length;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    u16 *d = dst;
 | 
					 | 
				
			||||||
    u16 *d_end = d + max_wchars;
 | 
					 | 
				
			||||||
    umem limit = length;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    umem needed_max = 0;
 | 
					 | 
				
			||||||
    u32 advance = 1;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    *error = false;
 | 
					 | 
				
			||||||
    for(; s < s_end;){
 | 
					 | 
				
			||||||
        u32 codepoint = 0;
 | 
					 | 
				
			||||||
        u32 utf8_size = 0;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (s[0] < 0x80){
 | 
					 | 
				
			||||||
            codepoint = (u32)s[0];
 | 
					 | 
				
			||||||
            utf8_size = 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (s[0] < 0xE0){
 | 
					 | 
				
			||||||
            if (limit <= 1){
 | 
					 | 
				
			||||||
                *error = true;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            codepoint = ((u32)((s[0])&0x1F)) << 6;
 | 
					 | 
				
			||||||
            codepoint |= ((u32)((s[1])&0x3F));
 | 
					 | 
				
			||||||
            utf8_size = 2;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (s[0] < 0xF0){
 | 
					 | 
				
			||||||
            if (limit <= 2){
 | 
					 | 
				
			||||||
                *error = true;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            codepoint = ((u32)((s[0])&0x0F)) << 12;
 | 
					 | 
				
			||||||
            codepoint |= ((u32)((s[1])&0x3F)) << 6;
 | 
					 | 
				
			||||||
            codepoint |= ((u32)((s[2])&0x3F));
 | 
					 | 
				
			||||||
            utf8_size = 3;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (s[0] < 0xF8){
 | 
					 | 
				
			||||||
            if (limit > 3){
 | 
					 | 
				
			||||||
                *error = true;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            codepoint = ((u32)((s[0])&0x07)) << 18;
 | 
					 | 
				
			||||||
            codepoint |= ((u32)((s[1])&0x3F)) << 12;
 | 
					 | 
				
			||||||
            codepoint |= ((u32)((s[2])&0x3F)) << 6;
 | 
					 | 
				
			||||||
            codepoint |= ((u32)((s[3])&0x3F));
 | 
					 | 
				
			||||||
            utf8_size = 4;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else{
 | 
					 | 
				
			||||||
            *error = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (codepoint < cp_min_by_utf8_length[utf8_size]){
 | 
					 | 
				
			||||||
            *error = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        s += utf8_size;
 | 
					 | 
				
			||||||
        limit -= utf8_size;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)){
 | 
					 | 
				
			||||||
            *d = (u16)(codepoint);
 | 
					 | 
				
			||||||
            d += advance;
 | 
					 | 
				
			||||||
            needed_max += 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (codepoint >= 0x10000 && codepoint <= 0x10FFFF){
 | 
					 | 
				
			||||||
            codepoint -= 0x10000;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            u32 high = (codepoint >> 10) & 0x03FF;
 | 
					 | 
				
			||||||
            u32 low = (codepoint) & 0x03FF;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            high += 0xD800;
 | 
					 | 
				
			||||||
            low += 0xDC00;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            if (d + advance < d_end){
 | 
					 | 
				
			||||||
                *d = (u16)high;
 | 
					 | 
				
			||||||
                d += advance;
 | 
					 | 
				
			||||||
                *d = (u16)low;
 | 
					 | 
				
			||||||
                d += advance;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else{
 | 
					 | 
				
			||||||
                advance = 0;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            needed_max += 2;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else{
 | 
					 | 
				
			||||||
            *error = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (d >= d_end){
 | 
					 | 
				
			||||||
            advance = 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return(needed_max);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static umem
 | 
					 | 
				
			||||||
utf16_to_utf8_minimal_checking(u8 *dst, umem max_chars, u16 *src, umem length, b32 *error){
 | 
					 | 
				
			||||||
    u16 *s = src;
 | 
					 | 
				
			||||||
    u16 *s_end = s + length;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    u8 *d = dst;
 | 
					 | 
				
			||||||
    u8 *d_end = d + max_chars;
 | 
					 | 
				
			||||||
    umem limit = length;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    umem needed_max = 0;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    *error = false;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for (; s < s_end;){
 | 
					 | 
				
			||||||
        u32 codepoint = 0;
 | 
					 | 
				
			||||||
        u32 utf16_size = 0;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (s[0] <= 0xD7FF || (s[0] >= 0xE000 && s[0] <= 0xFFFF)){
 | 
					 | 
				
			||||||
            codepoint = s[0];
 | 
					 | 
				
			||||||
            utf16_size = 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else{
 | 
					 | 
				
			||||||
            if (s[0] >= 0xD800 && s[0] <= 0xDBFF){
 | 
					 | 
				
			||||||
                if (limit <= 1){
 | 
					 | 
				
			||||||
                    *error = true;
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                u32 high = s[0] - 0xD800;
 | 
					 | 
				
			||||||
                u32 low = s[1] - 0xDC00;
 | 
					 | 
				
			||||||
                codepoint = ((high << 10) | (low)) + 0x10000;
 | 
					 | 
				
			||||||
                utf16_size = 2;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else{
 | 
					 | 
				
			||||||
                *error = true;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        s += utf16_size;
 | 
					 | 
				
			||||||
        limit -= utf16_size;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        u8 d_fill[4];
 | 
					 | 
				
			||||||
        u32 d_fill_count = 0;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (codepoint <= 0x7F){
 | 
					 | 
				
			||||||
            d_fill[0] = (u8)codepoint;
 | 
					 | 
				
			||||||
            d_fill_count = 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (codepoint <= 0x7FF){
 | 
					 | 
				
			||||||
            d_fill[0] = (u8)(0xC0 | (codepoint >> 6));
 | 
					 | 
				
			||||||
            d_fill[1] = (u8)(0x80 | (codepoint & 0x3F));
 | 
					 | 
				
			||||||
            d_fill_count = 2;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (codepoint <= 0xFFFF){
 | 
					 | 
				
			||||||
            d_fill[0] = (u8)(0xE0 | (codepoint >> 12));
 | 
					 | 
				
			||||||
            d_fill[1] = (u8)(0x80 | ((codepoint >> 6) & 0x3F));
 | 
					 | 
				
			||||||
            d_fill[2] = (u8)(0x80 | (codepoint & 0x3F));
 | 
					 | 
				
			||||||
            d_fill_count = 3;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (codepoint <= 0x10FFFF){
 | 
					 | 
				
			||||||
            d_fill[0] = (u8)(0xF0 | (codepoint >> 18));
 | 
					 | 
				
			||||||
            d_fill[1] = (u8)(0x80 | ((codepoint >> 12) & 0x3F));
 | 
					 | 
				
			||||||
            d_fill[2] = (u8)(0x80 | ((codepoint >> 6) & 0x3F));
 | 
					 | 
				
			||||||
            d_fill[3] = (u8)(0x80 | (codepoint & 0x3F));
 | 
					 | 
				
			||||||
            d_fill_count = 4;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else{
 | 
					 | 
				
			||||||
            *error = true;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if (d + d_fill_count <= d_end){
 | 
					 | 
				
			||||||
            for (u32 i = 0; i < d_fill_count; ++i){
 | 
					 | 
				
			||||||
                *d = d_fill[i];
 | 
					 | 
				
			||||||
                ++d;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        needed_max += d_fill_count;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return(needed_max);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
byte_to_ascii(u8 n, u8 *out){
 | 
					 | 
				
			||||||
    u8 C = '0' + (n / 0x10);
 | 
					 | 
				
			||||||
    if ((n / 0x10) > 0x9){
 | 
					 | 
				
			||||||
        C = ('A' - 0xA) + (n / 0x10);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    out[0] = C;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    n = (n % 0x10);
 | 
					 | 
				
			||||||
    C = '0' + n;
 | 
					 | 
				
			||||||
    if (n > 0x9){
 | 
					 | 
				
			||||||
        C = ('A' - 0xA) + n;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    out[1] = C;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// BOTTOM
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -30,8 +30,6 @@
 | 
				
			||||||
#include "4coder_hash_functions.cpp"
 | 
					#include "4coder_hash_functions.cpp"
 | 
				
			||||||
#include "4coder_table.cpp"
 | 
					#include "4coder_table.cpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "4coder_lib/4coder_utf8.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "4ed_render_target.h"
 | 
					#include "4ed_render_target.h"
 | 
				
			||||||
#include "4ed.h"
 | 
					#include "4ed.h"
 | 
				
			||||||
#include "4ed_buffer_model.h"
 | 
					#include "4ed_buffer_model.h"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -318,7 +318,19 @@ draw_string(Render_Target *target, Face *face, String_Const_u8 string, Vec2 poin
 | 
				
			||||||
                    if (color != 0){
 | 
					                    if (color != 0){
 | 
				
			||||||
                        u8 cs[3];
 | 
					                        u8 cs[3];
 | 
				
			||||||
                        cs[0] = '\\';
 | 
					                        cs[0] = '\\';
 | 
				
			||||||
                        byte_to_ascii(n, cs+1);
 | 
					                        u8 nh = (n >> 4);
 | 
				
			||||||
 | 
					                        u8 nl = (n & 0xF);
 | 
				
			||||||
 | 
					                        u8 ch = '0' + nh;
 | 
				
			||||||
 | 
					                        u8 cl = '0' + nl;
 | 
				
			||||||
 | 
					                        if (nh > 0x9){
 | 
				
			||||||
 | 
					                            ch = ('A' - 0xA) + nh;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        if (nl > 0x9){
 | 
				
			||||||
 | 
					                            cl = ('A' - 0xA) + nl;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        cs[1] = ch;
 | 
				
			||||||
 | 
					                        cs[2] = cl;
 | 
				
			||||||
 | 
					                        
 | 
				
			||||||
                        Vec2 pp = point;
 | 
					                        Vec2 pp = point;
 | 
				
			||||||
                        for (u32 j = 0; j < 3; ++j){
 | 
					                        for (u32 j = 0; j < 3; ++j){
 | 
				
			||||||
                            draw_font_glyph(target, face, cs[j], pp.x, pp.y, color, flags);
 | 
					                            draw_font_glyph(target, face, cs[j], pp.x, pp.y, color, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,23 +105,6 @@ translating_consume_byte(Translation_State *tran, u8 ch, u32 i, u32 size, Transl
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal void
 | 
					 | 
				
			||||||
translating_select_emit_rule_ASCII(Translation_State *tran, Translation_Byte_Description desc, Translation_Emit_Rule *type_out){
 | 
					 | 
				
			||||||
    type_out->byte_class = desc.byte_class;
 | 
					 | 
				
			||||||
    type_out->last_byte_handler = desc.last_byte_handler;
 | 
					 | 
				
			||||||
    type_out->emit_type = desc.prelim_emit_type;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    type_out->codepoint = 0;
 | 
					 | 
				
			||||||
    type_out->codepoint_length = 0;
 | 
					 | 
				
			||||||
    if (desc.prelim_emit_type == BufferModelUnit_Codepoint){
 | 
					 | 
				
			||||||
        u32 cp = utf8_to_u32_length_unchecked(tran->fill_buffer, &type_out->codepoint_length);
 | 
					 | 
				
			||||||
        type_out->codepoint = cp;
 | 
					 | 
				
			||||||
        if (!(cp == '\n' || cp == '\t' || cp == '\r' || (cp >= ' ' && cp <= 255 && cp != 127))){
 | 
					 | 
				
			||||||
            type_out->emit_type = BufferModelUnit_Numbers;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal void
 | 
					internal void
 | 
				
			||||||
translating_select_emit_rule_UTF8(Translation_State *tran, Translation_Byte_Description desc, Translation_Emit_Rule *type_out){
 | 
					translating_select_emit_rule_UTF8(Translation_State *tran, Translation_Byte_Description desc, Translation_Emit_Rule *type_out){
 | 
				
			||||||
    type_out->byte_class = desc.byte_class;
 | 
					    type_out->byte_class = desc.byte_class;
 | 
				
			||||||
| 
						 | 
					@ -131,7 +114,12 @@ translating_select_emit_rule_UTF8(Translation_State *tran, Translation_Byte_Desc
 | 
				
			||||||
    type_out->codepoint = 0;
 | 
					    type_out->codepoint = 0;
 | 
				
			||||||
    type_out->codepoint_length = 0;
 | 
					    type_out->codepoint_length = 0;
 | 
				
			||||||
    if (desc.prelim_emit_type == BufferModelUnit_Codepoint){
 | 
					    if (desc.prelim_emit_type == BufferModelUnit_Codepoint){
 | 
				
			||||||
        u32 cp = utf8_to_u32_length_unchecked(tran->fill_buffer, &type_out->codepoint_length);
 | 
					        Character_Consume_Result consume = utf8_consume(tran->fill_buffer, ArrayCount(tran->fill_buffer));
 | 
				
			||||||
 | 
					        u32 cp = consume.codepoint;
 | 
				
			||||||
 | 
					        type_out->codepoint_length = consume.inc;
 | 
				
			||||||
 | 
					        if (cp == max_u32){
 | 
				
			||||||
 | 
					            type_out->codepoint_length = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if (type_out->codepoint_length != 0){
 | 
					        if (type_out->codepoint_length != 0){
 | 
				
			||||||
            if ((cp >= nonchar_min && cp <= nonchar_max) || ((cp & 0xFFFF) >= 0xFFFE)){
 | 
					            if ((cp >= nonchar_min && cp <= nonchar_max) || ((cp & 0xFFFF) >= 0xFFFE)){
 | 
				
			||||||
                type_out->emit_type = BufferModelUnit_Numbers;
 | 
					                type_out->emit_type = BufferModelUnit_Numbers;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,69 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
$ProductVersion{4.1.0}
 | 
					 | 
				
			||||||
$ManualSubVersion{0}
 | 
					 | 
				
			||||||
$File{4coder_manual}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$Title{4coder 4.1 User's Manual}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$Hd{1}{4coder 4.1. User's Manual}
 | 
					 | 
				
			||||||
$Hd{3}[Allen Webster, 2018-09-07}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$TableOfContents{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$BeginContents{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$PushSection{ALL}{}{$Hd{2}{First Time User}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$PushSection{ALL}{}{$Hd{3}{Organization}}
 | 
					 | 
				
			||||||
4coder's most basic organization of information is by $Link{buffers}{org_buffers} and $Link{views}{views}.  Buffers, described
 | 
					 | 
				
			||||||
simply, are an optimized array of characters encoded in UTF-8, that support reading and writing anywhere in the buffer and can
 | 
					 | 
				
			||||||
be rendered to screen.  A view represents an region of the 4coder window with a self contained state for interactions from the
 | 
					 | 
				
			||||||
user.  
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
These major objects exist independently, they are created and closed independently.  The only relationship that ever exists
 | 
					 | 
				
			||||||
between a view and a buffer is that a view can set a buffer as it's target for writing, reading, and rendering.  Multiple views
 | 
					 | 
				
			||||||
can target a single buffer.  Any view can target any buffer at any time.  Closing a buffer in a view leaves the view open,
 | 
					 | 
				
			||||||
closing a view that targets a buffer leaves the buffer open.  All of this is to emphasize that these two types of entities
 | 
					 | 
				
			||||||
exist absolutely independently and have only a very weak relationship.
 | 
					 | 
				
			||||||
$PopSection{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$PushSection{ALL}{org_buffers}{$Hd{3}{Buffer Basics}}
 | 
					 | 
				
			||||||
A buffer is essentially an optimized array of characters encoded in UTF-8, with a lot of extra features attached.  Many
 | 
					 | 
				
			||||||
buffers will be tied directly to a corresponding file and will save their contents out to their file, but a few buffers exist
 | 
					 | 
				
			||||||
just to be a holder for text.  In deafult 4coder behavior all buffers that lack a backing file have a name starting and ending
 | 
					 | 
				
			||||||
with $Code{'*'} characters.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A new buffer with a file association can be opened any time using one of the interactive commands for file system browsing:
 | 
					 | 
				
			||||||
$BeginTable{FileBuf}{1}
 | 
					 | 
				
			||||||
$Row{$Link{cmdref_interactive_open_or_new}{interactive_open_or_new}}
 | 
					 | 
				
			||||||
$Row{$Link{cmdref_interactive_new}{interactive_new}}
 | 
					 | 
				
			||||||
$Row{$Link{cmdref_interactive_open}{interactive_open}}
 | 
					 | 
				
			||||||
$EndContents{FileBuf}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Once you open a new buffer with a file association it will be the dedicated buffer for that file from then on, opening the
 | 
					 | 
				
			||||||
file again will always just bring you back to the buffer you already opened, to create a totally different copy you have to
 | 
					 | 
				
			||||||
manually make a fresh new buffer and then copy the contents over.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
To see a list of all open buffers and switch a view to targetting any buffer there is the interactive command
 | 
					 | 
				
			||||||
$Link{cmdref_interactive_switch_buffer}{interactive_switch_buffer}.
 | 
					 | 
				
			||||||
$PopSection{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$PopSection{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$PushSection{ALL}{}{$Hd{2}{Commands}}
 | 
					 | 
				
			||||||
$ImportContents{commands.man}{ALL}
 | 
					 | 
				
			||||||
$PopSection{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$PushSection{ALL}{}{$Hd{2}{Bindings}}
 | 
					 | 
				
			||||||
$ImportContents{bindings.man}{ALL}
 | 
					 | 
				
			||||||
$PopSection{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$PushSection{ALL}{}{$Hd{2}{Config Files and Project Files}}
 | 
					 | 
				
			||||||
$PopSection{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$PushSection{ALL}{}{$Hd{2}{Customization}}
 | 
					 | 
				
			||||||
$PopSection{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$EndContents{ALL}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,6 @@
 | 
				
			||||||
#include "4coder_API/4coder_version.h"
 | 
					#include "4coder_API/4coder_version.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include "4coder_lib/4coder_utf8.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(FRED_SUPER)
 | 
					#if defined(FRED_SUPER)
 | 
				
			||||||
# include "4coder_base_types.cpp"
 | 
					# include "4coder_base_types.cpp"
 | 
				
			||||||
| 
						 | 
					@ -170,8 +169,7 @@ struct Win32_Vars{
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    String_Const_u8 binary_path;
 | 
					    String_Const_u8 binary_path;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    u8 *clip_buffer;
 | 
					    Arena *clipboard_arena;
 | 
				
			||||||
    u32 clip_max;
 | 
					 | 
				
			||||||
    String_Const_u8 clipboard_contents;
 | 
					    String_Const_u8 clipboard_contents;
 | 
				
			||||||
    b32 next_clipboard_is_self;
 | 
					    b32 next_clipboard_is_self;
 | 
				
			||||||
    DWORD clipboard_sequence;
 | 
					    DWORD clipboard_sequence;
 | 
				
			||||||
| 
						 | 
					@ -388,57 +386,34 @@ win32_read_clipboard_contents(Arena *scratch){
 | 
				
			||||||
    if (can_read){
 | 
					    if (can_read){
 | 
				
			||||||
        if (OpenClipboard(win32vars.window_handle)){
 | 
					        if (OpenClipboard(win32vars.window_handle)){
 | 
				
			||||||
            result = true;
 | 
					            result = true;
 | 
				
			||||||
            HANDLE clip_data = 0;
 | 
					            String_u8 contents = {};
 | 
				
			||||||
            i32 contents_length = 0;
 | 
					            Arena *clip_arena = win32vars.clipboard_arena;
 | 
				
			||||||
            if (has_unicode){
 | 
					            if (has_unicode){
 | 
				
			||||||
                clip_data = GetClipboardData(CF_UNICODETEXT);
 | 
					                HANDLE clip_data = GetClipboardData(CF_UNICODETEXT);
 | 
				
			||||||
                if (clip_data != 0){
 | 
					                if (clip_data != 0){
 | 
				
			||||||
                    u16 *clip_16 = (u16*)GlobalLock(clip_data);
 | 
					                    u16 *clip_16_ptr = (u16*)GlobalLock(clip_data);
 | 
				
			||||||
                    if (clip_16 != 0){
 | 
					                    if (clip_16_ptr != 0){
 | 
				
			||||||
                        u32 clip_16_len = 0;
 | 
					                        linalloc_clear(clip_arena);
 | 
				
			||||||
                        for(;clip_16[clip_16_len];++clip_16_len);
 | 
					                        String_Const_u16 clip_16 = SCu16(clip_16_ptr);
 | 
				
			||||||
                        
 | 
					                        contents = string_u8_from_string_u16(clip_arena, clip_16, StringFill_NullTerminate);
 | 
				
			||||||
                        b32 error = false;
 | 
					 | 
				
			||||||
                        u32 clip_8_len = (u32)utf16_to_utf8_minimal_checking(win32vars.clip_buffer, win32vars.clip_max-1, clip_16, clip_16_len, &error);
 | 
					 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                        for (;clip_8_len >= win32vars.clip_max && !error;){
 | 
					 | 
				
			||||||
                            system_memory_free(win32vars.clip_buffer, win32vars.clip_max);
 | 
					 | 
				
			||||||
                            win32vars.clip_max = round_up_u32(clip_8_len + 1, KB(4));
 | 
					 | 
				
			||||||
                            win32vars.clip_buffer = (u8*)system_memory_allocate(win32vars.clip_max);
 | 
					 | 
				
			||||||
                            clip_8_len = (u32)utf16_to_utf8_minimal_checking(win32vars.clip_buffer, win32vars.clip_max - 1, clip_16, clip_16_len, &error);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                        if (clip_8_len < win32vars.clip_max && !error){
 | 
					 | 
				
			||||||
                            win32vars.clip_buffer[clip_8_len] = 0;
 | 
					 | 
				
			||||||
                            contents_length = clip_8_len + 1;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                GlobalUnlock(clip_data);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else{
 | 
					            else{
 | 
				
			||||||
                clip_data = GetClipboardData(CF_TEXT);
 | 
					                HANDLE clip_data = GetClipboardData(CF_TEXT);
 | 
				
			||||||
                if (clip_data != 0){
 | 
					                if (clip_data != 0){
 | 
				
			||||||
                    char *clip_ascii = (char*)GlobalLock(clip_data);
 | 
					                    char *clip_ascii_ptr = (char*)GlobalLock(clip_data);
 | 
				
			||||||
                    if (clip_ascii != 0){
 | 
					                    if (clip_ascii_ptr != 0){
 | 
				
			||||||
                        u32 clip_ascii_len = 0;
 | 
					                        linalloc_clear(clip_arena);
 | 
				
			||||||
                        for(;clip_ascii[clip_ascii_len];++clip_ascii_len);
 | 
					                        String_Const_char clip_ascii = SCchar(clip_ascii_ptr);
 | 
				
			||||||
                        
 | 
					                        contents = string_u8_from_string_char(clip_arena, clip_ascii, StringFill_NullTerminate);
 | 
				
			||||||
                        if (clip_ascii_len >= win32vars.clip_max){
 | 
					 | 
				
			||||||
                            system_memory_free(win32vars.clip_buffer, win32vars.clip_max);
 | 
					 | 
				
			||||||
                            win32vars.clip_max = round_up_u32(clip_ascii_len + 1, KB(4));
 | 
					 | 
				
			||||||
                            win32vars.clip_buffer = (u8*)system_memory_allocate(win32vars.clip_max);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        memcpy(win32vars.clip_buffer, clip_ascii, clip_ascii_len + 1);
 | 
					 | 
				
			||||||
                        contents_length = clip_ascii_len + 1;
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            if (contents_length > 0){
 | 
					 | 
				
			||||||
                win32vars.clipboard_contents = SCu8(win32vars.clip_buffer, contents_length - 1);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
                GlobalUnlock(clip_data);
 | 
					                GlobalUnlock(clip_data);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            win32vars.clipboard_contents = contents.string;
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            CloseClipboard();
 | 
					            CloseClipboard();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1634,8 +1609,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
 | 
				
			||||||
        win32_output_error_string(scratch, ErrorString_UseLog);
 | 
					        win32_output_error_string(scratch, ErrorString_UseLog);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    win32vars.clip_max = KB(16);
 | 
					    win32vars.clipboard_arena = reserve_arena(win32vars.tctx);
 | 
				
			||||||
    win32vars.clip_buffer = (u8*)system_memory_allocate(win32vars.clip_max);
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    win32vars.clipboard_sequence = GetClipboardSequenceNumber();
 | 
					    win32vars.clipboard_sequence = GetClipboardSequenceNumber();
 | 
				
			||||||
    if (win32vars.clipboard_sequence == 0){
 | 
					    if (win32vars.clipboard_sequence == 0){
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -378,17 +378,9 @@ color_picker_hook(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam){
 | 
				
			||||||
            Color_Picker *picker = (Color_Picker*)win32_params->lCustData;
 | 
					            Color_Picker *picker = (Color_Picker*)win32_params->lCustData;
 | 
				
			||||||
            SetWindowLongPtr(Window, GWLP_USERDATA, (LONG_PTR)LParam);
 | 
					            SetWindowLongPtr(Window, GWLP_USERDATA, (LONG_PTR)LParam);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            u16 Temp[256];
 | 
					            Scratch_Block scratch(win32vars.tctx);
 | 
				
			||||||
            Temp[ArrayCount(Temp) - 1] = 0;
 | 
					            String_u16 temp = string_u16_from_string_u8(scratch, picker->title, StringFill_NullTerminate);
 | 
				
			||||||
            
 | 
					            SetWindowTextW(Window, (LPCWSTR)temp.str);
 | 
				
			||||||
            b32 ignored;
 | 
					 | 
				
			||||||
            utf8_to_utf16_minimal_checking(Temp, ArrayCount(Temp), (u8 *)picker->title.str, picker->title.size, &ignored);
 | 
					 | 
				
			||||||
            if(picker->title.size < ArrayCount(Temp))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                Temp[picker->title.size] = 0;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            SetWindowTextW(Window, (LPCWSTR)Temp);
 | 
					 | 
				
			||||||
        } break;
 | 
					        } break;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        case WM_CTLCOLORSTATIC:
 | 
					        case WM_CTLCOLORSTATIC:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,50 +12,12 @@
 | 
				
			||||||
#if !defined(FRED_WIN32_UTF8_CPP)
 | 
					#if !defined(FRED_WIN32_UTF8_CPP)
 | 
				
			||||||
#define FRED_WIN32_UTF8_CPP
 | 
					#define FRED_WIN32_UTF8_CPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO(allen): rewrite _EVERYTHING_ that does Win32 UTF16 <-> UTF8
 | 
					 | 
				
			||||||
internal Win32_UTF16
 | 
					 | 
				
			||||||
input_8_to_16(Arena *scratch, u8 *in, u32 in_length){
 | 
					 | 
				
			||||||
    Win32_UTF16 r = {};
 | 
					 | 
				
			||||||
    u32 utf16_max = (in_length + 1)*2;
 | 
					 | 
				
			||||||
    u16 *utf16 = push_array(scratch, u16, utf16_max);
 | 
					 | 
				
			||||||
    b32 error = false;
 | 
					 | 
				
			||||||
    u32 utf16_len = (u32)utf8_to_utf16_minimal_checking(utf16, utf16_max - 1, in, in_length, &error);
 | 
					 | 
				
			||||||
    if (!error && utf16_len < utf16_max){
 | 
					 | 
				
			||||||
        utf16[utf16_len] = 0;
 | 
					 | 
				
			||||||
        r.success = true;
 | 
					 | 
				
			||||||
        r.utf8_len = in_length;
 | 
					 | 
				
			||||||
        r.utf16_max = utf16_max;
 | 
					 | 
				
			||||||
        r.utf16_len = utf16_len;
 | 
					 | 
				
			||||||
        r.utf16 = utf16;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return(r);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal Win32_UTF16
 | 
					 | 
				
			||||||
input_8_to_16(Arena *scratch, u8 *in){
 | 
					 | 
				
			||||||
    u32 length = 0;
 | 
					 | 
				
			||||||
    for (;in[length];++length);
 | 
					 | 
				
			||||||
    return(input_8_to_16(scratch, in, length));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal Win32_UTF16
 | 
					 | 
				
			||||||
input_8_to_16(Arena *scratch, String_Const_u8 in){
 | 
					 | 
				
			||||||
    return(input_8_to_16(scratch, in.str, (u32)in.size));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
internal HANDLE
 | 
					internal HANDLE
 | 
				
			||||||
CreateFile_utf8(Arena *scratch, u8 *name, DWORD access, DWORD share, LPSECURITY_ATTRIBUTES security, DWORD creation, DWORD flags, HANDLE template_file){
 | 
					CreateFile_utf8(Arena *scratch, u8 *name, DWORD access, DWORD share, LPSECURITY_ATTRIBUTES security, DWORD creation, DWORD flags, HANDLE template_file){
 | 
				
			||||||
    HANDLE result = INVALID_HANDLE_VALUE;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    Temp_Memory temp = begin_temp(scratch);
 | 
					    Temp_Memory temp = begin_temp(scratch);
 | 
				
			||||||
    
 | 
					    String_u16 name_16 = string_u16_from_string_u8(scratch, SCu8(name), StringFill_NullTerminate);
 | 
				
			||||||
    Win32_UTF16 name_16 = input_8_to_16(scratch, name);
 | 
					    HANDLE result = CreateFileW((LPWSTR)name_16.str, access, share, security, creation, flags, template_file);
 | 
				
			||||||
    if (name_16.success){
 | 
					 | 
				
			||||||
        result = CreateFileW((LPWSTR)name_16.utf16, access, share, security, creation, flags, template_file);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    end_temp(temp);
 | 
					    end_temp(temp);
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,10 +39,14 @@ GetFinalPathNameByHandle_utf8(Arena *scratch, HANDLE file, u8 *file_path_out, DW
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        if (length_16 != 0 && length_16 < path_16_max){
 | 
					        if (length_16 != 0 && length_16 < path_16_max){
 | 
				
			||||||
            b32 convert_error = false;
 | 
					            b32 convert_error = false;
 | 
				
			||||||
            u32 path_8_len = (u32)utf16_to_utf8_minimal_checking(file_path_out, path_max-1, path_16, length_16, &convert_error);
 | 
					            String_Const_u16 path_16_str = SCu16(path_16, length_16);
 | 
				
			||||||
            if (path_8_len < path_max && !convert_error){
 | 
					            String_u8 path_8 = string_u8_from_string_u16(scratch, path_16_str, StringFill_NullTerminate);
 | 
				
			||||||
                file_path_out[path_8_len] = 0;
 | 
					            if (path_8.size + 1 <= path_max && !convert_error){
 | 
				
			||||||
                result = path_8_len;
 | 
					                block_copy(file_path_out, path_8.str, path_8.size + 1);
 | 
				
			||||||
 | 
					                result = (DWORD)path_8.size;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else{
 | 
				
			||||||
 | 
					                result = (DWORD)path_8.size + 1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					@ -92,48 +58,33 @@ GetFinalPathNameByHandle_utf8(Arena *scratch, HANDLE file, u8 *file_path_out, DW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal HANDLE
 | 
					internal HANDLE
 | 
				
			||||||
FindFirstFile_utf8(Arena *scratch, u8 *name, LPWIN32_FIND_DATA find_data){
 | 
					FindFirstFile_utf8(Arena *scratch, u8 *name, LPWIN32_FIND_DATA find_data){
 | 
				
			||||||
    HANDLE result = INVALID_HANDLE_VALUE;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    Temp_Memory temp = begin_temp(scratch);
 | 
					    Temp_Memory temp = begin_temp(scratch);
 | 
				
			||||||
    
 | 
					    String_u16 name_16 = string_u16_from_string_u8(scratch, SCu8(name), StringFill_NullTerminate);
 | 
				
			||||||
    Win32_UTF16 name_16 = input_8_to_16(scratch, name);
 | 
					    HANDLE result = FindFirstFileW((LPWSTR)name_16.str, find_data);
 | 
				
			||||||
    if (name_16.success){
 | 
					 | 
				
			||||||
        result = FindFirstFileW((LPWSTR)name_16.utf16, find_data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    end_temp(temp);
 | 
					    end_temp(temp);
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal DWORD
 | 
					internal DWORD
 | 
				
			||||||
GetFileAttributes_utf8(Arena *scratch, u8 *name){
 | 
					GetFileAttributes_utf8(Arena *scratch, u8 *name){
 | 
				
			||||||
    DWORD result = 0;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    Temp_Memory temp = begin_temp(scratch);
 | 
					    Temp_Memory temp = begin_temp(scratch);
 | 
				
			||||||
    
 | 
					    String_u16 name_16 = string_u16_from_string_u8(scratch, SCu8(name), StringFill_NullTerminate);
 | 
				
			||||||
    Win32_UTF16 name_16 = input_8_to_16(scratch, name);
 | 
					    DWORD result = GetFileAttributesW((LPWSTR)name_16.str);
 | 
				
			||||||
    if (name_16.success){
 | 
					 | 
				
			||||||
        result = GetFileAttributesW((LPWSTR)name_16.utf16);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    end_temp(temp);
 | 
					    end_temp(temp);
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal DWORD
 | 
					internal DWORD
 | 
				
			||||||
GetModuleFileName_utf8(Arena *scratch, HMODULE module, u8 *file_out, DWORD max){
 | 
					GetModuleFileName_utf8(Arena *scratch, HMODULE module, u8 *file_out, DWORD max){
 | 
				
			||||||
    DWORD result = 0;
 | 
					 | 
				
			||||||
    Temp_Memory temp = begin_temp(scratch);
 | 
					    Temp_Memory temp = begin_temp(scratch);
 | 
				
			||||||
    u32 file_16_max = KB(40);
 | 
					    u32 file_16_max = KB(40);
 | 
				
			||||||
    u16 *file_16 = push_array(scratch, u16, file_16_max);
 | 
					    u16 *file_16 = push_array(scratch, u16, file_16_max);
 | 
				
			||||||
    DWORD file_16_len = GetModuleFileNameW(module, (LPWSTR)file_16, file_16_max);
 | 
					    DWORD file_16_len = GetModuleFileNameW(module, (LPWSTR)file_16, file_16_max);
 | 
				
			||||||
    b32 convert_error = false;
 | 
					    String_u8 file_8 = string_u8_from_string_u16(scratch, SCu16(file_16, file_16_len), StringFill_NullTerminate);
 | 
				
			||||||
    u32 file_8_len = (u32)utf16_to_utf8_minimal_checking(file_out, max - 1, file_16, file_16_len, &convert_error);
 | 
					    DWORD result = 0;
 | 
				
			||||||
    result = file_8_len;
 | 
					    if (file_8.size + 1 <= max){
 | 
				
			||||||
    if (convert_error || file_8_len >= max){
 | 
					        block_copy(file_out, file_8.str, file_8.size + 1);
 | 
				
			||||||
        result = 0;
 | 
					        result = (DWORD)file_8.size;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    end_temp(temp);
 | 
					    end_temp(temp);
 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
| 
						 | 
					@ -141,24 +92,12 @@ GetModuleFileName_utf8(Arena *scratch, HMODULE module, u8 *file_out, DWORD max){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal BOOL
 | 
					internal BOOL
 | 
				
			||||||
CreateProcess_utf8(Arena *scratch, u8 *app_name, u8 *command, LPSECURITY_ATTRIBUTES security, LPSECURITY_ATTRIBUTES thread, BOOL inherit_handles, DWORD creation, LPVOID environment, u8 *curdir, LPSTARTUPINFO startup, LPPROCESS_INFORMATION process){
 | 
					CreateProcess_utf8(Arena *scratch, u8 *app_name, u8 *command, LPSECURITY_ATTRIBUTES security, LPSECURITY_ATTRIBUTES thread, BOOL inherit_handles, DWORD creation, LPVOID environment, u8 *curdir, LPSTARTUPINFO startup, LPPROCESS_INFORMATION process){
 | 
				
			||||||
    BOOL result = false;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    Temp_Memory temp = begin_temp(scratch);
 | 
					    Temp_Memory temp = begin_temp(scratch);
 | 
				
			||||||
    
 | 
					    String_u16 app_name_16 = string_u16_from_string_u8(scratch, SCu8(app_name), StringFill_NullTerminate);
 | 
				
			||||||
    Win32_UTF16 app_name_16 = input_8_to_16(scratch, app_name);
 | 
					    String_u16 command_16 = string_u16_from_string_u8(scratch, SCu8(command), StringFill_NullTerminate);
 | 
				
			||||||
    
 | 
					    String_u16 curdir_16 = string_u16_from_string_u8(scratch, SCu8(curdir), StringFill_NullTerminate);
 | 
				
			||||||
    if (app_name_16.success){
 | 
					    BOOL result = CreateProcessW((LPWSTR)app_name_16.str, (LPWSTR)command_16.str, security, thread, inherit_handles, creation, environment, (LPWSTR)curdir_16.str, startup, process);
 | 
				
			||||||
        Win32_UTF16 command_16 = input_8_to_16(scratch, command);
 | 
					 | 
				
			||||||
        if (command_16.success){
 | 
					 | 
				
			||||||
            Win32_UTF16 curdir_16 = input_8_to_16(scratch, curdir);
 | 
					 | 
				
			||||||
            if (curdir_16.success){
 | 
					 | 
				
			||||||
                result = CreateProcessW((LPWSTR)app_name_16.utf16, (LPWSTR)command_16.utf16, security, thread, inherit_handles, creation, environment, (LPWSTR)curdir_16.utf16, startup, process);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    end_temp(temp);
 | 
					    end_temp(temp);
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,16 +110,19 @@ GetCurrentDirectory_utf8(Arena *scratch, DWORD max, u8 *buffer){
 | 
				
			||||||
        u32 buffer_16_max = KB(40);
 | 
					        u32 buffer_16_max = KB(40);
 | 
				
			||||||
        u16 *buffer_16 = push_array(scratch, u16, buffer_16_max);
 | 
					        u16 *buffer_16 = push_array(scratch, u16, buffer_16_max);
 | 
				
			||||||
        DWORD buffer_16_len = GetCurrentDirectoryW(buffer_16_max, (LPWSTR)buffer_16);
 | 
					        DWORD buffer_16_len = GetCurrentDirectoryW(buffer_16_max, (LPWSTR)buffer_16);
 | 
				
			||||||
        b32 error = false;
 | 
					        String_u8 curdir_8 = string_u8_from_string_u16(scratch, SCu16(buffer_16, buffer_16_len), StringFill_NullTerminate);
 | 
				
			||||||
        u32 buffer_8_len = (u32)utf16_to_utf8_minimal_checking(buffer, max-1, buffer_16, buffer_16_len, &error);
 | 
					        if (curdir_8.size + 1 <= max){
 | 
				
			||||||
        if (buffer_8_len < max && !error){
 | 
					            block_copy(buffer, curdir_8.str, curdir_8.size + 1);
 | 
				
			||||||
            buffer[buffer_8_len] = 0;
 | 
					            result = (DWORD)curdir_8.size;
 | 
				
			||||||
            result = buffer_8_len;
 | 
					        }
 | 
				
			||||||
 | 
					        else{
 | 
				
			||||||
 | 
					            result = (DWORD)curdir_8.size + 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        end_temp(temp);
 | 
					        end_temp(temp);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else{
 | 
					    else{
 | 
				
			||||||
        result = GetCurrentDirectoryW(0, 0);
 | 
					        result = GetCurrentDirectoryW(0, 0);
 | 
				
			||||||
 | 
					        result *= 2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
| 
						 | 
					@ -188,39 +130,28 @@ GetCurrentDirectory_utf8(Arena *scratch, DWORD max, u8 *buffer){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal int
 | 
					internal int
 | 
				
			||||||
MessageBox_utf8(Arena *scratch, HWND owner, u8 *text, u8 *caption, UINT type){
 | 
					MessageBox_utf8(Arena *scratch, HWND owner, u8 *text, u8 *caption, UINT type){
 | 
				
			||||||
    int result = 0;
 | 
					 | 
				
			||||||
    Temp_Memory temp = begin_temp(scratch);
 | 
					    Temp_Memory temp = begin_temp(scratch);
 | 
				
			||||||
    Win32_UTF16 text_16 = input_8_to_16(scratch, text);
 | 
					    String_u16 text_16 = string_u16_from_string_u8(scratch, SCu8(text), StringFill_NullTerminate);
 | 
				
			||||||
    if (text_16.success){
 | 
					    String_u16 caption_16 = string_u16_from_string_u8(scratch, SCu8(caption), StringFill_NullTerminate);
 | 
				
			||||||
        Win32_UTF16 caption_16 = input_8_to_16(scratch, caption);
 | 
					    int result = MessageBoxW(owner, (LPWSTR)text_16.str, (LPWSTR)caption_16.str, type);
 | 
				
			||||||
        if (caption_16.success){
 | 
					 | 
				
			||||||
            result = MessageBoxW(owner, (LPWSTR)text_16.utf16, (LPWSTR)caption_16.utf16, type);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    end_temp(temp);
 | 
					    end_temp(temp);
 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal BOOL
 | 
					internal BOOL
 | 
				
			||||||
SetWindowText_utf8(Arena *scratch, HWND window, u8 *string){
 | 
					SetWindowText_utf8(Arena *scratch, HWND window, u8 *string){
 | 
				
			||||||
    BOOL result = FALSE;
 | 
					 | 
				
			||||||
    Temp_Memory temp = begin_temp(scratch);
 | 
					    Temp_Memory temp = begin_temp(scratch);
 | 
				
			||||||
    Win32_UTF16 string_16 = input_8_to_16(scratch, string);
 | 
					    String_u16 string_16 = string_u16_from_string_u8(scratch, SCu8(string), StringFill_NullTerminate);
 | 
				
			||||||
    if (string_16.success){
 | 
					    BOOL result = SetWindowTextW(window, (LPWSTR)string_16.str);
 | 
				
			||||||
        result = SetWindowTextW(window, (LPWSTR)string_16.utf16);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    end_temp(temp);
 | 
					    end_temp(temp);
 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal BOOL
 | 
					internal BOOL
 | 
				
			||||||
GetFileAttributesEx_utf8String(Arena *scratch, String_Const_u8 file_name, GET_FILEEX_INFO_LEVELS info_level_id, LPVOID file_info){
 | 
					GetFileAttributesEx_utf8String(Arena *scratch, String_Const_u8 file_name, GET_FILEEX_INFO_LEVELS info_level_id, LPVOID file_info){
 | 
				
			||||||
    BOOL result = FALSE;
 | 
					 | 
				
			||||||
    Temp_Memory temp = begin_temp(scratch);
 | 
					    Temp_Memory temp = begin_temp(scratch);
 | 
				
			||||||
    Win32_UTF16 string_16 = input_8_to_16(scratch, file_name);
 | 
					    String_u16 string_16 = string_u16_from_string_u8(scratch, file_name, StringFill_NullTerminate);
 | 
				
			||||||
    if (string_16.success){
 | 
					    BOOL result = GetFileAttributesExW((LPWSTR)string_16.str, info_level_id, file_info);
 | 
				
			||||||
        result = GetFileAttributesExW((LPWSTR)string_16.utf16, info_level_id, file_info);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    end_temp(temp);
 | 
					    end_temp(temp);
 | 
				
			||||||
    return(result);
 | 
					    return(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,16 +42,6 @@ SetWindowText_utf8(Arena *scratch, HWND window, u8 *string);
 | 
				
			||||||
internal BOOL
 | 
					internal BOOL
 | 
				
			||||||
GetFileAttributesEx_utf8String(Arena *scratch, String_Const_u8 file_name, GET_FILEEX_INFO_LEVELS info_level_id, LPVOID file_info);
 | 
					GetFileAttributesEx_utf8String(Arena *scratch, String_Const_u8 file_name, GET_FILEEX_INFO_LEVELS info_level_id, LPVOID file_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// For implementation
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Win32_UTF16{
 | 
					 | 
				
			||||||
    b32 success;
 | 
					 | 
				
			||||||
    u32 utf8_len;
 | 
					 | 
				
			||||||
    u32 utf16_max;
 | 
					 | 
				
			||||||
    u32 utf16_len;
 | 
					 | 
				
			||||||
    u16 *utf16;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BOTTOM
 | 
					// BOTTOM
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,2 +0,0 @@
 | 
				
			||||||
*
 | 
					 | 
				
			||||||
!.gitignore
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,6 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
basewait 1
 | 
					 | 
				
			||||||
key o MDFR_CTRL
 | 
					 | 
				
			||||||
type 1 FONT_COURIER_NEW_28
 | 
					 | 
				
			||||||
key key_newline MDFR_NONE
 | 
					 | 
				
			||||||
exit
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,15 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
basewait 1
 | 
					 | 
				
			||||||
key P MDFR_CTRL
 | 
					 | 
				
			||||||
key o MDFR_CTRL
 | 
					 | 
				
			||||||
type 1 rome.txt
 | 
					 | 
				
			||||||
key key_newline MDFR_NONE
 | 
					 | 
				
			||||||
key key_page_down MDFR_CTRL
 | 
					 | 
				
			||||||
key key_newline MDFR_NONE
 | 
					 | 
				
			||||||
key key_newline MDFR_NONE
 | 
					 | 
				
			||||||
wait 20
 | 
					 | 
				
			||||||
type 0 Hello World!
 | 
					 | 
				
			||||||
wait 2
 | 
					 | 
				
			||||||
exit
 | 
					 | 
				
			||||||
key y MDFR_NONE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue