185 lines
6.6 KiB
C++
185 lines
6.6 KiB
C++
/*
|
|
* Mr. 4th Dimention - Allen Webster
|
|
* Four Tech
|
|
*
|
|
* public domain -- no warranty is offered or implied; use this code at your own risk
|
|
*
|
|
* 08.11.2015
|
|
*
|
|
* Buffer experiment testing layer, abstract portion
|
|
*
|
|
*/
|
|
|
|
// TOP
|
|
|
|
#define Buffer_Init_Type cat_4tech(Buffer_Type, _Init)
|
|
#define Buffer_Stringify_Type cat_4tech(Buffer_Type, _Stringify_Loop)
|
|
#define Buffer_Backify_Type cat_4tech(Buffer_Type, _Backify_Loop)
|
|
|
|
void
|
|
init_buffer(Buffer_Type *buffer, File_Data file, void *scratch, int scratch_size){
|
|
memzero_4tech(*buffer);
|
|
Buffer_Init_Type init;
|
|
for (init = buffer_begin_init(buffer, file.data, file.size);
|
|
buffer_init_need_more(&init);){
|
|
int page_size = buffer_init_page_size(&init);
|
|
void *page = malloc(page_size);
|
|
buffer_init_provide_page(&init, page, page_size);
|
|
}
|
|
debug_4tech(int result =)
|
|
buffer_end_init(&init, scratch, scratch_size);
|
|
assert_4tech(result);
|
|
}
|
|
|
|
void
|
|
measure_starts_widths(Buffer_Type *buffer, float *font_widths){
|
|
if (buffer->line_max == 0){
|
|
assert_4tech(buffer->line_starts == 0);
|
|
assert_4tech(buffer->line_widths == 0);
|
|
assert_4tech(buffer->widths_max == 0);
|
|
int max = 1 << 10;
|
|
buffer->line_starts = (int*)malloc(max*sizeof(int));
|
|
buffer->line_max = max;
|
|
buffer->line_widths = (float*)malloc(max*sizeof(float));
|
|
buffer->widths_max = max;
|
|
}
|
|
assert_4tech(buffer->line_starts != 0);
|
|
assert_4tech(buffer->widths_max != 0);
|
|
assert_4tech(buffer->line_widths != 0);
|
|
|
|
Buffer_Measure_Starts state;
|
|
memzero_4tech(state);
|
|
for (;buffer_measure_starts_widths(&state, buffer, font_widths);){
|
|
int max = buffer->line_max;
|
|
int count = state.count;
|
|
int target = count + 1;
|
|
|
|
max = target*2;
|
|
int *new_lines = (int*)malloc(max*sizeof(int));
|
|
memcpy_4tech(new_lines, buffer->line_starts, count*sizeof(int));
|
|
free(buffer->line_starts);
|
|
buffer->line_starts = new_lines;
|
|
buffer->line_max = max;
|
|
|
|
float *new_widths = (float*)malloc(max*sizeof(float));
|
|
memcpy_4tech(new_widths, buffer->line_widths, count*sizeof(int));
|
|
free(buffer->line_widths);
|
|
buffer->line_widths = new_widths;
|
|
buffer->widths_max = max;
|
|
}
|
|
buffer->line_count = state.count;
|
|
buffer->widths_count = state.count;
|
|
}
|
|
|
|
void
|
|
edit(Buffer_Type *buffer, int start, int end, char *word, int len,
|
|
float *advance_data, void *scratch, int scratch_size){
|
|
int shift_amount, request_amount;
|
|
|
|
for (;buffer_replace_range(buffer, start, end, word, len, &shift_amount,
|
|
scratch, scratch_size, &request_amount);){
|
|
void *new_data = 0;
|
|
if (request_amount > 0) new_data = malloc(request_amount);
|
|
void *old_data = buffer_edit_provide_memory(buffer, new_data, request_amount);
|
|
if (old_data) free(old_data);
|
|
}
|
|
|
|
int line_start = buffer_get_line_index(buffer, start);
|
|
int line_end = buffer_get_line_index(buffer, end);
|
|
int replaced_line_count = line_end - line_start;
|
|
int new_line_count = buffer_count_newlines(buffer, start, start+len);
|
|
int line_shift = new_line_count - replaced_line_count;
|
|
|
|
{
|
|
assert_4tech(buffer->line_starts);
|
|
int count = buffer->line_count;
|
|
if (count + line_shift > buffer->line_max){
|
|
int new_max = round_up_4tech(buffer->line_max + line_shift, 1 << 10);
|
|
int *new_lines = (int*)malloc(sizeof(int)*new_max);
|
|
memcpy_4tech(new_lines, buffer->line_starts, sizeof(int)*count);
|
|
free(buffer->line_starts);
|
|
|
|
buffer->line_starts = new_lines;
|
|
buffer->line_max = new_max;
|
|
}
|
|
|
|
buffer_remeasure_starts(buffer, line_start, line_end, line_shift, shift_amount);
|
|
}
|
|
|
|
{
|
|
assert_4tech(buffer->line_widths);
|
|
if (buffer->line_count > buffer->widths_max){
|
|
int new_max = round_up_4tech(buffer->line_max, 1 << 10);
|
|
float *new_widths = (float*)malloc(sizeof(float)*new_max);
|
|
memcpy_4tech(new_widths, buffer->line_widths, sizeof(float)*buffer->widths_count);
|
|
free(buffer->line_widths);
|
|
|
|
buffer->line_widths = new_widths;
|
|
buffer->widths_max = new_max;
|
|
}
|
|
|
|
buffer_remeasure_widths(buffer, advance_data, line_start, line_end, line_shift);
|
|
}
|
|
}
|
|
|
|
void
|
|
insert_bottom(Buffer_Type *buffer, char *word, int len, float *advance_data, void *scratch, int scratch_size){
|
|
int size;
|
|
size = buffer_size(buffer);
|
|
edit(buffer, size, size, word, len, advance_data, scratch, scratch_size);
|
|
}
|
|
|
|
void
|
|
insert_top(Buffer_Type *buffer, char *word, int len, float *advance_data, void *scratch, int scratch_size){
|
|
edit(buffer, 0, 0, word, len, advance_data, scratch, scratch_size);
|
|
}
|
|
|
|
void
|
|
delete_bottom(Buffer_Type *buffer, int len, float *advance_data, void *scratch, int scratch_size){
|
|
int size;
|
|
size = buffer_size(buffer);
|
|
edit(buffer, size - len, size, 0, 0, advance_data, scratch, scratch_size);
|
|
}
|
|
|
|
void
|
|
delete_top(Buffer_Type *buffer, int len, float *advance_data, void *scratch, int scratch_size){
|
|
edit(buffer, 0, len, 0, 0, advance_data, scratch, scratch_size);
|
|
}
|
|
|
|
void
|
|
natural_edits(Buffer_Type *buffer, float *advance_data, Replay *replay, int pos, void *scratch, int scratch_size){
|
|
Edit_Step *steps = replay->replay.edits;
|
|
char *base_str = replay->replay.strings;
|
|
int edit_count = replay->replay.count;
|
|
|
|
for (int i = 0; i < edit_count; ++i){
|
|
Edit_Step step = steps[i];
|
|
|
|
if (step.child_count == 0 && step.edit.end <= buffer_size(buffer)){
|
|
edit(buffer, pos + step.edit.start, pos + step.edit.end, base_str + step.edit.str_start, step.edit.len,
|
|
advance_data, scratch, scratch_size);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
batch_edit(Buffer_Type *buffer, float *advance_data, Buffer_Edit *batch, char *str_base, int batch_size,
|
|
void *scratch, int scratch_size){
|
|
Buffer_Batch_State state;
|
|
int request_amount;
|
|
|
|
memzero_4tech(state);
|
|
for (;buffer_batch_edit_step(&state, buffer, batch, str_base, batch_size,
|
|
scratch, scratch_size, &request_amount);){
|
|
void *new_data = 0;
|
|
if (request_amount > 0) new_data = malloc(request_amount);
|
|
void *old_data = buffer_edit_provide_memory(buffer, new_data, request_amount);
|
|
if (old_data) free(old_data);
|
|
}
|
|
|
|
measure_starts_widths(buffer, advance_data);
|
|
}
|
|
|
|
// BOTTOM
|
|
|