This field indicates whether the Buffer_Summary describes a buffer that is open in 4coder.
diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp
index 421248a6..9c144d4d 100644
--- a/4coder_default_include.cpp
+++ b/4coder_default_include.cpp
@@ -63,13 +63,13 @@ view_open_file(Application_Links *app,
char *filename,
int32_t filename_len,
int32_t never_new){
- int32_t result = false;
+ int32_t result = 0;
if (view){
Buffer_Summary buffer = {0};
if (open_file(app, &buffer, filename, filename_len, false, never_new)){
view_set_buffer(app, view, buffer.buffer_id, 0);
- result = true;
+ result = 1;
}
}
@@ -744,8 +744,8 @@ CUSTOM_COMMAND_SIG(delete_char){
int32_t start = view.cursor.pos;
- Partial_Cursor cursor;
- buffer_compute_cursor(app, &buffer, seek_character_pos(view.cursor.character_pos+1), &cursor);
+ Full_Cursor cursor;
+ view_compute_cursor(app, &view, seek_character_pos(view.cursor.character_pos+1), &cursor);
int32_t end = cursor.pos;
if (0 <= start && start < buffer.size){
@@ -760,8 +760,8 @@ CUSTOM_COMMAND_SIG(backspace_char){
int32_t end = view.cursor.pos;
- Partial_Cursor cursor;
- buffer_compute_cursor(app, &buffer, seek_character_pos(view.cursor.character_pos-1), &cursor);
+ Full_Cursor cursor;
+ view_compute_cursor(app, &view, seek_character_pos(view.cursor.character_pos-1), &cursor);
int32_t start = cursor.pos;
if (0 < end && end <= buffer.size){
@@ -858,10 +858,7 @@ CUSTOM_COMMAND_SIG(click_set_cursor){
Mouse_State mouse = get_mouse_state(app);
float rx = 0, ry = 0;
if (get_relative_xy(&view, mouse.x, mouse.y, &rx, &ry)){
- view_set_cursor(app, &view,
- seek_xy(rx, ry, true,
- view.unwrapped_lines),
- true);
+ view_set_cursor(app, &view, seek_xy(rx, ry, 1, view.unwrapped_lines), 1);
}
}
@@ -872,10 +869,7 @@ CUSTOM_COMMAND_SIG(click_set_mark){
Mouse_State mouse = get_mouse_state(app);
float rx = 0, ry = 0;
if (get_relative_xy(&view, mouse.x, mouse.y, &rx, &ry)){
- view_set_mark(app, &view,
- seek_xy(rx, ry, true,
- view.unwrapped_lines)
- );
+ view_set_mark(app, &view, seek_xy(rx, ry, 1, view.unwrapped_lines));
}
}
@@ -887,9 +881,7 @@ move_vertical(Application_Links *app, float line_multiplier){
float new_y = get_view_y(view) + line_multiplier*view.line_height;
float x = view.preferred_x;
- view_set_cursor(app, &view,
- seek_xy(x, new_y, false, view.unwrapped_lines),
- false);
+ view_set_cursor(app, &view, seek_xy(x, new_y, 0, view.unwrapped_lines), 0);
}
CUSTOM_COMMAND_SIG(move_up){
diff --git a/4coder_types.h b/4coder_types.h
index 690012ae..72e923e3 100644
--- a/4coder_types.h
+++ b/4coder_types.h
@@ -575,8 +575,6 @@ DOC_SEE(4coder_Buffer_Positioning_System) */
struct Partial_Cursor{
/* DOC(This field contains the cursor's position in absolute byte index positioning.) */
int32_t pos;
- /* DOC(This field contains the cursor's position in apparent character index positioning.) */
- int32_t character_pos;
/* DOC(This field contains the number of the character from the beginninf of the line
where the cursor is located. This field is one based.) */
int32_t line;
diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp
index d6c46db4..49ba9110 100644
--- a/4ed_file_view.cpp
+++ b/4ed_file_view.cpp
@@ -9,6 +9,8 @@
// TOP
+#define VWHITE 1
+
internal i32
get_or_add_map_index(Models *models, i32 mapid){
i32 result;
@@ -391,17 +393,18 @@ view_compute_cursor(View *view, Buffer_Seek seek){
Render_Font *font = get_font_info(models->font_set, file->settings.font_id)->font;
Buffer_Cursor_Seek_Params params;
- params.buffer = &file->state.buffer;
- params.seek = seek;
- params.width = view_file_display_width(view);
- params.font_height = (f32)font->height;
- params.adv = font->advance_data;
- params.wraps = file->state.wraps;
- params.virtual_white = 0;
+ params.buffer = &file->state.buffer;
+ params.seek = seek;
+ params.width = view_file_display_width(view);
+ params.font_height = (f32)font->height;
+ params.adv = font->advance_data;
+ params.wraps = file->state.wraps;
+ params.character_starts = file->state.character_starts;
+ params.virtual_white = VWHITE;
Buffer_Cursor_Seek_State state = {0};
- Full_Cursor result;
- Buffer_Layout_Stop stop;
+ Full_Cursor result = {0};
+ Buffer_Layout_Stop stop = {0};
f32 edge_tolerance = 50.f;
if (edge_tolerance > params.width){
@@ -930,7 +933,7 @@ file_allocate_character_starts_as_needed(General_Memory *general, Editing_File *
internal void
file_measure_character_starts(Models *models, Editing_File *file){
file_allocate_character_starts_as_needed(&models->mem.general, file);
- buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, 1);
+ buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, VWHITE);
file_update_cursor_positions(models, file);
}
@@ -2056,7 +2059,7 @@ file_do_single_edit(System_Functions *system,
// TODO(allen): write the remeasurement version
file_allocate_character_starts_as_needed(general, file);
- buffer_measure_character_starts(buffer, file->state.character_starts, 0, 1);
+ buffer_measure_character_starts(buffer, file->state.character_starts, 0, VWHITE);
file_allocate_wraps_as_needed(general, file);
buffer_remeasure_wrap_y(buffer, line_start, line_end, line_shift,
@@ -4852,10 +4855,10 @@ draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target
params.wrapped = wrapped;
params.font_height = (f32)line_height;
params.adv = advance_data;
- params.virtual_white = 0;
+ params.virtual_white = VWHITE;
Buffer_Render_State state = {0};
- Buffer_Layout_Stop stop;
+ Buffer_Layout_Stop stop = {0};
f32 edge_tolerance = 50.f;
if (edge_tolerance > params.width){
diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp
index d3d776bb..4f55bec4 100644
--- a/buffer/4coder_buffer_abstract.cpp
+++ b/buffer/4coder_buffer_abstract.cpp
@@ -140,8 +140,14 @@ buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32
i32 line_index = 0;
i32 character_index = 0;
+ b32 skipping_whitespace = 0;
+
character_starts[line_index++] = character_index;
+ if (virtual_whitespace){
+ skipping_whitespace = 1;
+ }
+
if (buffer_stringify_loop(&stream, buffer, i, size)){
b32 still_looping = 0;
do{
@@ -150,9 +156,18 @@ buffer_measure_character_starts(Buffer_Type *buffer, i32 *character_starts, i32
if (ch == '\n'){
++character_index;
character_starts[line_index++] = character_index;
+ if (virtual_whitespace){
+ skipping_whitespace = 1;
+ }
}
else{
- ++character_index;
+ if (ch != ' ' && ch != '\t'){
+ skipping_whitespace = 0;
+ }
+
+ if (!skipping_whitespace){
+ ++character_index;
+ }
}
}
still_looping = buffer_stringify_next(&stream);
@@ -403,25 +418,54 @@ buffer_get_line_index(Buffer_Type *buffer, i32 pos){
return(result);
}
+// TODO(allen): Try to merge this with the other line start binary search.
internal_4tech i32
-buffer_get_line_index_from_wrapped_y(f32 *wraps, f32 y, f32 font_height, i32 l_bound, i32 u_bound){
- i32 start, end, i, result;
- start = l_bound;
- end = u_bound;
+buffer_get_line_index_from_character_pos(i32 *character_starts, i32 pos, i32 l_bound, i32 u_bound){
+ i32 start = l_bound, end = u_bound;
+ i32 i = 0;
+
for (;;){
- i = (start + end) / 2;
- if (wraps[i]+font_height <= y) start = i;
- else if (wraps[i] > y) end = i;
+ i = (start + end) >> 1;
+ if (character_starts[i] < pos){
+ start = i;
+ }
+ else if (character_starts[i] > pos){
+ end = i;
+ }
else{
- result = i;
+ start = i;
break;
}
- if (start >= end - 1){
- result = start;
+ assert_4tech(start < end);
+ if (start == end - 1){
break;
}
}
- return(result);
+
+ return(start);
+}
+
+internal_4tech i32
+buffer_get_line_index_from_wrapped_y(f32 *wraps, f32 y, f32 font_height, i32 l_bound, i32 u_bound){
+ i32 start = l_bound, end = u_bound;
+ i32 i = 0;
+ for (;;){
+ i = (start + end) / 2;
+ if (wraps[i]+font_height <= y){
+ start = i;
+ }
+ else if (wraps[i] > y){
+ end = i;
+ }
+ else{
+ break;
+ }
+ if (start >= end - 1){
+ i = start;
+ break;
+ }
+ }
+ return(i);
}
internal_4tech Partial_Cursor
@@ -481,6 +525,7 @@ struct Buffer_Cursor_Seek_Params{
f32 font_height;
f32 *adv;
f32 *wraps;
+ i32 *character_starts;
b32 virtual_white;
};
@@ -528,6 +573,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
S.size = buffer_size(params.buffer);
// Get cursor hint
+ i32 line_index = 0;
switch (params.seek.type){
case buffer_seek_pos:
{
@@ -538,52 +584,67 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
params.seek.pos = 0;
}
- i32 line_index = buffer_get_line_index_range(params.buffer, params.seek.pos, 0, params.buffer->line_count);
- S.cursor = make_cursor_hint(line_index, params.buffer->line_starts, params.wraps, params.font_height);
+ line_index = buffer_get_line_index(params.buffer, params.seek.pos);
}break;
case buffer_seek_character_pos:
{
- NotImplemented;
+ i32 line_count = params.buffer->line_count;
+ i32 max_character = params.character_starts[line_count] - 1;
+ 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);
}break;
case buffer_seek_line_char:
{
- i32 line_index = params.seek.line - 1;
+ line_index = params.seek.line - 1;
if (line_index >= params.buffer->line_count){
line_index = params.buffer->line_count - 1;
}
if (line_index < 0){
line_index = 0;
}
-
- S.cursor = make_cursor_hint(line_index, params.buffer->line_starts, params.wraps, params.font_height);
}break;
case buffer_seek_unwrapped_xy:
{
- i32 line_index = (i32)(params.seek.y / params.font_height);
+ line_index = (i32)(params.seek.y / params.font_height);
if (line_index >= params.buffer->line_count){
line_index = params.buffer->line_count - 1;
}
if (line_index < 0){
line_index = 0;
}
-
- S.cursor = make_cursor_hint(line_index, params.buffer->line_starts, params.wraps, params.font_height);
}break;
case buffer_seek_wrapped_xy:
{
- i32 line_index = buffer_get_line_index_from_wrapped_y(params.wraps, params.seek.y,
- params.font_height, 0, params.buffer->line_count);
-
- S.cursor = make_cursor_hint(line_index, params.buffer->line_starts, params.wraps, params.font_height);
+ line_index = buffer_get_line_index_from_wrapped_y(params.wraps, params.seek.y,
+ params.font_height, 0, params.buffer->line_count);
}break;
default: InvalidCodePath;
}
+ // Build the cursor hint
+ {
+ S.cursor.pos = params.buffer->line_starts[line_index];
+ S.cursor.character_pos = params.character_starts[line_index];
+ S.cursor.line = line_index + 1;
+ S.cursor.character = 1;
+ S.cursor.unwrapped_y = (f32)(line_index * params.font_height);
+ S.cursor.unwrapped_x = 0;
+ S.cursor.wrapped_y = params.wraps[line_index];
+ S.cursor.wrapped_x = 0;
+ }
+
// Get the initial line shift.
// Adjust the non-screen based coordinates to point to the first
// non-virtual character of the line.
@@ -674,6 +735,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
switch (S.ch){
case '\n':
{
+ ++S.cursor.character_pos;
++S.cursor.line;
S.cursor.unwrapped_y += params.font_height;
S.cursor.wrapped_y += params.font_height;
@@ -714,6 +776,14 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
goto buffer_cursor_seek_end;
}break;
+ case buffer_seek_character_pos:
+ {
+ if (S.cursor.character_pos > params.seek.pos){
+ S.cursor = S.prev_cursor;
+ goto buffer_cursor_seek_end;
+ }break;
+ }break;
+
case buffer_seek_wrapped_xy:
{
x = S.cursor.wrapped_x; px = S.prev_cursor.wrapped_x;
diff --git a/buffer/4coder_shared.cpp b/buffer/4coder_shared.cpp
index 3cc2b609..c80c3f94 100644
--- a/buffer/4coder_shared.cpp
+++ b/buffer/4coder_shared.cpp
@@ -82,21 +82,9 @@ typedef struct Buffer_Batch_State{
i32 shift_total;
} Buffer_Batch_State;
-inline_4tech Full_Cursor
-make_cursor_hint(i32 line_index, i32 *starts, f32 *wrap_ys, f32 font_height){
- Full_Cursor hint;
- hint.pos = starts[line_index];
- hint.line = line_index + 1;
- hint.character = 1;
- hint.unwrapped_y = (f32)(line_index * font_height);
- hint.unwrapped_x = 0;
- hint.wrapped_y = wrap_ys[line_index];
- hint.wrapped_x = 0;
- return(hint);
-}
-
typedef struct Cursor_With_Index{
- i32 pos, index;
+ i32 pos;
+ i32 index;
} Cursor_With_Index;
inline_4tech void
@@ -110,12 +98,9 @@ write_cursor_with_index(Cursor_With_Index *positions, i32 *count, i32 pos){
internal_4tech void
buffer_quick_sort_cursors(Cursor_With_Index *positions, i32 start, i32 pivot){
- i32 i, mid;
- i32 pivot_pos;
-
- mid = start;
- pivot_pos = positions[pivot].pos;
- for (i = mid; i < pivot; ++i){
+ i32 mid = start;
+ i32 pivot_pos = positions[pivot].pos;
+ for (i32 i = mid; i < pivot; ++i){
if (positions[i].pos < pivot_pos){
CursorSwap__(positions[mid], positions[i]);
++mid;
@@ -127,14 +112,12 @@ buffer_quick_sort_cursors(Cursor_With_Index *positions, i32 start, i32 pivot){
if (mid + 1 < pivot) buffer_quick_sort_cursors(positions, mid + 1, pivot);
}
+// TODO(allen): Rewrite this without being a dumbass.
internal_4tech void
buffer_quick_unsort_cursors(Cursor_With_Index *positions, i32 start, i32 pivot){
- i32 i, mid;
- i32 pivot_index;
-
- mid = start;
- pivot_index = positions[pivot].index;
- for (i = mid; i < pivot; ++i){
+ i32 mid = start;
+ i32 pivot_index = positions[pivot].index;
+ for (i32 i = mid; i < pivot; ++i){
if (positions[i].index < pivot_index){
CursorSwap__(positions[mid], positions[i]);
++mid;