utf8 encoded buffers fully working on windows
This commit is contained in:
parent
59267a6418
commit
67f6e7b743
|
@ -19,7 +19,7 @@
|
|||
/* DOC(bool32 is an alias name to signal that an integer parameter or field is for true/false values.) */
|
||||
TYPEDEF int32_t bool32;
|
||||
|
||||
/* DOC(int_color is an alias name to signal that an integer parameter or field is for a color value, colors are specified as 24 bit integers in 3 channels: 0xRRGGBB.) */
|
||||
/* DOC(int_color is an alias name to signal that an integer parameter or field is for a color value, colors are specified as 32 bit integers (8 bit + 24 bit) with 3 channels: 0x**RRGGBB.) */
|
||||
TYPEDEF uint32_t int_color;
|
||||
|
||||
/* DOC(Buffer_ID is used to name a 4coder buffer. Each buffer has a unique id but when a buffer is closed it's id may be recycled by future, different buffers.) */
|
||||
|
|
|
@ -25,16 +25,17 @@ CUSTOM_COMMAND_SIG(write_character){
|
|||
|
||||
User_Input in = get_command_input(app);
|
||||
|
||||
char character = 0;
|
||||
uint8_t character[4];
|
||||
uint32_t length = 0;
|
||||
if (in.type == UserInputKey){
|
||||
character = to_writable_char(in.key.character);
|
||||
u32_to_utf8_unchecked(in.key.character, character, &length);
|
||||
}
|
||||
|
||||
if (character != 0){
|
||||
if (length != 0){
|
||||
Buffer_Summary buffer = get_buffer(app, view.buffer_id, access);
|
||||
int32_t pos = view.cursor.pos;
|
||||
buffer_replace_range(app, &buffer, pos, pos, &character, 1);
|
||||
view_set_cursor(app, &view, seek_pos(view.cursor.pos + 1), true);
|
||||
buffer_replace_range(app, &buffer, pos, pos, (char*)character, length);
|
||||
view_set_cursor(app, &view, seek_character_pos(view.cursor.character_pos + 1), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ inline char
|
|||
buffer_get_char(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
|
||||
char result = ' ';
|
||||
*buffer = get_buffer(app, buffer->buffer_id, AccessAll);
|
||||
if (pos >= 0 && pos < buffer->size){
|
||||
if (pos < buffer->size){
|
||||
buffer_read_range(app, buffer, pos, pos+1, &result);
|
||||
}
|
||||
return(result);
|
||||
|
|
|
@ -17,7 +17,7 @@ struct Stream_Chunk{
|
|||
int32_t start, end;
|
||||
int32_t min_start, max_end;
|
||||
bool32 add_null;
|
||||
int32_t data_size;
|
||||
uint32_t data_size;
|
||||
|
||||
char *data;
|
||||
};
|
||||
|
@ -42,7 +42,7 @@ round_up(int32_t x, int32_t b){
|
|||
|
||||
static bool32
|
||||
init_stream_chunk(Stream_Chunk *chunk, Application_Links *app, Buffer_Summary *buffer,
|
||||
int32_t pos, char *data, int32_t size){
|
||||
int32_t pos, char *data, uint32_t size){
|
||||
bool32 result = 0;
|
||||
|
||||
refresh_buffer(app, buffer);
|
||||
|
|
|
@ -41,31 +41,137 @@ typedef int32_t b32_4tech;
|
|||
// standard preamble end
|
||||
|
||||
static u32_4tech
|
||||
utf8_to_u32_unchecked(u8_4tech *buffer){
|
||||
utf8_to_u32_length_unchecked(u8_4tech *buffer, u32_4tech *length_out){
|
||||
u32_4tech result = 0;
|
||||
|
||||
if (buffer[0] <= 0x7F){
|
||||
result = (u32_4tech)buffer[0];
|
||||
*length_out = 1;
|
||||
}
|
||||
else if (buffer[0] <= 0xE0){
|
||||
result = ((u32_4tech)((buffer[0])&0x1F)) << 6;
|
||||
result |= ((u32_4tech)((buffer[1])&0x3F));
|
||||
*length_out = 2;
|
||||
}
|
||||
else if (buffer[0] <= 0xF0){
|
||||
result = ((u32_4tech)((buffer[0])&0x0F)) << 12;
|
||||
result |= ((u32_4tech)((buffer[1])&0x3F)) << 6;
|
||||
result |= ((u32_4tech)((buffer[2])&0x3F));
|
||||
*length_out = 3;
|
||||
}
|
||||
else{
|
||||
result = ((u32_4tech)((buffer[0])&0x07)) << 18;
|
||||
result |= ((u32_4tech)((buffer[1])&0x3F)) << 12;
|
||||
result |= ((u32_4tech)((buffer[2])&0x3F)) << 6;
|
||||
result |= ((u32_4tech)((buffer[3])&0x3F));
|
||||
*length_out = 4;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static u32_4tech
|
||||
utf8_to_u32_unchecked(u8_4tech *buffer){
|
||||
u32_4tech ignore;
|
||||
u32_4tech result = utf8_to_u32_length_unchecked(buffer, &ignore);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static u32_4tech
|
||||
utf8_to_u32(u8_4tech **buffer_ptr, u8_4tech *end){
|
||||
u8_4tech *buffer = *buffer_ptr;
|
||||
u32_4tech limit = (u32_4tech)(end - buffer);
|
||||
|
||||
u32_4tech 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{
|
||||
length = 4;
|
||||
}
|
||||
|
||||
for (u32_4tech i = 1; i < length; ++i){
|
||||
if ((buffer[i] & 0xC0) != 0x80){
|
||||
length = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u32_4tech result = 0;
|
||||
if (length != 0 && length <= limit){
|
||||
switch (length){
|
||||
case 1:
|
||||
{
|
||||
result = (u32_4tech)buffer[0];
|
||||
}break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
result = ((u32_4tech)((buffer[0])&0x1F)) << 6;
|
||||
result |= ((u32_4tech)((buffer[1])&0x3F));
|
||||
}break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
result = ((u32_4tech)((buffer[0])&0x0F)) << 12;
|
||||
result |= ((u32_4tech)((buffer[1])&0x3F)) << 6;
|
||||
result |= ((u32_4tech)((buffer[2])&0x3F));
|
||||
}break;
|
||||
|
||||
case 4:
|
||||
{
|
||||
result = ((u32_4tech)((buffer[0])&0x07)) << 18;
|
||||
result |= ((u32_4tech)((buffer[1])&0x3F)) << 12;
|
||||
result |= ((u32_4tech)((buffer[2])&0x3F)) << 6;
|
||||
result |= ((u32_4tech)((buffer[3])&0x3F));
|
||||
}break;
|
||||
}
|
||||
|
||||
*buffer_ptr = buffer + length;
|
||||
}
|
||||
else{
|
||||
*buffer_ptr = end;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
static void
|
||||
u32_to_utf8_unchecked(u32_4tech code_point, u8_4tech *buffer, u32_4tech *length_out){
|
||||
if (code_point <= 0x7F){
|
||||
buffer[0] = (u8_4tech)code_point;
|
||||
*length_out = 1;
|
||||
}
|
||||
else if (code_point <= 0x7FF){
|
||||
buffer[0] = (u8_4tech)(0xC0 | (code_point >> 6));
|
||||
buffer[1] = (u8_4tech)(0x80 | (code_point & 0x3F));
|
||||
*length_out = 2;
|
||||
}
|
||||
else if (code_point <= 0xFFFF){
|
||||
buffer[0] = (u8_4tech)(0xE0 | (code_point >> 12));
|
||||
buffer[1] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
|
||||
buffer[2] = (u8_4tech)(0x80 | (code_point & 0x3F));
|
||||
*length_out = 3;
|
||||
}
|
||||
else{
|
||||
code_point &= 0x001FFFFF;
|
||||
buffer[0] = (u8_4tech)(0xF0 | (code_point >> 18));
|
||||
buffer[1] = (u8_4tech)(0x80 | ((code_point >> 12) & 0x3F));
|
||||
buffer[2] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
|
||||
buffer[3] = (u8_4tech)(0x80 | (code_point & 0x3F));
|
||||
*length_out = 4;
|
||||
}
|
||||
}
|
||||
|
||||
static umem_4tech
|
||||
utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *src, umem_4tech length, b32_4tech *error){
|
||||
u8_4tech *s = src;
|
||||
|
@ -247,6 +353,22 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s
|
|||
return(needed_max);
|
||||
}
|
||||
|
||||
static void
|
||||
byte_to_ascii(u8_4tech n, u8_4tech *out){
|
||||
u8_4tech 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
|
||||
|
|
4
4ed.cpp
4
4ed.cpp
|
@ -2361,6 +2361,10 @@ App_Step_Sig(app_step){
|
|||
"If you're new to 4coder there are some tutorials at http://4coder.net/tutorials.html\n"
|
||||
"\n"
|
||||
"Newest features:\n"
|
||||
"-New support for extended ascii input.\n"
|
||||
"-Extended ascii encoded in buffers as utf8.\n"
|
||||
"\n"
|
||||
"New in alpha 4.0.16:\n"
|
||||
"-<alt 2> If the current file is a C++ code file, this opens the matching header.\n"" If the current file is a C++ header, this opens the matching code file.\n"
|
||||
"-Option to automatically save changes on build in the config file.\n"
|
||||
" This works for builds triggered by <alt m>.\n"
|
||||
|
|
|
@ -786,7 +786,7 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
if (new_value != file->settings.display_width){
|
||||
i16 font_id = file->settings.font_id;
|
||||
Render_Font *font = get_font_info(models->font_set, font_id)->font;
|
||||
file_set_display_width_and_fix_cursor(models, file, new_value, (f32)font->height, font->advance_data);
|
||||
file_set_width(models, file, new_value, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -799,7 +799,7 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
if (new_value != file->settings.minimum_base_display_width){
|
||||
i16 font_id = file->settings.font_id;
|
||||
Render_Font *font = get_font_info(models->font_set, font_id)->font;
|
||||
file_set_minimum_base_display_width_and_fix_cursor(models, file, new_value, (f32)font->height, font->advance_data);
|
||||
file_set_min_base_width(models, file, new_value, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -888,7 +888,7 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
|
||||
file_allocate_character_starts_as_needed(&models->mem.general, file);
|
||||
buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
|
||||
file_measure_wraps(models, file, (f32)font->height, font->advance_data);
|
||||
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
file_update_cursor_positions(models, file);
|
||||
}
|
||||
}break;
|
||||
|
@ -2071,12 +2071,9 @@ Set_Theme_Colors(Application_Links *app, Theme_Color *colors, int32_t count)
|
|||
/*
|
||||
DOC_PARAM(colors, The colors pointer provides an array of color structs pairing differet style tags to color codes.)
|
||||
DOC_PARAM(count, The count parameter specifies the number of Theme_Color structs in the colors array.)
|
||||
DOC
|
||||
(
|
||||
For each struct in the array, the slot in the main color pallet specified by the
|
||||
struct's tag is set to the color code in the struct. If the tag value is invalid
|
||||
no change is made to the color pallet.
|
||||
)
|
||||
DOC(
|
||||
For each struct in the array, the slot in the main color pallet specified by the struct's tag is set to the color code in the struct. If the tag value is invalid no change is made to the color pallet.)
|
||||
DOC_SEE(Theme_Color)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
Style *style = main_style(cmd->models);
|
||||
|
@ -2098,11 +2095,8 @@ Get_Theme_Colors(Application_Links *app, Theme_Color *colors, int32_t count)
|
|||
/*
|
||||
DOC_PARAM(colors, an array of color structs listing style tags to get color values for)
|
||||
DOC_PARAM(count, the number of color structs in the colors array)
|
||||
DOC(
|
||||
For each struct in the array, the color field of the struct is filled with the
|
||||
color from the slot in the main color pallet specified by the tag. If the tag
|
||||
value is invalid the color is filled with black.
|
||||
)
|
||||
DOC(For each struct in the array, the color field of the struct is filled with the color from the slot in the main color pallet specified by the tag. If the tag value is invalid the color is filled with black.)
|
||||
DOC_SEE(Theme_Color)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
Style *style = main_style(cmd->models);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "4coder_lib/4coder_string.h"
|
||||
#include "4coder_lib/4coder_mem.h"
|
||||
#include "4coder_lib/4coder_table.h"
|
||||
#include "4coder_lib/4coder_utf8.h"
|
||||
#if defined(USE_DEBUG_MEMORY)
|
||||
# include "4ed_debug_mem.h"
|
||||
#endif
|
||||
|
|
|
@ -396,7 +396,8 @@ view_compute_cursor(View *view, Buffer_Seek seek, b32 return_hint){
|
|||
params.buffer = &file->state.buffer;
|
||||
params.seek = seek;
|
||||
params.font_height = (f32)font->height;
|
||||
params.adv = font->advance_data;
|
||||
params.cp_adv = font->codepoint_advance_data;
|
||||
params.byte_adv = font->byte_advance;
|
||||
params.wrap_line_index = file->state.wrap_line_index;
|
||||
params.character_starts = file->state.character_starts;
|
||||
params.virtual_white = file->settings.virtual_white;
|
||||
|
@ -1007,14 +1008,18 @@ struct Code_Wrap_State{
|
|||
b32 consume_newline;
|
||||
|
||||
Gap_Buffer_Stream stream;
|
||||
i32 size;
|
||||
i32 i;
|
||||
|
||||
f32 *adv;
|
||||
f32 *cp_adv;
|
||||
f32 byte_adv;
|
||||
f32 tab_indent_amount;
|
||||
|
||||
Buffer_Translating_State tran;
|
||||
};
|
||||
|
||||
internal void
|
||||
wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *adv){
|
||||
wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *cp_adv, f32 byte_adv){
|
||||
state->token_array = file->state.token_array;
|
||||
state->token_ptr = state->token_array.tokens;
|
||||
state->end_token = state->token_ptr + state->token_array.count;
|
||||
|
@ -1025,9 +1030,14 @@ wrap_state_init(Code_Wrap_State *state, Editing_File *file, f32 *adv){
|
|||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
i32 size = buffer_size(buffer);
|
||||
buffer_stringify_loop(&state->stream, buffer, 0, size);
|
||||
state->size = size;
|
||||
state->i = 0;
|
||||
|
||||
state->adv = adv;
|
||||
state->tab_indent_amount = adv['\t'];
|
||||
state->cp_adv = cp_adv;
|
||||
state->byte_adv = byte_adv;
|
||||
state->tab_indent_amount = cp_adv['\t'];
|
||||
|
||||
state->tran = null_buffer_translating_state;
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -1085,11 +1095,11 @@ wrap_state_consume_token(Code_Wrap_State *state, i32 fixed_end_point){
|
|||
}
|
||||
}
|
||||
|
||||
b32 skipping_whitespace = 0;
|
||||
b32 skipping_whitespace = false;
|
||||
if (i >= state->next_line_start){
|
||||
state->x = state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top];
|
||||
state->x = state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top];
|
||||
skipping_whitespace = 1;
|
||||
skipping_whitespace = true;
|
||||
}
|
||||
|
||||
// TODO(allen): exponential search this shit!
|
||||
|
@ -1111,34 +1121,49 @@ wrap_state_consume_token(Code_Wrap_State *state, i32 fixed_end_point){
|
|||
}
|
||||
|
||||
if (i == line_start){
|
||||
skipping_whitespace = 1;
|
||||
skipping_whitespace = true;
|
||||
}
|
||||
|
||||
b32 recorded_start_x = 0;
|
||||
b32 recorded_start_x = false;
|
||||
do{
|
||||
for (; i < state->stream.end; ++i){
|
||||
if (!(i < end)){
|
||||
Assert(state->tran.fill_expected == 0);
|
||||
goto doublebreak;
|
||||
}
|
||||
|
||||
u8 ch = (u8)state->stream.data[i];
|
||||
|
||||
if (ch != ' ' && ch != '\t'){
|
||||
skipping_whitespace = 0;
|
||||
}
|
||||
translating_consume_byte(&state->tran, ch, i, state->size);
|
||||
|
||||
if (!skipping_whitespace){
|
||||
if (ch == '\n'){
|
||||
for (TRANSLATION_OUTPUT(&state->tran)){
|
||||
TRANSLATION_GET_STEP(&state->tran);
|
||||
|
||||
if (state->tran.do_newline){
|
||||
state->consume_newline = 1;
|
||||
goto doublebreak;
|
||||
}
|
||||
else if(state->tran.do_number_advance || state->tran.do_codepoint_advance){
|
||||
u32 n = state->tran.step_current.value;
|
||||
f32 adv = 0;
|
||||
if (state->tran.do_codepoint_advance){
|
||||
adv = state->cp_adv[n];
|
||||
if (n != ' ' && n != '\t'){
|
||||
skipping_whitespace = false;
|
||||
}
|
||||
}
|
||||
else{
|
||||
adv = state->byte_adv;
|
||||
skipping_whitespace = false;
|
||||
}
|
||||
|
||||
if (!skipping_whitespace){
|
||||
if (!recorded_start_x){
|
||||
result.start_x = state->x;
|
||||
recorded_start_x = 1;
|
||||
}
|
||||
|
||||
state->x += state->adv[ch];
|
||||
state->x += adv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1425,7 +1450,7 @@ get_current_shift(Code_Wrap_State *wrap_state, i32 next_line_start, b32 *adjust_
|
|||
}
|
||||
|
||||
internal void
|
||||
file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv){
|
||||
file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *cp_adv, f32 byte_adv){
|
||||
General_Memory *general = &models->mem.general;
|
||||
Partition *part = &models->mem.part;
|
||||
|
||||
|
@ -1438,7 +1463,8 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
|
|||
Buffer_Measure_Wrap_Params params;
|
||||
params.buffer = &file->state.buffer;
|
||||
params.wrap_line_index = file->state.wrap_line_index;
|
||||
params.adv = adv;
|
||||
params.cp_adv = cp_adv;
|
||||
params.byte_adv = byte_adv;
|
||||
params.virtual_white = file->settings.virtual_white;
|
||||
|
||||
f32 width = (f32)file->settings.display_width;
|
||||
|
@ -1468,8 +1494,9 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
|
|||
Wrap_Indent_Pair *wrap_indent_marks = 0;
|
||||
Potential_Wrap_Indent_Pair *potential_marks = 0;
|
||||
i32 max_wrap_indent_mark = 0;
|
||||
|
||||
if (params.virtual_white && file->state.tokens_complete && !file->state.still_lexing){
|
||||
wrap_state_init(&wrap_state, file, adv);
|
||||
wrap_state_init(&wrap_state, file, cp_adv, byte_adv);
|
||||
use_tokens = 1;
|
||||
|
||||
potential_marks = push_array(part, Potential_Wrap_Indent_Pair, floor32(width));
|
||||
|
@ -1521,7 +1548,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
|
|||
word_stage = 1;
|
||||
}
|
||||
else{
|
||||
f32 adv = params.adv[ch];
|
||||
f32 adv = params.cp_adv[ch];
|
||||
x += adv;
|
||||
self_x += adv;
|
||||
if (self_x > width){
|
||||
|
@ -1648,7 +1675,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
|
|||
goto doublebreak_stage1;
|
||||
}
|
||||
|
||||
f32 adv = params.adv[ch];
|
||||
f32 adv = params.cp_adv[ch];
|
||||
x += adv;
|
||||
if (!first_word && x > current_width){
|
||||
emit_comment_position = 1;
|
||||
|
@ -1674,7 +1701,7 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
|
|||
goto doublebreak_stage2;
|
||||
}
|
||||
|
||||
f32 adv = params.adv[ch];
|
||||
f32 adv = params.cp_adv[ch];
|
||||
x += adv;
|
||||
}
|
||||
still_looping = buffer_stringify_next(&stream);
|
||||
|
@ -1881,21 +1908,21 @@ file_measure_wraps(Models *models, Editing_File *file, f32 font_height, f32 *adv
|
|||
}
|
||||
|
||||
internal void
|
||||
file_measure_wraps_and_fix_cursor(Models *models, Editing_File *file, f32 font_height, f32 *adv){
|
||||
file_measure_wraps(models, file, font_height, adv);
|
||||
file_measure_wraps_and_fix_cursor(Models *models, Editing_File *file, f32 font_height, f32 *cp_adv, f32 byte_adv){
|
||||
file_measure_wraps(models, file, font_height, cp_adv, byte_adv);
|
||||
file_update_cursor_positions(models, file);
|
||||
}
|
||||
|
||||
internal void
|
||||
file_set_display_width_and_fix_cursor(Models *models, Editing_File *file, i32 display_width, f32 font_height, f32 *adv){
|
||||
file_set_width(Models *models, Editing_File *file, i32 display_width, f32 font_height, f32 *cp_adv, f32 byte_adv){
|
||||
file->settings.display_width = display_width;
|
||||
file_measure_wraps_and_fix_cursor(models, file, font_height, adv);
|
||||
file_measure_wraps_and_fix_cursor(models, file, font_height, cp_adv, byte_adv);
|
||||
}
|
||||
|
||||
internal void
|
||||
file_set_minimum_base_display_width_and_fix_cursor(Models *models, Editing_File *file, i32 minimum_base_display_width, f32 font_height, f32 *adv){
|
||||
file_set_min_base_width(Models *models, Editing_File *file, i32 minimum_base_display_width, f32 font_height, f32 *cp_adv, f32 byte_adv){
|
||||
file->settings.minimum_base_display_width = minimum_base_display_width;
|
||||
file_measure_wraps_and_fix_cursor(models, file, font_height, adv);
|
||||
file_measure_wraps_and_fix_cursor(models, file, font_height, cp_adv, byte_adv);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1944,7 +1971,7 @@ file_create_from_string(System_Functions *system, Models *models, Editing_File *
|
|||
file->settings.font_id = font_id;
|
||||
Render_Font *font = get_font_info(font_set, font_id)->font;
|
||||
|
||||
file_measure_wraps(models, file, (f32)font->height, font->advance_data);
|
||||
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
|
||||
file->settings.read_only = read_only;
|
||||
if (!read_only){
|
||||
|
@ -3215,7 +3242,7 @@ file_do_single_edit(System_Functions *system, Models *models, Editing_File *file
|
|||
(f32)file->settings.display_width);
|
||||
#endif
|
||||
|
||||
file_measure_wraps(models, file, (f32)font->height, font->advance_data);
|
||||
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
|
||||
// NOTE(allen): cursor fixing
|
||||
Cursor_Fix_Descriptor desc = {};
|
||||
|
@ -3330,16 +3357,14 @@ file_do_batch_edit(System_Functions *system, Models *models, Editing_File *file,
|
|||
buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
|
||||
|
||||
Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font;
|
||||
file_measure_wraps(models, file, (f32)font->height, font->advance_data);
|
||||
file_measure_wraps(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
|
||||
// NOTE(allen): cursor fixing
|
||||
{
|
||||
Cursor_Fix_Descriptor desc = {};
|
||||
Cursor_Fix_Descriptor desc = {0};
|
||||
desc.is_batch = 1;
|
||||
desc.batch = batch;
|
||||
desc.batch_size = batch_size;
|
||||
file_edit_cursor_fix(system, models, file, layout, desc);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -3697,7 +3722,7 @@ internal void
|
|||
file_set_font(Models *models, Editing_File *file, i16 font_id){
|
||||
file->settings.font_id = font_id;
|
||||
Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font;
|
||||
file_measure_wraps_and_fix_cursor(models, file, (f32)font->height, font->advance_data);
|
||||
file_measure_wraps_and_fix_cursor(models, file, (f32)font->height, font->codepoint_advance_data, font->byte_advance);
|
||||
|
||||
Editing_Layout *layout = &models->layout;
|
||||
for (View_Iter iter = file_view_iter_init(layout, file, 0);
|
||||
|
@ -5966,7 +5991,6 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
|
|||
|
||||
i16 font_id = file->settings.font_id;
|
||||
Render_Font *font = get_font_info(models->font_set, font_id)->font;
|
||||
float *advance_data = font->advance_data;
|
||||
|
||||
f32 scroll_x = view->edit_pos->scroll.scroll_x;
|
||||
f32 scroll_y = view->edit_pos->scroll.scroll_y;
|
||||
|
@ -6005,7 +6029,8 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
|
|||
params.start_cursor = render_cursor;
|
||||
params.wrapped = wrapped;
|
||||
params.font_height = (f32)line_height;
|
||||
params.adv = advance_data;
|
||||
params.cp_adv = font->codepoint_advance_data;
|
||||
params.byte_adv = font->byte_advance;
|
||||
params.virtual_white = file->settings.virtual_white;
|
||||
params.wrap_slashes = file->settings.wrap_indicator;
|
||||
|
||||
|
@ -6162,8 +6187,7 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
|
|||
draw_rectangle_outline(target, char_rect, mark_color);
|
||||
}
|
||||
if (item->glyphid != 0){
|
||||
font_draw_glyph(target, font_id, (u8)item->glyphid,
|
||||
item->x0, item->y0, char_color);
|
||||
font_draw_glyph(target, font_id, (u8)item->glyphid, item->x0, item->y0, char_color);
|
||||
}
|
||||
prev_ind = ind;
|
||||
}
|
||||
|
@ -6194,8 +6218,7 @@ draw_text_field(Render_Target *target, View *view, i16 font_id,
|
|||
}
|
||||
|
||||
internal void
|
||||
draw_text_with_cursor(Render_Target *target, View *view, i16 font_id,
|
||||
i32_Rect rect, String s, i32 pos){
|
||||
draw_text_with_cursor(Render_Target *target, View *view, i16 font_id, i32_Rect rect, String s, i32 pos){
|
||||
Models *models = view->persistent.models;
|
||||
Style *style = main_style(models);
|
||||
|
||||
|
@ -6222,8 +6245,9 @@ draw_text_with_cursor(Render_Target *target, View *view, i16 font_id,
|
|||
|
||||
x = draw_string(target, font_id, part1, floor32(x), y, text_color);
|
||||
|
||||
// TODO(allen): WHAT TO DO NOW?
|
||||
cursor_rect.x0 = floor32(x);
|
||||
cursor_rect.x1 = floor32(x) + ceil32(font->advance_data[s.str[pos]]);
|
||||
cursor_rect.x1 = floor32(x) + ceil32(font->codepoint_advance_data[s.str[pos]]);
|
||||
cursor_rect.y0 = y;
|
||||
cursor_rect.y1 = y + view->line_height;
|
||||
draw_rectangle(target, cursor_rect, cursor_color);
|
||||
|
|
|
@ -28,7 +28,8 @@ struct Render_Font{
|
|||
b32 loaded;
|
||||
|
||||
Glyph_Data glyphs[256];
|
||||
f32 advance_data[256];
|
||||
f32 byte_advance;
|
||||
f32 codepoint_advance_data[256];
|
||||
i32 height, ascent, descent, line_skip;
|
||||
i32 advance;
|
||||
u32 tex;
|
||||
|
|
|
@ -116,9 +116,9 @@ font_predict_size(i32 pt_size){
|
|||
}
|
||||
|
||||
internal void
|
||||
font_draw_glyph_mono(Render_Target *target, i16 font_id, u8 character, f32 x, f32 y, f32 advance, u32 color){
|
||||
font_draw_glyph(Render_Target *target, i16 font_id, i32 type, u8 character, f32 x, f32 y, u32 color){
|
||||
Render_Piece_Combined piece;
|
||||
piece.header.type = piece_type_mono_glyph;
|
||||
piece.header.type = type;
|
||||
piece.glyph.pos.x = x;
|
||||
piece.glyph.pos.y = y;
|
||||
piece.glyph.color = color;
|
||||
|
@ -128,113 +128,111 @@ font_draw_glyph_mono(Render_Target *target, i16 font_id, u8 character, f32 x, f3
|
|||
font_set_use(target->partition, &target->font_set, font_id);
|
||||
}
|
||||
|
||||
inline void
|
||||
font_draw_glyph_mono(Render_Target *target, i16 font_id,
|
||||
u8 character, f32 x, f32 y, u32 color){
|
||||
f32 advance = (f32)get_font_info(&target->font_set, font_id)->advance;
|
||||
font_draw_glyph_mono(target, font_id, character, x, y, advance, color);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_draw_glyph(Render_Target *target, i16 font_id, u8 character, f32 x, f32 y, u32 color){
|
||||
Render_Piece_Combined piece;
|
||||
piece.header.type = piece_type_glyph;
|
||||
piece.glyph.pos.x = x;
|
||||
piece.glyph.pos.y = y;
|
||||
piece.glyph.color = color;
|
||||
piece.glyph.font_id = font_id;
|
||||
piece.glyph.character = character;
|
||||
target->push_piece(target, piece);
|
||||
font_set_use(target->partition, &target->font_set, font_id);
|
||||
font_draw_glyph(target, font_id, piece_type_glyph, character, x, y, color);
|
||||
}
|
||||
|
||||
internal f32
|
||||
font_string_width(Render_Target *target, i16 font_id, char *str){
|
||||
f32 x = 0;
|
||||
draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32 x_, i32 y_, u32 color){
|
||||
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
|
||||
f32 *advance_data = font->advance_data;
|
||||
f32 x = 0;
|
||||
|
||||
if (font){
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
u8 c = str[i];
|
||||
x += advance_data[c];
|
||||
f32 y = (f32)y_;
|
||||
x = (f32)x_;
|
||||
|
||||
f32 byte_advance = font->byte_advance;
|
||||
f32 *codepoint_advance_data = font->codepoint_advance_data;
|
||||
|
||||
u8 *str = (u8*)str_.str;
|
||||
u8 *str_end = str + str_.size;
|
||||
|
||||
for (;str < str_end;){
|
||||
u8 *byte = str;
|
||||
u32 codepoint = utf8_to_u32(&str, str_end);
|
||||
|
||||
b32 do_codepoint = false;
|
||||
b32 do_numbers = false;
|
||||
if (codepoint){
|
||||
if (codepoint >= ' ' && codepoint <= 0xFF && codepoint != 127){
|
||||
do_codepoint = true;
|
||||
}
|
||||
else{
|
||||
do_numbers = true;
|
||||
}
|
||||
}
|
||||
else{
|
||||
do_numbers = true;
|
||||
}
|
||||
|
||||
if (do_codepoint){
|
||||
if (color != 0){
|
||||
font_draw_glyph(target, font_id, type, (u8)codepoint, x, y, color);
|
||||
}
|
||||
x += codepoint_advance_data[codepoint];
|
||||
}
|
||||
else if (do_numbers){
|
||||
for (;byte < str; ++byte){
|
||||
u8_4tech n = *byte;
|
||||
if (color != 0){
|
||||
u8 cs[3];
|
||||
cs[0] = '\\';
|
||||
byte_to_ascii(n, cs+1);
|
||||
|
||||
f32 xx = x;
|
||||
for (u32 j = 0; j < 3; ++j){
|
||||
font_draw_glyph(target, font_id, type, cs[j], xx, y, color);
|
||||
xx += byte_advance;
|
||||
}
|
||||
}
|
||||
|
||||
x += byte_advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(x);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string(Render_Target *target, i16 font_id, String str, i32 x, i32 y, u32 color){
|
||||
f32 w = draw_string_base(target, font_id, piece_type_glyph, str, x, y, color);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string(Render_Target *target, i16 font_id, char *str, i32 x, i32 y, u32 color){
|
||||
String string = make_string_slowly(str);
|
||||
f32 w = draw_string_base(target, font_id, piece_type_glyph, string, x, y, color);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string_mono(Render_Target *target, i16 font_id, String str, i32 x, i32 y, f32 advance, u32 color){
|
||||
f32 w = draw_string_base(target, font_id, piece_type_mono_glyph, str, x, y, color);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string_mono(Render_Target *target, i16 font_id, char *str, i32 x, i32 y, f32 advance, u32 color){
|
||||
String string = make_string_slowly(str);
|
||||
f32 w = draw_string_base(target, font_id, piece_type_mono_glyph, string, x, y, color);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
font_string_width(Render_Target *target, i16 font_id, String str){
|
||||
f32 x = 0;
|
||||
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
|
||||
f32 *advance_data = font->advance_data;
|
||||
|
||||
if (font){
|
||||
for (i32 i = 0; i < str.size; ++i){
|
||||
u8 c = str.str[i];
|
||||
x += advance_data[c];
|
||||
}
|
||||
}
|
||||
|
||||
return(x);
|
||||
f32 w = draw_string_base(target, font_id, piece_type_glyph, str, 0, 0, 0);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string(Render_Target *target, i16 font_id,
|
||||
char *str, i32 x_, i32 y, u32 color){
|
||||
f32 x = (f32)x_;
|
||||
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
|
||||
f32 *advance_data = font->advance_data;
|
||||
|
||||
if (font){
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
u8 c = str[i];
|
||||
font_draw_glyph(target, font_id, c, x, (f32)y, color);
|
||||
x += advance_data[c];
|
||||
}
|
||||
}
|
||||
|
||||
return(x);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string_mono(Render_Target *target, i16 font_id, char *str, f32 x, f32 y, f32 advance, u32 color){
|
||||
for (i32 i = 0; str[i]; ++i){
|
||||
u8 c = str[i];
|
||||
font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
|
||||
x += advance;
|
||||
}
|
||||
|
||||
return(x);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string(Render_Target *target, i16 font_id, String str, i32 x_, i32 y, u32 color){
|
||||
f32 x = (f32)x_;
|
||||
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
|
||||
f32 *advance_data = font->advance_data;
|
||||
|
||||
if (font){
|
||||
for (i32 i = 0; i < str.size; ++i){
|
||||
u8 c = str.str[i];
|
||||
font_draw_glyph(target, font_id, c, x, (f32)y, color);
|
||||
x += advance_data[c];
|
||||
}
|
||||
}
|
||||
|
||||
return(x);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string_mono(Render_Target *target, i16 font_id, String str, f32 x, f32 y, f32 advance, u32 color){
|
||||
for (i32 i = 0; i < str.size; ++i){
|
||||
u8 c = str.str[i] % 128;
|
||||
font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
|
||||
x += advance;
|
||||
}
|
||||
|
||||
return(x);
|
||||
font_string_width(Render_Target *target, i16 font_id, char *str){
|
||||
String string = make_string_slowly(str);
|
||||
f32 w = draw_string_base(target, font_id, piece_type_glyph, string, 0, 0, 0);
|
||||
return(w);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
BIN
4ed_site.ctm
BIN
4ed_site.ctm
Binary file not shown.
|
@ -544,6 +544,7 @@ launch_rendering(Render_Target *target){
|
|||
|
||||
#undef ExtractStruct
|
||||
|
||||
#if 0
|
||||
internal void*
|
||||
part_alloc(i32 size, void *context){
|
||||
Partition *part = (Partition*)context;
|
||||
|
@ -552,8 +553,7 @@ part_alloc(i32 size, void *context){
|
|||
}
|
||||
|
||||
internal void
|
||||
part_free(void *ptr, void *context){
|
||||
}
|
||||
part_free(void *ptr, void *context){}
|
||||
|
||||
#define STBTT_malloc part_alloc
|
||||
#define STBTT_free part_free
|
||||
|
@ -561,34 +561,28 @@ part_free(void *ptr, void *context){
|
|||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "stb_truetype.h"
|
||||
|
||||
internal i32
|
||||
stb_font_load(Partition *part,
|
||||
Render_Font *font_out,
|
||||
char *filename_untranslated,
|
||||
i32 pt_size,
|
||||
i32 tab_width,
|
||||
i32 oversample,
|
||||
b32 store_texture){
|
||||
internal b32
|
||||
stb_font_load(Partition *part, Render_Font *font_out, char *filename_untranslated, i32 pt_size, i32 tab_width, i32 oversample, b32 store_texture){
|
||||
|
||||
char space_[1024];
|
||||
String filename = make_fixed_width_string(space_);
|
||||
b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated);
|
||||
if (!translate_success) return 0;
|
||||
|
||||
i32 result = 1;
|
||||
b32 result = true;
|
||||
|
||||
stbtt_packedchar chardata[256];
|
||||
|
||||
File_Data file = sysshared_load_file(filename.str);
|
||||
|
||||
if (!file.data){
|
||||
result = 0;
|
||||
result = false;
|
||||
}
|
||||
|
||||
else{
|
||||
stbtt_fontinfo font;
|
||||
if (!stbtt_InitFont(&font, (u8*)file.data, 0)){
|
||||
result = 0;
|
||||
result = false;
|
||||
}
|
||||
else{
|
||||
memset(font_out, 0, sizeof(*font_out));
|
||||
|
@ -620,19 +614,16 @@ stb_font_load(Partition *part,
|
|||
/////////////////////////////////////////////////////////////////
|
||||
stbtt_pack_context spc;
|
||||
|
||||
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height,
|
||||
tex_width, 1, part)){
|
||||
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, part)){
|
||||
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
||||
if (!stbtt_PackFontRange(&spc, (u8*)file.data, 0,
|
||||
STBTT_POINT_SIZE((f32)pt_size),
|
||||
0, 128, chardata)){
|
||||
result = 0;
|
||||
if (!stbtt_PackFontRange(&spc, (u8*)file.data, 0, STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){
|
||||
result = false;
|
||||
}
|
||||
|
||||
stbtt_PackEnd(&spc);
|
||||
}
|
||||
else{
|
||||
result = 0;
|
||||
result = false;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -694,6 +685,7 @@ stb_font_load(Partition *part,
|
|||
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
// NOTE(allen): Thanks to insofaras. This is copy-pasted from some work he originally did to get free type working on Linux.
|
||||
|
||||
|
@ -826,11 +818,11 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
|
|||
|
||||
// TODO(allen): maybe advance data should be integers for a while...
|
||||
// I require the actual values to be integers anyway... hmm...
|
||||
rf->advance_data[i] = (f32)ceil32(face->glyph->advance.x / 64.0f);
|
||||
f32 advance = (f32)ceil32(face->glyph->advance.x / 64.0f);
|
||||
rf->codepoint_advance_data[i] = advance;
|
||||
|
||||
rf->glyphs[i].exists = 1;
|
||||
|
||||
|
||||
i32 pitch = face->glyph->bitmap.pitch;
|
||||
|
||||
// write to texture atlas
|
||||
|
@ -865,40 +857,23 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
|
|||
pen_x = ceil32(c->x1 + 1);
|
||||
}
|
||||
|
||||
// TODO(allen): advance data is still too stupid.
|
||||
// Provide an "unedited" version, then generate these
|
||||
// on the fly. Maybe later introduce a caching system or whatevs.
|
||||
f32 *adv = rf->advance_data;
|
||||
for (i32 i = 0; i < 256; ++i){
|
||||
if (i < ' ' || i == 127){
|
||||
switch (i){
|
||||
case '\n':
|
||||
adv[i] = adv[' '];
|
||||
break;
|
||||
f32 *cp_adv = rf->codepoint_advance_data;
|
||||
cp_adv['\n'] = cp_adv[' '];
|
||||
cp_adv['\r'] = cp_adv['\\'] + cp_adv['r'];
|
||||
cp_adv['\t'] = cp_adv[' ']*tab_width;
|
||||
|
||||
case '\r':
|
||||
adv[i] = adv['\\'] + adv['r'];
|
||||
break;
|
||||
f32 max_hex_advance = cp_adv['0'];
|
||||
for (u32 i = '1'; i <= '9'; ++i){
|
||||
max_hex_advance = Max(max_hex_advance, cp_adv[i]);
|
||||
}
|
||||
for (u32 i = 'a'; i <= 'f'; ++i){
|
||||
max_hex_advance = Max(max_hex_advance, cp_adv[i]);
|
||||
}
|
||||
for (u32 i = 'A'; i <= 'F'; ++i){
|
||||
max_hex_advance = Max(max_hex_advance, cp_adv[i]);
|
||||
}
|
||||
|
||||
case '\t':
|
||||
adv[i] = adv[' ']*tab_width;
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
int8_t d1 = (int8_t)(i/0x10), d2 = (int8_t)(i%0x10);
|
||||
char c1 = '0' + d1, c2 = '0' + d2;
|
||||
if (d1 >= 0xA){
|
||||
c1 = ('A' - 0xA) + d1;
|
||||
}
|
||||
if (d2 >= 0xA){
|
||||
c2 = ('A' - 0xA) + d2;
|
||||
}
|
||||
adv[i] = adv['\\'] + adv[c1] + adv[c2];
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rf->byte_advance = cp_adv['\\'] + max_hex_advance*2;
|
||||
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
|
|
|
@ -13,5 +13,7 @@ fi
|
|||
|
||||
echo "Building custom_4coders.so from $SOURCE ..."
|
||||
|
||||
SOURCE=$(readlink -f "$SOURCE")
|
||||
|
||||
g++ -I"$CODE_HOME" -Wno-write-strings -std=gnu++0x "$SOURCE" -shared -o custom_4coder.so -fPIC
|
||||
|
||||
|
|
|
@ -235,6 +235,7 @@ eol_in_place_convert_out(char *data, i32 size, i32 max, i32 *size_out){
|
|||
return(result);
|
||||
}
|
||||
|
||||
// TODO(allen): ditch this shit yo
|
||||
inline i32
|
||||
is_whitespace(char c){
|
||||
i32 result;
|
||||
|
@ -288,6 +289,203 @@ is_match_insensitive(char *a, char *b, i32 len){
|
|||
return(result);
|
||||
}
|
||||
|
||||
//
|
||||
// Translation state for turning byte streams into unicode/trash byte streams
|
||||
//
|
||||
|
||||
struct Buffer_Model_Step{
|
||||
u32 type;
|
||||
u32 value;
|
||||
i32 i;
|
||||
u32 byte_length;
|
||||
};
|
||||
|
||||
enum{
|
||||
BufferModelUnit_None,
|
||||
BufferModelUnit_Codepoint,
|
||||
BufferModelUnit_Numbers,
|
||||
};
|
||||
|
||||
struct Buffer_Translating_State{
|
||||
u8 fill_buffer[4];
|
||||
u32 fill_start_i;
|
||||
u32 fill_i;
|
||||
u32 fill_expected;
|
||||
|
||||
u32 byte_class;
|
||||
b32 emit_type;
|
||||
b32 rebuffer_current;
|
||||
b32 emit_current_as_cp;
|
||||
|
||||
Buffer_Model_Step steps[5];
|
||||
Buffer_Model_Step step_current;
|
||||
u32 step_count;
|
||||
u32 step_j;
|
||||
|
||||
u32 codepoint;
|
||||
u32 codepoint_length;
|
||||
b32 do_codepoint;
|
||||
b32 do_numbers;
|
||||
|
||||
b32 do_newline;
|
||||
b32 do_codepoint_advance;
|
||||
b32 do_number_advance;
|
||||
};
|
||||
global_const Buffer_Translating_State null_buffer_translating_state = {0};
|
||||
|
||||
internal void
|
||||
translating_consume_byte(Buffer_Translating_State *tran, u8 ch, u32 i, u32 size){
|
||||
tran->byte_class = 0;
|
||||
if ((ch >= ' ' && ch < 0x7F) || ch == '\t' || ch == '\n' || ch == '\r'){
|
||||
tran->byte_class = 1;
|
||||
}
|
||||
else if (ch < 0xC0){
|
||||
tran->byte_class = 1000;
|
||||
}
|
||||
else if (ch < 0xE0){
|
||||
tran->byte_class = 2;
|
||||
}
|
||||
else if (ch < 0xF0){
|
||||
tran->byte_class = 3;
|
||||
}
|
||||
else{
|
||||
tran->byte_class = 4;
|
||||
}
|
||||
|
||||
tran->emit_type = BufferModelUnit_None;
|
||||
tran->rebuffer_current = false;
|
||||
tran->emit_current_as_cp = false;
|
||||
if (tran->fill_expected == 0){
|
||||
tran->fill_buffer[0] = ch;
|
||||
tran->fill_start_i = i;
|
||||
tran->fill_i = 1;
|
||||
|
||||
if (tran->byte_class == 1){
|
||||
tran->emit_type = BufferModelUnit_Codepoint;
|
||||
}
|
||||
else if (tran->byte_class == 0 || tran->byte_class == 1000){
|
||||
tran->emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
else{
|
||||
tran->fill_expected = tran->byte_class;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (tran->byte_class == 1000){
|
||||
tran->fill_buffer[tran->fill_i] = ch;
|
||||
++tran->fill_i;
|
||||
|
||||
if (tran->fill_i == tran->fill_expected){
|
||||
tran->emit_type = BufferModelUnit_Codepoint;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (tran->byte_class >= 2 && tran->byte_class <= 4){
|
||||
tran->rebuffer_current = true;
|
||||
}
|
||||
else if (tran->byte_class == 1){
|
||||
tran->emit_current_as_cp = true;
|
||||
}
|
||||
else{
|
||||
tran->fill_buffer[tran->fill_i] = ch;
|
||||
++tran->fill_i;
|
||||
}
|
||||
tran->emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
}
|
||||
|
||||
if (tran->emit_type == BufferModelUnit_None && i+1 == size){
|
||||
tran->emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
|
||||
tran->codepoint = 0;
|
||||
tran->codepoint_length = 0;
|
||||
tran->do_codepoint = false;
|
||||
tran->do_numbers = false;
|
||||
if (tran->emit_type == BufferModelUnit_Codepoint){
|
||||
tran->codepoint = utf8_to_u32_length_unchecked(tran->fill_buffer, &tran->codepoint_length);
|
||||
if ((tran->codepoint >= ' ' && tran->codepoint <= 255 && tran->codepoint != 127) || tran->codepoint == '\t' || tran->codepoint == '\n' || tran->codepoint == '\r'){
|
||||
tran->do_codepoint = true;
|
||||
}
|
||||
else{
|
||||
tran->do_numbers = true;
|
||||
}
|
||||
}
|
||||
else if (tran->emit_type == BufferModelUnit_Numbers){
|
||||
tran->do_numbers = true;
|
||||
}
|
||||
|
||||
Assert((tran->do_codepoint + tran->do_numbers) <= 1);
|
||||
|
||||
tran->step_count = 0;
|
||||
if (tran->do_codepoint){
|
||||
tran->steps[0].type = 1;
|
||||
tran->steps[0].value = tran->codepoint;
|
||||
tran->steps[0].i = tran->fill_start_i;
|
||||
tran->steps[0].byte_length = tran->codepoint_length;
|
||||
tran->step_count = 1;
|
||||
}
|
||||
else if (tran->do_numbers){
|
||||
for (u32 j = 0; j < tran->fill_i; ++j){
|
||||
tran->steps[j].type = 0;
|
||||
tran->steps[j].value = tran->fill_buffer[j];
|
||||
tran->steps[j].i = tran->fill_start_i + j;
|
||||
tran->steps[j].byte_length = 1;
|
||||
}
|
||||
tran->step_count = tran->fill_i;
|
||||
}
|
||||
|
||||
if (tran->do_codepoint || tran->do_numbers){
|
||||
tran->fill_start_i = 0;
|
||||
tran->fill_i = 0;
|
||||
tran->fill_expected = 0;
|
||||
}
|
||||
|
||||
if (tran->rebuffer_current){
|
||||
Assert(tran->do_codepoint || tran->do_numbers);
|
||||
|
||||
tran->fill_buffer[0] = ch;
|
||||
tran->fill_start_i = i;
|
||||
tran->fill_i = 1;
|
||||
tran->fill_expected = tran->byte_class;
|
||||
}
|
||||
else if (tran->emit_current_as_cp){
|
||||
Assert(tran->do_codepoint || tran->do_numbers);
|
||||
|
||||
tran->steps[tran->step_count].type = 1;
|
||||
tran->steps[tran->step_count].value = ch;
|
||||
tran->steps[tran->step_count].i = i;
|
||||
tran->steps[tran->step_count].byte_length = 1;
|
||||
++tran->step_count;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
translation_step_read(Buffer_Translating_State *tran){
|
||||
tran->do_newline = false;
|
||||
tran->do_codepoint_advance = false;
|
||||
tran->do_number_advance = false;
|
||||
if (tran->step_current.type == 1){
|
||||
switch (tran->step_current.value){
|
||||
case '\n':
|
||||
{
|
||||
tran->do_newline = true;
|
||||
}break;
|
||||
|
||||
default:
|
||||
{
|
||||
tran->do_codepoint_advance = true;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
tran->do_number_advance = true;
|
||||
}
|
||||
}
|
||||
|
||||
#define TRANSLATION_OUTPUT(t) (t)->step_j = 0; (t)->step_j < (t)->step_count; ++(t)->step_j
|
||||
#define TRANSLATION_GET_STEP(t) (t)->step_current = (t)->steps[(t)->step_j]; translation_step_read(t)
|
||||
|
||||
//
|
||||
// Implementation of the gap buffer
|
||||
//
|
||||
|
@ -700,6 +898,8 @@ buffer_measure_character_starts(Gap_Buffer *buffer, i32 *character_starts, i32 m
|
|||
skipping_whitespace = 1;
|
||||
}
|
||||
|
||||
Buffer_Translating_State tran = {0};
|
||||
|
||||
stream.use_termination_character = 1;
|
||||
stream.terminator = '\n';
|
||||
if (buffer_stringify_loop(&stream, buffer, i, size)){
|
||||
|
@ -707,14 +907,20 @@ buffer_measure_character_starts(Gap_Buffer *buffer, i32 *character_starts, i32 m
|
|||
do{
|
||||
for (; i < stream.end; ++i){
|
||||
u8 ch = (u8)stream.data[i];
|
||||
if (ch == '\n'){
|
||||
|
||||
translating_consume_byte(&tran, ch, i, size);
|
||||
|
||||
for (TRANSLATION_OUTPUT(&tran)){
|
||||
TRANSLATION_GET_STEP(&tran);
|
||||
|
||||
if (tran.do_newline){
|
||||
++character_index;
|
||||
character_starts[line_index++] = character_index;
|
||||
if (virtual_white){
|
||||
skipping_whitespace = 1;
|
||||
}
|
||||
}
|
||||
else{
|
||||
else if (tran.do_codepoint_advance || tran.do_number_advance){
|
||||
if (ch != ' ' && ch != '\t'){
|
||||
skipping_whitespace = 0;
|
||||
}
|
||||
|
@ -724,6 +930,7 @@ buffer_measure_character_starts(Gap_Buffer *buffer, i32 *character_starts, i32 m
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = buffer_stringify_next(&stream);
|
||||
}while(still_looping);
|
||||
}
|
||||
|
@ -750,7 +957,8 @@ struct Buffer_Layout_Stop{
|
|||
struct Buffer_Measure_Wrap_Params{
|
||||
Gap_Buffer *buffer;
|
||||
i32 *wrap_line_index;
|
||||
f32 *adv;
|
||||
f32 *cp_adv;
|
||||
f32 byte_adv;
|
||||
b32 virtual_white;
|
||||
};
|
||||
|
||||
|
@ -773,6 +981,8 @@ struct Buffer_Measure_Wrap_State{
|
|||
|
||||
u8 ch;
|
||||
|
||||
Buffer_Translating_State tran;
|
||||
|
||||
i32 __pc__;
|
||||
};
|
||||
|
||||
|
@ -807,7 +1017,7 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
|
|||
params.wrap_line_index[S.line_index++] = 0;
|
||||
|
||||
if (params.virtual_white){
|
||||
S.skipping_whitespace = 1;
|
||||
S.skipping_whitespace = true;
|
||||
}
|
||||
|
||||
S.first_of_the_line = 1;
|
||||
|
@ -816,7 +1026,17 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
|
|||
do{
|
||||
for (; S.i < S.stream.end; ++S.i){
|
||||
S.ch = (u8)S.stream.data[S.i];
|
||||
if (S.ch == '\n'){
|
||||
|
||||
if (S.ch != ' ' && S.ch != '\t'){
|
||||
S.skipping_whitespace = false;
|
||||
}
|
||||
|
||||
translating_consume_byte(&S.tran, S.ch, S.i, S.size);
|
||||
|
||||
for (TRANSLATION_OUTPUT(&S.tran)){
|
||||
TRANSLATION_GET_STEP(&S.tran);
|
||||
|
||||
if (S.tran.do_newline){
|
||||
++S.current_wrap_index;
|
||||
params.wrap_line_index[S.line_index++] = S.current_wrap_index;
|
||||
|
||||
|
@ -835,15 +1055,17 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
|
|||
}
|
||||
S.first_of_the_line = 1;
|
||||
}
|
||||
else if (S.tran.do_number_advance || S.tran.do_codepoint_advance){
|
||||
if (!S.skipping_whitespace){
|
||||
|
||||
if (S.tran.do_codepoint_advance){
|
||||
S.current_adv = params.cp_adv[S.tran.step_current.value];
|
||||
}
|
||||
else{
|
||||
if (S.ch != ' ' && S.ch != '\t'){
|
||||
S.skipping_whitespace = 0;
|
||||
S.current_adv = params.byte_adv;
|
||||
}
|
||||
|
||||
if (!S.skipping_whitespace){
|
||||
S.current_adv = params.adv[S.ch];
|
||||
|
||||
S.did_wrap = 0;
|
||||
S.did_wrap = false;
|
||||
if (S.i >= S.wrap_unit_end){
|
||||
S_stop.status = BLStatus_NeedWrapDetermination;
|
||||
S_stop.line_index = S.line_index - 1;
|
||||
|
@ -855,7 +1077,7 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
|
|||
S.wrap_unit_end = wrap_unit_end;
|
||||
|
||||
if (do_wrap && !S.first_of_the_line){
|
||||
S.did_wrap = 1;
|
||||
S.did_wrap = true;
|
||||
++S.current_wrap_index;
|
||||
|
||||
if (params.virtual_white){
|
||||
|
@ -878,6 +1100,7 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
S.still_looping = buffer_stringify_next(&S.stream);
|
||||
}while(S.still_looping);
|
||||
}
|
||||
|
@ -970,8 +1193,7 @@ buffer_remeasure_starts(Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 li
|
|||
}
|
||||
|
||||
internal void
|
||||
buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 line_shift,
|
||||
i32 *character_starts, i32 mode, i32 virtual_whitespace){
|
||||
buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 *character_starts, i32 mode, i32 virtual_whitespace){
|
||||
assert(mode == 0);
|
||||
|
||||
i32 new_line_count = buffer->line_count;
|
||||
|
@ -989,11 +1211,10 @@ buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_e
|
|||
line_count -= line_shift;
|
||||
new_line_end += line_shift;
|
||||
|
||||
memmove(character_starts + line_end + line_shift, character_starts + line_end,
|
||||
sizeof(i32)*(line_count - line_end + 1));
|
||||
memmove(character_starts + line_end + line_shift, character_starts + line_end, sizeof(i32)*(line_count - line_end + 1));
|
||||
}
|
||||
|
||||
// Iteration data (yikes! Need better loop system)
|
||||
// Iteration data
|
||||
Gap_Buffer_Stream stream = {0};
|
||||
i32 size = buffer_size(buffer);
|
||||
i32 char_i = buffer->line_starts[line_start];
|
||||
|
@ -1009,6 +1230,9 @@ buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_e
|
|||
skipping_whitespace = 1;
|
||||
}
|
||||
|
||||
// Translation
|
||||
Buffer_Translating_State tran = {0};
|
||||
|
||||
stream.use_termination_character = 1;
|
||||
stream.terminator = '\n';
|
||||
if (buffer_stringify_loop(&stream, buffer, char_i, size)){
|
||||
|
@ -1016,7 +1240,12 @@ buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_e
|
|||
do{
|
||||
for (; char_i < stream.end; ++char_i){
|
||||
u8 ch = (u8)stream.data[char_i];
|
||||
if (ch == '\n'){
|
||||
translating_consume_byte(&tran, ch, char_i, size);
|
||||
|
||||
for (TRANSLATION_OUTPUT(&tran)){
|
||||
TRANSLATION_GET_STEP(&tran);
|
||||
|
||||
if (tran.do_newline){
|
||||
character_starts[line_i++] = last_char_start;
|
||||
++current_char_start;
|
||||
last_char_start = current_char_start;
|
||||
|
@ -1028,7 +1257,7 @@ buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_e
|
|||
goto buffer_remeasure_character_starts_end;
|
||||
}
|
||||
}
|
||||
else{
|
||||
else if (tran.do_codepoint_advance || tran.do_number_advance){
|
||||
if (ch != ' ' && ch != '\t'){
|
||||
skipping_whitespace = 0;
|
||||
}
|
||||
|
@ -1038,6 +1267,7 @@ buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_e
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = buffer_stringify_next(&stream);
|
||||
}while(still_looping);
|
||||
}
|
||||
|
@ -1275,7 +1505,8 @@ struct Buffer_Cursor_Seek_Params{
|
|||
Gap_Buffer *buffer;
|
||||
Buffer_Seek seek;
|
||||
f32 font_height;
|
||||
f32 *adv;
|
||||
f32 *cp_adv;
|
||||
f32 byte_adv;
|
||||
i32 *wrap_line_index;
|
||||
i32 *character_starts;
|
||||
b32 virtual_white;
|
||||
|
@ -1299,6 +1530,8 @@ struct Buffer_Cursor_Seek_State{
|
|||
f32 ch_width;
|
||||
u8 ch;
|
||||
|
||||
Buffer_Translating_State tran;
|
||||
|
||||
i32 __pc__;
|
||||
};
|
||||
|
||||
|
@ -1331,9 +1564,6 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
if (params.seek.pos > S.size){
|
||||
params.seek.pos = S.size;
|
||||
}
|
||||
if (params.seek.pos < 0){
|
||||
params.seek.pos = 0;
|
||||
}
|
||||
|
||||
line_index = buffer_get_line_index(params.buffer, params.seek.pos);
|
||||
}break;
|
||||
|
@ -1345,9 +1575,6 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
if (params.seek.pos > max_character){
|
||||
params.seek.pos = max_character;
|
||||
}
|
||||
if (params.seek.pos < 0){
|
||||
params.seek.pos = 0;
|
||||
}
|
||||
|
||||
line_index = buffer_get_line_index_from_character_pos(params.character_starts, params.seek.pos,
|
||||
0, params.buffer->line_count);
|
||||
|
@ -1429,7 +1656,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
double_break_vwhite:;
|
||||
}
|
||||
|
||||
// If the user just wants the hint, return that now.
|
||||
// If the caller just wants the hint, return that now.
|
||||
if (params.return_hint){
|
||||
*params.cursor_out = S.next_cursor;
|
||||
S_stop.status = BLStatus_Finished;
|
||||
|
@ -1491,12 +1718,15 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
for (; S.i < S.stream.end; ++S.i){
|
||||
S.ch = (u8)S.stream.data[S.i];
|
||||
|
||||
translating_consume_byte(&S.tran, S.ch, S.i, S.size);
|
||||
|
||||
for (TRANSLATION_OUTPUT(&S.tran)){
|
||||
TRANSLATION_GET_STEP(&S.tran);
|
||||
|
||||
S.prev_cursor = S.this_cursor;
|
||||
S.this_cursor = S.next_cursor;
|
||||
|
||||
switch (S.ch){
|
||||
case '\n':
|
||||
{
|
||||
if (S.tran.do_newline){
|
||||
++S.next_cursor.character_pos;
|
||||
++S.next_cursor.line;
|
||||
++S.next_cursor.wrap_line;
|
||||
|
@ -1514,17 +1744,21 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
|
||||
S.next_cursor.wrapped_x = line_shift;
|
||||
S.first_of_the_line = 1;
|
||||
}break;
|
||||
}
|
||||
else if (S.tran.do_number_advance || S.tran.do_codepoint_advance){
|
||||
|
||||
default:
|
||||
{
|
||||
S.ch_width = params.adv[S.ch];
|
||||
if (S.tran.do_codepoint_advance){
|
||||
S.ch_width = params.cp_adv[S.tran.step_current.value];
|
||||
}
|
||||
else{
|
||||
S.ch_width = params.byte_adv;
|
||||
}
|
||||
|
||||
if (S.i >= S.wrap_unit_end){
|
||||
if (S.tran.step_current.i >= S.wrap_unit_end){
|
||||
S_stop.status = BLStatus_NeedWrapDetermination;
|
||||
S_stop.line_index = S.next_cursor.line-1;
|
||||
S_stop.wrap_line_index = S.next_cursor.wrap_line-1;
|
||||
S_stop.pos = S.i;
|
||||
S_stop.pos = S.tran.step_current.i;
|
||||
S_stop.x = S.next_cursor.wrapped_x;
|
||||
DrYield(4, S_stop);
|
||||
|
||||
|
@ -1552,10 +1786,9 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
S.next_cursor.wrapped_x += S.ch_width;
|
||||
|
||||
S.first_of_the_line = 0;
|
||||
}break;
|
||||
}
|
||||
|
||||
++S.next_cursor.pos;
|
||||
S.next_cursor.pos += S.tran.step_current.byte_length;
|
||||
|
||||
f32 x = 0, px = 0, y = 0, py = 0;
|
||||
switch (params.seek.type){
|
||||
|
@ -1620,6 +1853,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
goto buffer_cursor_seek_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
S.still_looping = buffer_stringify_next(&S.stream);
|
||||
}while(S.still_looping);
|
||||
}
|
||||
|
@ -1697,8 +1931,8 @@ enum Buffer_Render_Flag{
|
|||
|
||||
typedef struct Buffer_Render_Item{
|
||||
i32 index;
|
||||
u16 glyphid;
|
||||
u16 flags;
|
||||
u32 glyphid;
|
||||
u32 flags;
|
||||
f32 x0, y0;
|
||||
f32 x1, y1;
|
||||
} Buffer_Render_Item;
|
||||
|
@ -1713,7 +1947,7 @@ typedef struct Render_Item_Write{
|
|||
} Render_Item_Write;
|
||||
|
||||
inline Render_Item_Write
|
||||
write_render_item(Render_Item_Write write, i32 index, u16 glyphid, u16 flags){
|
||||
write_render_item(Render_Item_Write write, i32 index, u32 glyphid, u32 flags){
|
||||
f32 ch_width = write.adv[(u8)glyphid];
|
||||
|
||||
if (write.x <= write.x_max && write.x + ch_width >= write.x_min){
|
||||
|
@ -1749,7 +1983,8 @@ struct Buffer_Render_Params{
|
|||
Full_Cursor start_cursor;
|
||||
i32 wrapped;
|
||||
f32 font_height;
|
||||
f32 *adv;
|
||||
f32 *cp_adv;
|
||||
f32 byte_adv;
|
||||
b32 virtual_white;
|
||||
i32 wrap_slashes;
|
||||
};
|
||||
|
@ -1758,6 +1993,10 @@ struct Buffer_Render_State{
|
|||
Gap_Buffer_Stream stream;
|
||||
b32 still_looping;
|
||||
i32 i;
|
||||
i32 size;
|
||||
|
||||
f32 shift_x;
|
||||
f32 shift_y;
|
||||
|
||||
f32 ch_width;
|
||||
u8 ch;
|
||||
|
@ -1770,6 +2009,8 @@ struct Buffer_Render_State{
|
|||
b32 first_of_the_line;
|
||||
i32 wrap_unit_end;
|
||||
|
||||
Buffer_Translating_State tran;
|
||||
|
||||
i32 __pc__;
|
||||
};
|
||||
|
||||
|
@ -1783,17 +2024,6 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
Buffer_Render_State S = *S_ptr;
|
||||
Buffer_Layout_Stop S_stop;
|
||||
|
||||
i32 size = buffer_size(params.buffer);
|
||||
f32 shift_x = params.port_x - params.scroll_x;
|
||||
f32 shift_y = params.port_y - params.scroll_y;
|
||||
|
||||
if (params.wrapped){
|
||||
shift_y += params.start_cursor.wrapped_y;
|
||||
}
|
||||
else{
|
||||
shift_y += params.start_cursor.unwrapped_y;
|
||||
}
|
||||
|
||||
Buffer_Render_Item *item_end = params.items + params.max;
|
||||
|
||||
switch (S.__pc__){
|
||||
|
@ -1803,6 +2033,17 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
DrCase(4);
|
||||
}
|
||||
|
||||
S.size = buffer_size(params.buffer);
|
||||
S.shift_x = params.port_x - params.scroll_x;
|
||||
S.shift_y = params.port_y - params.scroll_y;
|
||||
|
||||
if (params.wrapped){
|
||||
S.shift_y += params.start_cursor.wrapped_y;
|
||||
}
|
||||
else{
|
||||
S.shift_y += params.start_cursor.unwrapped_y;
|
||||
}
|
||||
|
||||
S.line = params.start_cursor.line - 1;
|
||||
S.wrap_line = params.start_cursor.wrap_line - 1;
|
||||
|
||||
|
@ -1814,9 +2055,9 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
}
|
||||
|
||||
S.write.item = params.items;
|
||||
S.write.x = shift_x + line_shift;
|
||||
S.write.y = shift_y;
|
||||
S.write.adv = params.adv;
|
||||
S.write.x = S.shift_x + line_shift;
|
||||
S.write.y = S.shift_y;
|
||||
S.write.adv = params.cp_adv;
|
||||
S.write.font_height = params.font_height;
|
||||
S.write.x_min = params.port_x;
|
||||
S.write.x_max = params.port_x + params.clip_w;
|
||||
|
@ -1827,18 +2068,21 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
|
||||
S.first_of_the_line = 1;
|
||||
S.i = params.start_cursor.pos;
|
||||
if (buffer_stringify_loop(&S.stream, params.buffer, S.i, size)){
|
||||
if (buffer_stringify_loop(&S.stream, params.buffer, S.i, S.size)){
|
||||
do{
|
||||
for (; S.i < S.stream.end; ++S.i){
|
||||
S.ch = (u8)S.stream.data[S.i];
|
||||
S.ch_width = params.adv[S.ch];
|
||||
translating_consume_byte(&S.tran, S.ch, S.i, S.size);
|
||||
|
||||
if (S.ch != '\n' && S.i >= S.wrap_unit_end){
|
||||
for (TRANSLATION_OUTPUT(&S.tran)){
|
||||
TRANSLATION_GET_STEP(&S.tran);
|
||||
|
||||
if (!S.tran.do_newline && S.tran.step_current.i >= S.wrap_unit_end){
|
||||
S_stop.status = BLStatus_NeedWrapDetermination;
|
||||
S_stop.line_index = S.line;
|
||||
S_stop.wrap_line_index = S.wrap_line;
|
||||
S_stop.pos = S.i;
|
||||
S_stop.x = S.write.x - shift_x;
|
||||
S_stop.pos = S.tran.step_current.i;
|
||||
S_stop.x = S.write.x - S.shift_x;
|
||||
DrYield(4, S_stop);
|
||||
|
||||
S.wrap_unit_end = wrap_unit_end;
|
||||
|
@ -1857,38 +2101,31 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
switch (params.wrap_slashes){
|
||||
case WrapIndicator_Show_After_Line:
|
||||
{
|
||||
S.write = write_render_item(S.write, S.i-1, '\\', BRFlag_Ghost_Character);
|
||||
S.write = write_render_item(S.write, S.tran.step_current.i-1, '\\', BRFlag_Ghost_Character);
|
||||
}break;
|
||||
|
||||
case WrapIndicator_Show_At_Wrap_Edge:
|
||||
{
|
||||
if (S.write.x < shift_x + params.width){
|
||||
S.write.x = shift_x + params.width;
|
||||
if (S.write.x < S.shift_x + params.width){
|
||||
S.write.x = S.shift_x + params.width;
|
||||
}
|
||||
S.write = write_render_item(S.write, S.i-1, '\\', BRFlag_Ghost_Character);
|
||||
S.write = write_render_item(S.write, S.tran.step_current.i-1, '\\', BRFlag_Ghost_Character);
|
||||
}break;
|
||||
}
|
||||
|
||||
S.write.x = shift_x + line_shift;
|
||||
S.write.x = S.shift_x + line_shift;
|
||||
S.write.y += params.font_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (S.write.y > params.height + params.port_y){
|
||||
if (S.write.y > params.height + params.port_y || S.write.item >= item_end){
|
||||
goto buffer_get_render_data_end;
|
||||
}
|
||||
|
||||
if (S.ch != ' ' && S.ch != '\t'){
|
||||
S.skipping_whitespace = 0;
|
||||
}
|
||||
|
||||
if (!S.skipping_whitespace){
|
||||
S.first_of_the_line = 0;
|
||||
switch (S.ch){
|
||||
case '\n':
|
||||
if (S.write.item < item_end){
|
||||
S.write = write_render_item(S.write, S.i, ' ', 0);
|
||||
S.first_of_the_line = false;
|
||||
if (S.tran.do_newline){
|
||||
S.write = write_render_item(S.write, S.tran.step_current.i, ' ', 0);
|
||||
|
||||
if (params.virtual_white){
|
||||
S_stop.status = BLStatus_NeedLineShift;
|
||||
|
@ -1902,61 +2139,70 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
++S.line;
|
||||
++S.wrap_line;
|
||||
|
||||
S.write.x = shift_x + line_shift;
|
||||
S.write.x = S.shift_x + line_shift;
|
||||
S.write.y += params.font_height;
|
||||
|
||||
S.first_of_the_line = 1;
|
||||
S.first_of_the_line = true;
|
||||
}
|
||||
else if (S.tran.do_codepoint_advance){
|
||||
u32 n = S.tran.step_current.value;
|
||||
if (n != ' ' && n != '\t'){
|
||||
S.skipping_whitespace = false;
|
||||
}
|
||||
break;
|
||||
|
||||
if (!S.skipping_whitespace){
|
||||
u32 I = S.tran.step_current.i;
|
||||
switch (n){
|
||||
case '\r':
|
||||
{
|
||||
S.write = write_render_item(S.write, I, '\\', BRFlag_Special_Character);
|
||||
if (S.write.item < item_end){
|
||||
S.write = write_render_item(S.write, S.i, '\\', BRFlag_Special_Character);
|
||||
|
||||
if (S.write.item < item_end){
|
||||
S.write = write_render_item(S.write, S.i, 'r', BRFlag_Special_Character);
|
||||
S.write = write_render_item(S.write, I, 'r', BRFlag_Special_Character);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}break;
|
||||
|
||||
case '\t':
|
||||
if (S.write.item < item_end){
|
||||
{
|
||||
S.ch_width = params.cp_adv['\t'];
|
||||
f32 new_x = S.write.x + S.ch_width;
|
||||
S.write = write_render_item(S.write, S.i, ' ', 0);
|
||||
S.write = write_render_item(S.write, I, ' ', 0);
|
||||
S.write.x = new_x;
|
||||
}
|
||||
break;
|
||||
}break;
|
||||
|
||||
default:
|
||||
if (S.write.item < item_end){
|
||||
if (S.ch >= ' ' && S.ch <= 256 && S.ch != 127){
|
||||
S.write = write_render_item(S.write, S.i, S.ch, 0);
|
||||
{
|
||||
S.write = write_render_item(S.write, I, n, 0);
|
||||
}break;
|
||||
}
|
||||
else{
|
||||
S.write = write_render_item(S.write, S.i, '\\', BRFlag_Special_Character);
|
||||
}
|
||||
}
|
||||
else if (S.tran.do_number_advance){
|
||||
u8 n = (u8)S.tran.step_current.value;
|
||||
u32 I = S.tran.step_current.i;
|
||||
S.skipping_whitespace = false;
|
||||
|
||||
u8 ch = S.ch;
|
||||
char C = '0' + (ch / 0x10);
|
||||
if ((ch / 0x10) > 0x9){
|
||||
C = ('A' - 0xA) + (ch / 0x10);
|
||||
}
|
||||
S.ch_width = params.byte_adv;
|
||||
f32 new_x = S.write.x + S.ch_width;
|
||||
|
||||
u8 cs[3];
|
||||
cs[0] = '\\';
|
||||
byte_to_ascii(n, cs+1);
|
||||
|
||||
if (S.write.item < item_end){
|
||||
S.write = write_render_item(S.write, S.i, C, BRFlag_Special_Character);
|
||||
}
|
||||
|
||||
ch = (ch % 0x10);
|
||||
C = '0' + ch;
|
||||
if (ch > 0x9){
|
||||
C = ('A' - 0xA) + ch;
|
||||
}
|
||||
|
||||
S.write = write_render_item(S.write, I, cs[0], BRFlag_Special_Character);
|
||||
if (S.write.item < item_end){
|
||||
S.write = write_render_item(S.write, S.i, C, BRFlag_Special_Character);
|
||||
S.write = write_render_item(S.write, I, cs[1], BRFlag_Special_Character);
|
||||
if (S.write.item < item_end){
|
||||
S.write = write_render_item(S.write, I, cs[2], BRFlag_Special_Character);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
Assert(S.write.x <= new_x);
|
||||
S.write.x = new_x;
|
||||
}
|
||||
|
||||
if (!S.skipping_whitespace && !S.tran.do_newline){
|
||||
S.first_of_the_line = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1965,9 +2211,9 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
}
|
||||
|
||||
buffer_get_render_data_end:;
|
||||
if (S.write.y <= params.height + shift_y || S.write.item == params.items){
|
||||
if (S.write.y <= params.height + S.shift_y || S.write.item == params.items){
|
||||
if (S.write.item < item_end){
|
||||
S.write = write_render_item(S.write, size, ' ', 0);
|
||||
S.write = write_render_item(S.write, S.size, ' ', 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -357,6 +357,9 @@ Sys_Set_File_List_Sig(system_set_file_list){
|
|||
if (d){
|
||||
if (canon_directory_out != 0){
|
||||
u32 length = copy_fast_unsafe_cc(canon_directory_out, directory);
|
||||
if (canon_directory_out[length-1] != '/'){
|
||||
canon_directory_out[length++] = '/';
|
||||
}
|
||||
canon_directory_out[length] = 0;
|
||||
*canon_directory_size_out = length;
|
||||
}
|
||||
|
@ -2653,11 +2656,11 @@ LinuxHandleX11Events(void)
|
|||
fputs("FIXME: XBufferOverflow from LookupString.\n", stderr);
|
||||
}
|
||||
|
||||
u16 key = utf8_to_u32_unchecked(buff);
|
||||
u16 key_no_caps = key;
|
||||
u32 key = utf8_to_u32_unchecked(buff);
|
||||
u32 key_no_caps = key;
|
||||
|
||||
if(mods[MDFR_CAPS_INDEX] && status == XLookupBoth && Event.xkey.keycode){
|
||||
u8 buff_no_caps[32] = {};
|
||||
u8 buff_no_caps[32] = {0};
|
||||
Event.xkey.state &= ~(LockMask);
|
||||
|
||||
XLookupString(
|
||||
|
@ -2669,7 +2672,7 @@ LinuxHandleX11Events(void)
|
|||
);
|
||||
|
||||
if(*buff_no_caps){
|
||||
key_no_caps = utf8_to_u16_unchecked(buff_no_caps);
|
||||
key_no_caps = utf8_to_u32_unchecked(buff_no_caps);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ TYPE: 'build-target'
|
|||
# define BIND_4CODER_TESTS(context) ((void)context)
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
static float
|
||||
|
@ -1344,6 +1345,27 @@ CUSTOM_COMMAND_SIG(write_explicit_enum_values){
|
|||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
CUSTOM_COMMAND_SIG(punishment){
|
||||
Theme_Color colors[4];
|
||||
colors[0].tag = Stag_Back;
|
||||
colors[1].tag = Stag_Margin;
|
||||
colors[2].tag = Stag_Margin_Hover;
|
||||
colors[3].tag = Stag_Margin_Active;
|
||||
get_theme_colors(app, colors, 4);
|
||||
|
||||
for (uint32_t i = 0; i < 4; ++i){
|
||||
int_color color = colors[i].color;
|
||||
uint8_t *c = (uint8_t*)(&color);
|
||||
c[0] = 0xFF - c[0];
|
||||
c[1] = 0xFF - c[1];
|
||||
c[2] = 0xFF - c[2];
|
||||
c[3] = 0xFF - c[3];
|
||||
colors[i].color = color;
|
||||
}
|
||||
|
||||
set_theme_colors(app, colors, 4);
|
||||
}
|
||||
|
||||
extern "C" int32_t
|
||||
get_bindings(void *data, int32_t size){
|
||||
Bind_Helper context_ = begin_bind_helper(data, size);
|
||||
|
@ -1370,6 +1392,9 @@ get_bindings(void *data, int32_t size){
|
|||
end_map(context);
|
||||
|
||||
begin_map(context, mapid_file);
|
||||
bind(context, 's', MDFR_CTRL, punishment);
|
||||
bind(context, 's', MDFR_ALT, save);
|
||||
|
||||
bind(context, 'k', MDFR_ALT, kill_rect);
|
||||
bind(context, ' ', MDFR_ALT | MDFR_CTRL, multi_line_edit);
|
||||
|
||||
|
|
|
@ -768,7 +768,7 @@ Sys_Set_File_List_Sig(system_set_file_list){
|
|||
if (canon_directory_out != 0){
|
||||
if (final_length+1 < canon_directory_max){
|
||||
memcpy(canon_directory_out, c_str_dir, final_length);
|
||||
if (char_is_slash(dir.str[dir.size-1]) && canon_directory_out[final_length-1] != '\\'){
|
||||
if (canon_directory_out[final_length-1] != '\\'){
|
||||
canon_directory_out[final_length++] = '\\';
|
||||
}
|
||||
canon_directory_out[final_length] = 0;
|
||||
|
|
Loading…
Reference in New Issue