implemented custom side auto indent

This commit is contained in:
Allen Webster 2016-09-07 20:32:31 -04:00
parent 992058578d
commit bdd893438d
10 changed files with 763 additions and 614 deletions

File diff suppressed because one or more lines are too long

556
4coder_auto_indent.cpp Normal file
View File

@ -0,0 +1,556 @@
#ifndef FCODER_AUTO_INDENT_INC
#define FCODER_AUTO_INDENT_INC
struct Hard_Start_Result{
int32_t char_pos;
int32_t indent_pos;
int32_t all_whitespace;
int32_t all_space;
};
static Hard_Start_Result
buffer_find_hard_start(Application_Links *app, Buffer_Summary *buffer, int32_t line_start, int32_t tab_width){
Hard_Start_Result result = {0};
char data_chunk[1024];
Stream_Chunk stream = {0};
char c;
tab_width -= 1;
result.all_space = 1;
result.indent_pos = 0;
result.char_pos = line_start;
stream.add_null = 1;
if (init_stream_chunk(&stream, app, buffer, line_start, data_chunk, sizeof(data_chunk))){
int32_t still_looping = 1;
do{
for (; result.char_pos < stream.end; ++result.char_pos){
c = stream.data[result.char_pos];
if (c == '\n' || c == 0){
result.all_whitespace = 1;
goto double_break;
}
if (c >= '!' && c <= '~'){
goto double_break;
}
if (c == '\t'){
result.indent_pos += tab_width;
}
if (c != ' '){
result.all_space = 0;
}
result.indent_pos += 1;
}
still_looping = forward_stream_chunk(&stream);
}while(still_looping);
}
double_break:;
return(result);
}
struct Indent_Options{
bool32 empty_blank_lines;
bool32 use_tabs;
int32_t tab_width;
};
#include "4cpp_lexer.h"
static int32_t
buffer_get_line_start(Application_Links *app, Buffer_Summary *buffer, int32_t line){
Partial_Cursor partial_cursor;
app->buffer_compute_cursor(app, buffer, seek_line_char(line, 1), &partial_cursor);
return(partial_cursor.pos);
}
static int32_t
buffer_get_line_index(Application_Links *app, Buffer_Summary *buffer, int32_t pos){
Partial_Cursor partial_cursor;
app->buffer_compute_cursor(app, buffer, seek_pos(pos), &partial_cursor);
return(partial_cursor.line);
}
static Cpp_Token*
get_first_token_at_line(Application_Links *app, Buffer_Summary *buffer, Cpp_Token_Array tokens, int32_t line){
int32_t line_start = buffer_get_line_start(app, buffer, line);
Cpp_Get_Token_Result get_token = cpp_get_token(&tokens, line_start);
if (get_token.in_whitespace){
get_token.token_index += 1;
}
Cpp_Token *result = tokens.tokens + get_token.token_index;
return(result);
}
static Cpp_Token*
seek_matching_token_backwards(Cpp_Token_Array tokens, Cpp_Token *token,
Cpp_Token_Type open_type, Cpp_Token_Type close_type){
int32_t nesting_level = 0;
if (token <= tokens.tokens){
token = tokens.tokens;
}
else{
for (; token > tokens.tokens; --token){
if (!(token->flags & CPP_TFLAG_PP_BODY)){
if (token->type == close_type){
++nesting_level;
}
else if (token->type == open_type){
if (nesting_level == 0){
break;
}
else{
--nesting_level;
}
}
}
}
}
return(token);
}
struct Indent_Parse_State{
int32_t current_indent;
int32_t previous_line_indent;
int32_t paren_nesting;
int32_t paren_anchor_indent[16];
int32_t comment_shift;
};
static int32_t
compute_this_indent(Application_Links *app, Buffer_Summary *buffer, Indent_Parse_State indent,
Cpp_Token T, Cpp_Token prev_token, int32_t line_i, int32_t tab_width){
int32_t previous_indent = indent.previous_line_indent;
int32_t this_indent = 0;
int32_t this_line_start = buffer_get_line_start(app, buffer, line_i);
int32_t next_line_start = 0;
if (line_i+1 < buffer->line_count){
next_line_start = buffer_get_line_start(app, buffer, line_i+1);
}
else{
next_line_start = buffer->size;
}
bool32 did_special_behavior = false;
if (prev_token.start <= this_line_start &&
prev_token.start + prev_token.size > this_line_start){
if (prev_token.type == CPP_TOKEN_COMMENT){
Hard_Start_Result hard_start = buffer_find_hard_start(app, buffer, this_line_start, tab_width);
if (hard_start.all_whitespace){
this_indent = previous_indent;
did_special_behavior = true;
}
else{
int32_t line_pos = hard_start.char_pos - this_line_start;
this_indent = line_pos + indent.comment_shift;
if (this_indent < 0){
this_indent = 0;
}
did_special_behavior = true;
}
}
else if (prev_token.type == CPP_TOKEN_STRING_CONSTANT){
this_indent = previous_indent;
did_special_behavior = true;
}
}
if (!did_special_behavior){
this_indent = indent.current_indent;
if (T.start < next_line_start){
if (T.flags & CPP_TFLAG_PP_DIRECTIVE){
this_indent = 0;
}
else{
switch (T.type){
case CPP_TOKEN_BRACKET_CLOSE: this_indent -= tab_width; break;
case CPP_TOKEN_BRACE_CLOSE: this_indent -= tab_width; break;
case CPP_TOKEN_BRACE_OPEN: break;
default:
if (indent.current_indent > 0){
if (!(prev_token.flags & CPP_TFLAG_PP_BODY ||
prev_token.flags & CPP_TFLAG_PP_DIRECTIVE)){
switch (prev_token.type){
case CPP_TOKEN_BRACKET_OPEN:
case CPP_TOKEN_BRACE_OPEN: case CPP_TOKEN_BRACE_CLOSE:
case CPP_TOKEN_SEMICOLON: case CPP_TOKEN_COLON:
case CPP_TOKEN_COMMA: case CPP_TOKEN_COMMENT: break;
default: this_indent += tab_width;
}
}
}
}
}
}
if (this_indent < 0) this_indent = 0;
}
if (indent.paren_nesting > 0){
if (prev_token.type != CPP_TOKEN_PARENTHESE_OPEN){
int32_t level = indent.paren_nesting-1;
if (level >= ArrayCount(indent.paren_anchor_indent)){
level = ArrayCount(indent.paren_anchor_indent)-1;
}
this_indent = indent.paren_anchor_indent[level];
}
}
return(this_indent);
}
static int32_t*
get_line_indentation_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer, Cpp_Token_Array tokens,
int32_t line_start, int32_t line_end, int32_t tab_width){
int32_t indent_mark_count = line_end - line_start;
int32_t *indent_marks = push_array(part, int32_t, indent_mark_count);
Indent_Parse_State indent = {0};
Cpp_Token *token = get_first_token_at_line(app, buffer, tokens, line_start);
if (token != tokens.tokens){
--token;
for (; token > tokens.tokens; --token){
if (!(token->flags & CPP_TFLAG_PP_BODY)){
switch(token->type){
case CPP_TOKEN_BRACE_OPEN:
case CPP_TOKEN_BRACE_CLOSE:
goto out_of_loop;
}
}
}
out_of_loop:;
}
// TODO(allen): This can maybe be it's own function now, so that we
// can do the decls in the order we want and avoid the extra binary search.
int32_t found_safe_start_position = 0;
do{
int32_t line = buffer_get_line_index(app, buffer, token->start);
int32_t start = buffer_get_line_start(app, buffer, line);
Hard_Start_Result hard_start = buffer_find_hard_start(app, buffer, start, tab_width);
indent.current_indent = hard_start.indent_pos;
Cpp_Token *start_token = get_first_token_at_line(app, buffer, tokens, line);
Cpp_Token *brace_token = token;
if (start_token->type == CPP_TOKEN_PARENTHESE_OPEN){
if (start_token == tokens.tokens){
found_safe_start_position = 1;
}
else{
token = start_token-1;
}
}
else{
int32_t close = 0;
for (token = brace_token; token > start_token; --token){
switch(token->type){
case CPP_TOKEN_PARENTHESE_CLOSE:
case CPP_TOKEN_BRACKET_CLOSE:
case CPP_TOKEN_BRACE_CLOSE:
close = token->type;
goto out_of_loop2;
}
}
out_of_loop2:;
switch (close){
case 0: token = start_token; found_safe_start_position = 1; break;
case CPP_TOKEN_PARENTHESE_CLOSE:
token = seek_matching_token_backwards(tokens, token-1,
CPP_TOKEN_PARENTHESE_OPEN,
CPP_TOKEN_PARENTHESE_CLOSE);
break;
case CPP_TOKEN_BRACKET_CLOSE:
token = seek_matching_token_backwards(tokens, token-1,
CPP_TOKEN_BRACKET_OPEN,
CPP_TOKEN_BRACKET_CLOSE);
break;
case CPP_TOKEN_BRACE_CLOSE:
token = seek_matching_token_backwards(tokens, token-1,
CPP_TOKEN_BRACE_OPEN,
CPP_TOKEN_BRACE_CLOSE);
break;
}
}
} while(found_safe_start_position == 0);
// NOTE(allen): Shift the array so that line_i can just operate in
// it's natural value range.
indent_marks -= line_start;
int32_t line_i = buffer_get_line_index(app, buffer, token->start);
if (line_i > line_start){
line_i = line_start;
}
int32_t next_line_start = buffer->size;
if (line_i+1 < buffer->line_count){
next_line_start = buffer_get_line_start(app, buffer, line_i+1);
}
switch (token->type){
case CPP_TOKEN_BRACKET_OPEN: indent.current_indent += tab_width; break;
case CPP_TOKEN_BRACE_OPEN: indent.current_indent += tab_width; break;
case CPP_TOKEN_PARENTHESE_OPEN: indent.current_indent += tab_width; break;
}
indent.previous_line_indent = indent.current_indent;
Cpp_Token T;
Cpp_Token prev_token = *token;
++token;
for (; line_i < line_end; ++token){
if (token < tokens.tokens + tokens.count){
T = *token;
}
else{
T.type = CPP_TOKEN_EOF;
T.start = buffer->size;
T.flags = 0;
}
for (; T.start >= next_line_start && line_i < line_end;){
if (line_i+1 < buffer->line_count){
next_line_start = buffer_get_line_start(app, buffer, line_i+1);
}
else{
next_line_start = buffer->size;
}
int32_t this_indent =
compute_this_indent(app, buffer, indent, T, prev_token, line_i, tab_width);
// NOTE(allen): Rebase the paren anchor if the first token
// after an open paren is on the next line.
if (indent.paren_nesting > 0){
if (prev_token.type == CPP_TOKEN_PARENTHESE_OPEN){
int32_t level = indent.paren_nesting-1;
if (level >= ArrayCount(indent.paren_anchor_indent)){
level = ArrayCount(indent.paren_anchor_indent)-1;
}
indent.paren_anchor_indent[level] = this_indent;
}
}
if (line_i >= line_start){
indent_marks[line_i] = this_indent;
}
++line_i;
indent.previous_line_indent = this_indent;
}
switch (T.type){
case CPP_TOKEN_BRACKET_OPEN: indent.current_indent += 4; break;
case CPP_TOKEN_BRACKET_CLOSE: indent.current_indent -= 4; break;
case CPP_TOKEN_BRACE_OPEN: indent.current_indent += 4; break;
case CPP_TOKEN_BRACE_CLOSE: indent.current_indent -= 4; break;
case CPP_TOKEN_COMMENT:
{
int32_t line = buffer_get_line_index(app, buffer, T.start);
int32_t start = buffer_get_line_start(app, buffer, line);
indent.comment_shift = (indent.current_indent - (T.start - start));
}break;
case CPP_TOKEN_PARENTHESE_OPEN:
if (!(T.flags & CPP_TFLAG_PP_BODY)){
if (indent.paren_nesting < ArrayCount(indent.paren_anchor_indent)){
int32_t line = buffer_get_line_index(app, buffer, T.start);
int32_t start = buffer_get_line_start(app, buffer, line);
int32_t char_pos = T.start - start;
Hard_Start_Result hard_start =
buffer_find_hard_start(app, buffer, start, tab_width);
int32_t line_pos = hard_start.char_pos - start;
indent.paren_anchor_indent[indent.paren_nesting] =
char_pos - line_pos + indent.previous_line_indent + 1;
}
++indent.paren_nesting;
}
break;
case CPP_TOKEN_PARENTHESE_CLOSE:
if (!(T.flags & CPP_TFLAG_PP_BODY)){
--indent.paren_nesting;
}
break;
}
prev_token = T;
}
// NOTE(allen): Unshift the indent_marks array so that the return value
// is the exact starting point of the array that was actually allocated.
indent_marks += line_start;
return(indent_marks);
}
struct Make_Batch_Result{
char *str_base;
int32_t str_size;
Buffer_Edit *edits;
int32_t edit_max;
int32_t edit_count;
};
static Make_Batch_Result
make_batch_from_indent_marks(Application_Links *app, Partition *part, Buffer_Summary *buffer,
int32_t line_start, int32_t line_end, int32_t *indent_marks, Indent_Options opts){
Make_Batch_Result result = {0};
int32_t edit_max = line_end - line_start;
int32_t edit_count = 0;
Buffer_Edit *edits = push_array(part, Buffer_Edit, edit_max);
char *str_base = (char*)part->base + part->pos;
int32_t str_size = 0;
// NOTE(allen): Shift the array so that line_i can just operate in
// it's natural value range.
indent_marks -= line_start;
for (int32_t line_i = line_start; line_i < line_end; ++line_i){
int32_t line_start = buffer_get_line_start(app, buffer, line_i);
Hard_Start_Result hard_start =
buffer_find_hard_start(app, buffer, line_start, opts.tab_width);
int32_t correct_indentation = indent_marks[line_i];
if (hard_start.all_whitespace && opts.empty_blank_lines) correct_indentation = 0;
if (correct_indentation == -1) correct_indentation = hard_start.indent_pos;
// TODO(allen): Only replace spaces if we are using space based indentation.
// TODO(allen): See if the first clause can just be removed because it's dumb.
if ((hard_start.all_whitespace && hard_start.char_pos > line_start) ||
!hard_start.all_space || correct_indentation != hard_start.indent_pos){
Buffer_Edit new_edit;
new_edit.str_start = str_size;
str_size += correct_indentation;
char *str = push_array(part, char, correct_indentation);
int32_t j = 0;
if (opts.use_tabs){
int32_t i = 0;
for (; i + opts.tab_width <= correct_indentation; i += opts.tab_width) str[j++] = '\t';
for (; i < correct_indentation; ++i) str[j++] = ' ';
}
else{
for (; j < correct_indentation; ++j) str[j] = ' ';
}
new_edit.len = j;
new_edit.start = line_start;
new_edit.end = hard_start.char_pos;
edits[edit_count++] = new_edit;
}
Assert(edit_count <= edit_max);
}
result.str_base = str_base;
result.str_size = str_size;
result.edits = edits;
result.edit_max = edit_max;
result.edit_count = edit_count;
return(result);
}
static bool32
buffer_auto_indent(Application_Links *app, Partition *part, Buffer_Summary *buffer,
int32_t start, int32_t end, int32_t tab_width, Auto_Indent_Flag flags)/*
DOC_PARAM(buffer, The buffer specifies the buffer in which to apply auto indentation.)
DOC_PARAM(start, This parameter specifies the absolute position of the start of the indentation range.)
DOC_PARAM(end, This parameter specifies the absolute position of the end of the indentation range.)
DOC_PARAM(tab_width, The tab_width parameter specifies how many spaces should be used for one indentation in space mode.)
DOC_PARAM(flags, This parameter specifies behaviors for the indentation.)
DOC_RETURN(This call returns non-zero when the call succeeds.)
DOC(Applies the built in auto-indentation rule to the code in the range
from start to end by inserting spaces or tabs at the beginning of the
lines. If the buffer does not have lexing enabled or the lexing job has
not completed this function will fail.)
DOC_SEE(Auto_Indent_Flag)
DOC_SEE(4coder_Buffer_Positioning_System)
*/{
Indent_Options opts = {0};
bool32 result = 0;
if (buffer->exists && buffer->tokens_are_ready){
result = 1;
opts.empty_blank_lines = (flags & AutoIndent_ClearLine);
opts.use_tabs = (flags & AutoIndent_UseTab);
opts.tab_width = tab_width;
Temp_Memory temp = begin_temp_memory(part);
// TODO(allen): Only read in the tokens in the range we need.
Cpp_Token_Array tokens;
tokens.count = app->buffer_token_count(app, buffer);
tokens.max_count = tokens.count;
tokens.tokens = push_array(part, Cpp_Token, tokens.count);
app->buffer_read_tokens(app, buffer, 0, tokens.count, tokens.tokens);
int32_t line_start = buffer_get_line_index(app, buffer, start);
int32_t line_end = buffer_get_line_index(app, buffer, end);
int32_t *indent_marks =
get_line_indentation_marks(app, part, buffer, tokens,
line_start, line_end, opts.tab_width);
Make_Batch_Result batch =
make_batch_from_indent_marks(app, part, buffer, line_start, line_end, indent_marks, opts);
if (batch.edit_count > 0){
app->buffer_batch_edit(app, buffer, batch.str_base, batch.str_size,
batch.edits, batch.edit_count, BatchEdit_PreserveTokens);
}
end_temp_memory(temp);
}
return(result);
}
static bool32
buffer_auto_indent(Application_Links *app, Buffer_Summary *buffer,
int32_t start, int32_t end, int32_t tab_width, Auto_Indent_Flag flags){
bool32 result = buffer_auto_indent(app, &global_part, buffer, start, end, tab_width, flags);
return(result);
}
#endif

View File

@ -14,7 +14,8 @@
#define BUFFER_COMPUTE_CURSOR_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Buffer_Seek seek, Partial_Cursor *cursor_out)
#define BUFFER_BATCH_EDIT_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, char *str, int32_t str_len, Buffer_Edit *edits, int32_t edit_count, Buffer_Batch_Edit_Type type)
#define BUFFER_SET_SETTING_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, Buffer_Setting_ID setting, int32_t value)
#define BUFFER_AUTO_INDENT_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, int32_t tab_width, Auto_Indent_Flag flags)
#define BUFFER_TOKEN_COUNT_SIG(n) int32_t n(Application_Links *app, Buffer_Summary *buffer)
#define BUFFER_READ_TOKENS_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, int32_t first_token, int32_t last_token, Cpp_Token *tokens_out)
#define CREATE_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, char *filename, int32_t filename_len, Buffer_Create_Flag flags)
#define SAVE_BUFFER_SIG(n) bool32 n(Application_Links *app, Buffer_Summary *buffer, char *filename, int32_t filename_len, uint32_t flags)
#define KILL_BUFFER_SIG(n) bool32 n(Application_Links *app, Buffer_Identifier buffer, View_ID view_id, Buffer_Kill_Flag flags)
@ -74,7 +75,8 @@ typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
typedef BUFFER_COMPUTE_CURSOR_SIG(Buffer_Compute_Cursor_Function);
typedef BUFFER_BATCH_EDIT_SIG(Buffer_Batch_Edit_Function);
typedef BUFFER_SET_SETTING_SIG(Buffer_Set_Setting_Function);
typedef BUFFER_AUTO_INDENT_SIG(Buffer_Auto_Indent_Function);
typedef BUFFER_TOKEN_COUNT_SIG(Buffer_Token_Count_Function);
typedef BUFFER_READ_TOKENS_SIG(Buffer_Read_Tokens_Function);
typedef CREATE_BUFFER_SIG(Create_Buffer_Function);
typedef SAVE_BUFFER_SIG(Save_Buffer_Function);
typedef KILL_BUFFER_SIG(Kill_Buffer_Function);
@ -135,7 +137,8 @@ Buffer_Replace_Range_Function *buffer_replace_range;
Buffer_Compute_Cursor_Function *buffer_compute_cursor;
Buffer_Batch_Edit_Function *buffer_batch_edit;
Buffer_Set_Setting_Function *buffer_set_setting;
Buffer_Auto_Indent_Function *buffer_auto_indent;
Buffer_Token_Count_Function *buffer_token_count;
Buffer_Read_Tokens_Function *buffer_read_tokens;
Create_Buffer_Function *create_buffer;
Save_Buffer_Function *save_buffer;
Kill_Buffer_Function *kill_buffer;
@ -203,7 +206,8 @@ app_links->buffer_replace_range = Buffer_Replace_Range;\
app_links->buffer_compute_cursor = Buffer_Compute_Cursor;\
app_links->buffer_batch_edit = Buffer_Batch_Edit;\
app_links->buffer_set_setting = Buffer_Set_Setting;\
app_links->buffer_auto_indent = Buffer_Auto_Indent;\
app_links->buffer_token_count = Buffer_Token_Count;\
app_links->buffer_read_tokens = Buffer_Read_Tokens;\
app_links->create_buffer = Create_Buffer;\
app_links->save_buffer = Save_Buffer;\
app_links->kill_buffer = Kill_Buffer;\

View File

@ -142,6 +142,7 @@ struct Stream_Chunk{
char *base_data;
int32_t start, end;
int32_t min_start, max_end;
bool32 add_null;
int32_t data_size;
char *data;
@ -175,11 +176,11 @@ refresh_view(Application_Links *app, View_Summary *view){
*view = app->get_view(app, view->view_id, AccessAll);
}
int32_t
bool32
init_stream_chunk(Stream_Chunk *chunk,
Application_Links *app, Buffer_Summary *buffer,
int32_t pos, char *data, int32_t size){
int32_t result = false;
bool32 result = false;
refresh_buffer(app, buffer);
if (pos >= 0 && pos < buffer->size && size > 0){
@ -190,8 +191,7 @@ init_stream_chunk(Stream_Chunk *chunk,
chunk->start = round_down(pos, size);
chunk->end = round_up(pos, size);
if (chunk->max_end > buffer->size
|| chunk->max_end == 0){
if (chunk->max_end > buffer->size || chunk->max_end == 0){
chunk->max_end = buffer->size;
}
@ -235,6 +235,15 @@ forward_stream_chunk(Stream_Chunk *chunk){
result = true;
}
}
else if (chunk->add_null && chunk->end + 1 < buffer->size){
chunk->start = buffer->size;
chunk->end = buffer->size + 1;
chunk->base_data[0] = 0;
chunk->data = chunk->base_data - chunk->start;
result = true;
}
return(result);
}
@ -262,6 +271,14 @@ backward_stream_chunk(Stream_Chunk *chunk){
result = true;
}
}
else if (chunk->add_null && chunk->start > -1){
chunk->start = -1;
chunk->end = 0;
chunk->base_data[0] = 0;
chunk->data = chunk->base_data - chunk->start;
}
return(result);
}
@ -887,17 +904,17 @@ move_past_lead_whitespace(Application_Links *app, View_Summary *view, Buffer_Sum
}
}
//#include "4coder_auto_indent.cpp"
#include "4coder_auto_indent.cpp"
CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){
uint32_t access = AccessOpen;
View_Summary view = app->get_active_view(app, access);
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access);
app->buffer_auto_indent(app, &buffer,
view.cursor.pos, view.cursor.pos,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
buffer_auto_indent(app, &buffer,
view.cursor.pos, view.cursor.pos,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
move_past_lead_whitespace(app, &view, &buffer);
}
@ -906,10 +923,10 @@ CUSTOM_COMMAND_SIG(auto_tab_whole_file){
View_Summary view = app->get_active_view(app, access);
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access);
app->buffer_auto_indent(app, &buffer,
0, buffer.size,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
buffer_auto_indent(app, &buffer,
0, buffer.size,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
}
CUSTOM_COMMAND_SIG(auto_tab_range){
@ -918,10 +935,10 @@ CUSTOM_COMMAND_SIG(auto_tab_range){
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access);
Range range = get_range(&view);
app->buffer_auto_indent(app, &buffer,
range.min, range.max,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
buffer_auto_indent(app, &buffer,
range.min, range.max,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
move_past_lead_whitespace(app, &view, &buffer);
}
@ -1417,10 +1434,10 @@ long_braces(Application_Links *app, char *text, int32_t size){
app->buffer_replace_range(app, &buffer, pos, pos, text, size);
app->view_set_cursor(app, &view, seek_pos(pos + 2), true);
app->buffer_auto_indent(app, &buffer,
pos, pos + size,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
buffer_auto_indent(app, &buffer,
pos, pos + size,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
move_past_lead_whitespace(app, &view, &buffer);
}
@ -1491,10 +1508,10 @@ CUSTOM_COMMAND_SIG(if0_off){
}
range = get_range(&view);
app->buffer_auto_indent(app, &buffer,
range.min, range.max,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
buffer_auto_indent(app, &buffer,
range.min, range.max,
DEF_TAB_WIDTH,
DEFAULT_INDENT_FLAGS);
move_past_lead_whitespace(app, &view, &buffer);
}
}

View File

@ -607,6 +607,11 @@ struct Buffer_Summary{
/* DOC(If this is not a null summary, this field indicates whether the buffer is set to lex tokens.) */
bool32 is_lexed;
/* DOC(If this is not a null summary, this field indicates whether the buffer has up to date tokens available.
If this field is false, it may simply mean the tokens are still being generated in a background task and will
be available later. If that is the case, is_lexed will be true to indicate that the buffer is trying to get
it's tokens up to date.) */
bool32 tokens_are_ready;
/* DOC(If this is not a null summary, this field specifies the id of the command map for this buffer.) */
int32_t map_id;
/* DOC(If this is not a null summary, this field indicates whether the buffer 'prefers' wrapped lines.) */

View File

@ -32,6 +32,16 @@ fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *wor
buffer->buffer_name = file->name.live_name.str;
buffer->is_lexed = file->settings.tokens_exist;
if (file->state.token_array.tokens &&
file->state.tokens_complete &&
!file->state.still_lexing){
buffer->tokens_are_ready = 1;
}
else{
buffer->tokens_are_ready = 0;
}
buffer->map_id = file->settings.base_map_id;
buffer->unwrapped_lines = file->settings.unwrapped_lines;
@ -752,7 +762,9 @@ Buffer_Compute_Cursor(Application_Links *app, Buffer_Summary *buffer, Buffer_See
DOC_PARAM(buffer, The buffer parameter specifies the buffer on which to run the cursor computation.)
DOC_PARAM(seek, The seek parameter specifies the target position for the seek.)
DOC_PARAM(cursor_out, On success this struct is filled with the result of the seek.)
DOC_RETURN(This call returns non-zero on success.)
DOC_RETURN(This call returns non-zero on success. This call can fail if the buffer summary provided
does not summarize an actual buffer in 4coder, or if the provided seek format is invalid. The valid
seek types are seek_pos and seek_line_char.)
DOC(Computes a Partial_Cursor for the given seek position with no side effects.
The seek position must be one of the types supported by Partial_Cursor. Those
types are absolute position and line,column position.)
@ -780,7 +792,8 @@ DOC_PARAM(str_len, This parameter specifies the length of the str string.)
DOC_PARAM(edits, This parameter provides about the source string and destination range of each edit as an array.)
DOC_PARAM(edit_count, This parameter specifies the number of Buffer_Edit structs in edits.)
DOC_PARAM(type, This prameter specifies what type of batch edit to execute.)
DOC_RETURN(This call returns non-zero if the batch edit succeeds.)
DOC_RETURN(This call returns non-zero if the batch edit succeeds. This call can fail if the provided
buffer summary does not refer to an actual buffer in 4coder.)
DOC(TODO)
DOC_SEE(Buffer_Edit)
DOC_SEE(Buffer_Batch_Edit_Type)
@ -812,9 +825,8 @@ DOC_SEE(Buffer_Batch_Edit_Type)
end_temp_memory(temp);
}
else{
result = true;
}
result = true;
}
return(result);
@ -916,43 +928,32 @@ DOC_SEE(Buffer_Setting_ID)
return(result);
}
API_EXPORT bool32
Buffer_Auto_Indent(Application_Links *app, Buffer_Summary *buffer, int32_t start, int32_t end, int32_t tab_width, Auto_Indent_Flag flags)/*
DOC_PARAM(buffer, The buffer specifies the buffer in which to apply auto indentation.)
DOC_PARAM(start, This parameter specifies the absolute position of the start of the indentation range.)
DOC_PARAM(end, This parameter specifies the absolute position of the end of the indentation range.)
DOC_PARAM(tab_width, The tab_width parameter specifies how many spaces should be used for one indentation in space mode.)
DOC_PARAM(flags, This parameter specifies behaviors for the indentation.)
DOC_RETURN(This call returns non-zero when the call succeeds.)
DOC
(
Applies the built in auto-indentation rule to the code in the range from
start to end by inserting spaces or tabs at the beginning of the lines.
If the buffer does not have lexing enabled or the lexing job has not
completed this function will fail.
)
DOC_SEE(Auto_Indent_Flag)
DOC_SEE(4coder_Buffer_Positioning_System)
*/{
API_EXPORT int32_t
Buffer_Token_Count(Application_Links *app, Buffer_Summary *buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context;
System_Functions *system = cmd->system;
Models *models = cmd->models;
Indent_Options opts = {0};
bool32 result = false;
Editing_File *file = imp_get_file(cmd, buffer);
if (file && file->state.token_array.tokens &&
file->state.tokens_complete && !file->state.still_lexing){
result = true;
int32_t count = 0;
if (file && file->state.token_array.tokens && file->state.tokens_complete){
count = file->state.token_array.count;
}
return(count);
}
API_EXPORT bool32
Buffer_Read_Tokens(Application_Links *app, Buffer_Summary *buffer, int32_t first_token, int32_t last_token, Cpp_Token *tokens_out){
Command_Data *cmd = (Command_Data*)app->cmd_context;
Editing_File *file = imp_get_file(cmd, buffer);
bool32 result = 0;
if (file && file->state.token_array.tokens && file->state.tokens_complete){
result = 1;
opts.empty_blank_lines = (flags & AutoIndent_ClearLine);
opts.use_tabs = (flags & AutoIndent_UseTab);
opts.tab_width = tab_width;
file_auto_tab_tokens(system, models, file, start, start, end, opts);
fill_buffer_summary(buffer, file, cmd);
memcpy(tokens_out, file->state.token_array.tokens + first_token,
sizeof(Cpp_Token)*(last_token - first_token));
}
return(result);

View File

@ -41,9 +41,6 @@ typedef double f64;
#define globalconst static const
inline i32
raw_ptr_dif(void *a, void *b) { return (i32)((u8*)a - (u8*)b); }
#define COMP_ID_(a,b,c,d) (d << 24) | (c << 16) | (b << 8) | a
#define COMPOSE_ID(a,b,c,d) (COMP_ID_((a),(b),(c),(d)))

View File

@ -2517,465 +2517,6 @@ file_compute_edit(Mem_Options *mem, Editing_File *file,
return(spec);
}
struct Indent_Options{
b32 empty_blank_lines;
b32 use_tabs;
i32 tab_width;
};
struct Make_Batch_Result{
char *str_base;
i32 str_size;
Buffer_Edit *edits;
i32 edit_max;
i32 edit_count;
};
internal Cpp_Token*
get_first_token_at_line(Buffer *buffer, Cpp_Token_Array tokens, i32 line){
i32 start_pos = buffer->line_starts[line];
Cpp_Get_Token_Result get_token = cpp_get_token(&tokens, start_pos);
if (get_token.in_whitespace){
get_token.token_index += 1;
}
Cpp_Token *result = tokens.tokens + get_token.token_index;
return(result);
}
internal Cpp_Token*
seek_matching_token_backwards(Cpp_Token_Array tokens, Cpp_Token *token,
Cpp_Token_Type open_type, Cpp_Token_Type close_type){
int32_t nesting_level = 0;
if (token <= tokens.tokens){
token = tokens.tokens;
}
else{
for (; token > tokens.tokens; --token){
if (!(token->flags & CPP_TFLAG_PP_BODY)){
if (token->type == close_type){
++nesting_level;
}
else if (token->type == open_type){
if (nesting_level == 0){
break;
}
else{
--nesting_level;
}
}
}
}
}
return(token);
}
struct Indent_Parse_State{
i32 current_indent;
i32 previous_line_indent;
i32 paren_nesting;
i32 paren_anchor_indent[16];
i32 comment_shift;
};
internal i32
compute_this_indent(Buffer *buffer, Indent_Parse_State indent,
Cpp_Token T, Cpp_Token prev_token, i32 line_i, i32 tab_width){
i32 previous_indent = indent.previous_line_indent;
i32 this_indent = 0;
i32 this_line_start = buffer->line_starts[line_i];
i32 next_line_start = 0;
if (line_i+1 < buffer->line_count){
next_line_start = buffer->line_starts[line_i+1];
}
else{
next_line_start = buffer_size(buffer);
}
b32 did_special_behavior = false;
if (prev_token.start <= this_line_start &&
prev_token.start + prev_token.size > this_line_start){
if (prev_token.type == CPP_TOKEN_COMMENT){
Hard_Start_Result hard_start = buffer_find_hard_start(buffer, this_line_start, tab_width);
if (hard_start.all_whitespace){
this_indent = previous_indent;
did_special_behavior = true;
}
else{
i32 line_pos = hard_start.char_pos - this_line_start;
this_indent = line_pos + indent.comment_shift;
if (this_indent < 0){
this_indent = 0;
}
did_special_behavior = true;
}
}
else if (prev_token.type == CPP_TOKEN_STRING_CONSTANT){
this_indent = previous_indent;
did_special_behavior = true;
}
}
if (!did_special_behavior){
this_indent = indent.current_indent;
if (T.start < next_line_start){
if (T.flags & CPP_TFLAG_PP_DIRECTIVE){
this_indent = 0;
}
else{
switch (T.type){
case CPP_TOKEN_BRACKET_CLOSE: this_indent -= tab_width; break;
case CPP_TOKEN_BRACE_CLOSE: this_indent -= tab_width; break;
case CPP_TOKEN_BRACE_OPEN: break;
default:
if (indent.current_indent > 0){
if (!(prev_token.flags & CPP_TFLAG_PP_BODY ||
prev_token.flags & CPP_TFLAG_PP_DIRECTIVE)){
switch (prev_token.type){
case CPP_TOKEN_BRACKET_OPEN:
case CPP_TOKEN_BRACE_OPEN: case CPP_TOKEN_BRACE_CLOSE:
case CPP_TOKEN_SEMICOLON: case CPP_TOKEN_COLON:
case CPP_TOKEN_COMMA: case CPP_TOKEN_COMMENT: break;
default: this_indent += tab_width;
}
}
}
}
}
}
if (this_indent < 0) this_indent = 0;
}
if (indent.paren_nesting > 0){
if (prev_token.type != CPP_TOKEN_PARENTHESE_OPEN){
i32 level = indent.paren_nesting-1;
if (level >= ArrayCount(indent.paren_anchor_indent)){
level = ArrayCount(indent.paren_anchor_indent)-1;
}
this_indent = indent.paren_anchor_indent[level];
}
}
return(this_indent);
}
internal i32*
get_line_indentation_marks(Partition *part, Buffer *buffer, Cpp_Token_Array tokens,
i32 line_start, i32 line_end, i32 tab_width){
i32 indent_mark_count = line_end - line_start;
i32 *indent_marks = push_array(part, i32, indent_mark_count);
Indent_Parse_State indent = {0};
Cpp_Token *token = get_first_token_at_line(buffer, tokens, line_start);
if (token != tokens.tokens){
--token;
for (; token > tokens.tokens; --token){
if (!(token->flags & CPP_TFLAG_PP_BODY)){
switch(token->type){
case CPP_TOKEN_BRACE_OPEN:
case CPP_TOKEN_BRACE_CLOSE:
goto out_of_loop;
}
}
}
out_of_loop:;
}
// TODO(allen): This can maybe be it's own function now, so that we
// can do the decls in the order we want and avoid the extra binary search.
i32 found_safe_start_position = 0;
do{
i32 line = buffer_get_line_index(buffer, token->start);
i32 start = buffer->line_starts[line];
Hard_Start_Result hard_start = buffer_find_hard_start(buffer, start, tab_width);
indent.current_indent = hard_start.indent_pos;
Cpp_Token *start_token = get_first_token_at_line(buffer, tokens, line);
Cpp_Token *brace_token = token;
if (start_token->type == CPP_TOKEN_PARENTHESE_OPEN){
if (start_token == tokens.tokens){
found_safe_start_position = 1;
}
else{
token = start_token-1;
}
}
else{
int32_t close = 0;
for (token = brace_token; token > start_token; --token){
switch(token->type){
case CPP_TOKEN_PARENTHESE_CLOSE:
case CPP_TOKEN_BRACKET_CLOSE:
case CPP_TOKEN_BRACE_CLOSE:
close = token->type;
goto out_of_loop2;
}
}
out_of_loop2:;
switch (close){
case 0: token = start_token; found_safe_start_position = 1; break;
case CPP_TOKEN_PARENTHESE_CLOSE:
token = seek_matching_token_backwards(tokens, token-1,
CPP_TOKEN_PARENTHESE_OPEN,
CPP_TOKEN_PARENTHESE_CLOSE);
break;
case CPP_TOKEN_BRACKET_CLOSE:
token = seek_matching_token_backwards(tokens, token-1,
CPP_TOKEN_BRACKET_OPEN,
CPP_TOKEN_BRACKET_CLOSE);
break;
case CPP_TOKEN_BRACE_CLOSE:
token = seek_matching_token_backwards(tokens, token-1,
CPP_TOKEN_BRACE_OPEN,
CPP_TOKEN_BRACE_CLOSE);
break;
}
}
} while(found_safe_start_position == 0);
// NOTE(allen): Shift the array so that line_i can just operate in
// it's natural value range.
indent_marks -= line_start;
i32 line_i = buffer_get_line_index(buffer, token->start);
if (line_i > line_start){
line_i = line_start;
}
i32 next_line_start = buffer_size(buffer);
if (line_i+1 < buffer->line_count){
next_line_start = buffer->line_starts[line_i+1];
}
switch (token->type){
case CPP_TOKEN_BRACKET_OPEN: indent.current_indent += tab_width; break;
case CPP_TOKEN_BRACE_OPEN: indent.current_indent += tab_width; break;
case CPP_TOKEN_PARENTHESE_OPEN: indent.current_indent += tab_width; break;
}
indent.previous_line_indent = indent.current_indent;
Cpp_Token T;
Cpp_Token prev_token = *token;
++token;
for (; line_i < line_end; ++token){
if (token < tokens.tokens + tokens.count){
T = *token;
}
else{
T.type = CPP_TOKEN_EOF;
T.start = buffer_size(buffer);
T.flags = 0;
}
for (; T.start >= next_line_start && line_i < line_end;){
if (line_i+1 < buffer->line_count){
next_line_start = buffer->line_starts[line_i+1];
}
else{
next_line_start = buffer_size(buffer);
}
i32 this_indent =
compute_this_indent(buffer, indent, T, prev_token, line_i, tab_width);
// NOTE(allen): Rebase the paren anchor if the first token
// after an open paren is on the next line.
if (indent.paren_nesting > 0){
if (prev_token.type == CPP_TOKEN_PARENTHESE_OPEN){
i32 level = indent.paren_nesting-1;
if (level >= ArrayCount(indent.paren_anchor_indent)){
level = ArrayCount(indent.paren_anchor_indent)-1;
}
indent.paren_anchor_indent[level] = this_indent;
}
}
if (line_i >= line_start){
indent_marks[line_i] = this_indent;
}
++line_i;
indent.previous_line_indent = this_indent;
}
switch (T.type){
case CPP_TOKEN_BRACKET_OPEN: indent.current_indent += 4; break;
case CPP_TOKEN_BRACKET_CLOSE: indent.current_indent -= 4; break;
case CPP_TOKEN_BRACE_OPEN: indent.current_indent += 4; break;
case CPP_TOKEN_BRACE_CLOSE: indent.current_indent -= 4; break;
case CPP_TOKEN_COMMENT:
{
i32 line = buffer_get_line_index(buffer, T.start);
i32 start = buffer->line_starts[line];
indent.comment_shift = (indent.current_indent - (T.start - start));
}break;
case CPP_TOKEN_PARENTHESE_OPEN:
if (!(T.flags & CPP_TFLAG_PP_BODY)){
if (indent.paren_nesting < ArrayCount(indent.paren_anchor_indent)){
i32 line = buffer_get_line_index(buffer, T.start);
i32 start = buffer->line_starts[line];
i32 char_pos = T.start - start;
Hard_Start_Result hard_start =
buffer_find_hard_start(buffer, start, tab_width);
i32 line_pos = hard_start.char_pos - start;
indent.paren_anchor_indent[indent.paren_nesting] =
char_pos - line_pos + indent.previous_line_indent + 1;
}
++indent.paren_nesting;
}
break;
case CPP_TOKEN_PARENTHESE_CLOSE:
if (!(T.flags & CPP_TFLAG_PP_BODY)){
--indent.paren_nesting;
}
break;
}
prev_token = T;
}
// NOTE(allen): Unshift the indent_marks array so that the return value
// is the exact starting point of the array that was actually allocated.
indent_marks += line_start;
return(indent_marks);
}
internal Make_Batch_Result
make_batch_from_indent_marks(Partition *part, Buffer *buffer, i32 line_start, i32 line_end,
i32 *indent_marks, Indent_Options opts){
Make_Batch_Result result = {0};
i32 edit_max = line_end - line_start;
i32 edit_count = 0;
Buffer_Edit *edits = push_array(part, Buffer_Edit, edit_max);
char *str_base = (char*)part->base + part->pos;
i32 str_size = 0;
// NOTE(allen): Shift the array so that line_i can just operate in
// it's natural value range.
indent_marks -= line_start;
for (i32 line_i = line_start; line_i < line_end; ++line_i){
i32 start = buffer->line_starts[line_i];
Hard_Start_Result hard_start =
buffer_find_hard_start(buffer, start, opts.tab_width);
i32 correct_indentation = indent_marks[line_i];
if (hard_start.all_whitespace && opts.empty_blank_lines) correct_indentation = 0;
if (correct_indentation == -1) correct_indentation = hard_start.indent_pos;
if ((hard_start.all_whitespace && hard_start.char_pos > start) ||
!hard_start.all_space || correct_indentation != hard_start.indent_pos){
Buffer_Edit new_edit;
new_edit.str_start = str_size;
str_size += correct_indentation;
char *str = push_array(part, char, correct_indentation);
i32 j = 0;
if (opts.use_tabs){
i32 i = 0;
for (; i + opts.tab_width <= correct_indentation; i += opts.tab_width) str[j++] = '\t';
for (; i < correct_indentation; ++i) str[j++] = ' ';
}
else{
for (; j < correct_indentation; ++j) str[j] = ' ';
}
new_edit.len = j;
new_edit.start = start;
new_edit.end = hard_start.char_pos;
edits[edit_count++] = new_edit;
}
Assert(edit_count <= edit_max);
}
result.str_base = str_base;
result.str_size = str_size;
result.edits = edits;
result.edit_max = edit_max;
result.edit_count = edit_count;
return(result);
}
internal void
file_auto_tab_tokens(System_Functions *system, Models *models,
Editing_File *file, i32 pos, i32 start, i32 end, Indent_Options opts){
#if BUFFER_EXPERIMENT_SCALPEL <= 0
Mem_Options *mem = &models->mem;
Partition *part = &mem->part;
Buffer *buffer = &file->state.buffer;
Assert(file && !file->is_dummy);
Cpp_Token_Array tokens = file->state.token_array;
Assert(tokens.tokens);
i32 line_start = buffer_get_line_index(buffer, start);
i32 line_end = buffer_get_line_index(buffer, end) + 1;
Temp_Memory temp = begin_temp_memory(part);
i32 *indent_marks =
get_line_indentation_marks(part, buffer, tokens, line_start, line_end, opts.tab_width);
Make_Batch_Result batch =
make_batch_from_indent_marks(part, buffer, line_start, line_end, indent_marks, opts);
if (batch.edit_count > 0){
Assert(buffer_batch_debug_sort_check(batch.edits, batch.edit_count));
// NOTE(allen): computing edit spec, doing batch edit
Buffer_Edit *inverse_array = push_array(part, Buffer_Edit, batch.edit_count);
Assert(inverse_array);
char *inv_str = (char*)part->base + part->pos;
Edit_Spec spec =
file_compute_edit(mem, file,
batch.edits, batch.str_base, batch.str_size,
inverse_array, inv_str, part->max - part->pos,
batch.edit_count, BatchEdit_PreserveTokens);
file_do_batch_edit(system, models, file, spec, hist_normal, BatchEdit_PreserveTokens);
}
end_temp_memory(temp);
#endif
}
struct Get_Link_Result{
b32 in_link;
i32 index;
};
internal u32*
style_get_color(Style *style, Cpp_Token token){
u32 *result;
@ -5555,54 +5096,73 @@ draw_file_bar(Render_Target *target, View *view, Editing_File *file, i32_Rect re
bar.text_shift_y = 2;
bar.text_shift_x = 0;
draw_rectangle(target, bar.rect, back_color);
if (!file){
intbar_draw_string(target, &bar, make_lit_string("*NULL*"), base_color);
draw_rectangle(target, bar.rect, back_color);
Assert(file);
intbar_draw_string(target, &bar, file->name.live_name, base_color);
intbar_draw_string(target, &bar, make_lit_string(" -"), base_color);
if (file->is_loading){
intbar_draw_string(target, &bar, make_lit_string(" loading"), base_color);
}
else{
intbar_draw_string(target, &bar, file->name.live_name, base_color);
intbar_draw_string(target, &bar, make_lit_string(" -"), base_color);
char bar_space[526];
String bar_text = make_fixed_width_string(bar_space);
append_ss (&bar_text, make_lit_string(" L#"));
append_int_to_str(&bar_text, view->edit_pos->cursor.line);
append_ss (&bar_text, make_lit_string(" C#"));
append_int_to_str(&bar_text, view->edit_pos->cursor.character);
if (file->is_loading){
intbar_draw_string(target, &bar, make_lit_string(" loading"), base_color);
append_ss(&bar_text, make_lit_string(" -"));
if (file->settings.dos_write_mode){
append_ss(&bar_text, make_lit_string(" dos"));
}
else{
char line_number_space[30];
String line_number = make_fixed_width_string(line_number_space);
append_ss(&line_number, make_lit_string(" L#"));
append_int_to_str(&line_number, view->edit_pos->cursor.line);
append_ss(&line_number, make_lit_string(" C#"));
append_int_to_str(&line_number, view->edit_pos->cursor.character);
append_ss(&bar_text, make_lit_string(" nix"));
}
append_ss(&bar_text, make_lit_string(" -"));
Command_Map *map = view->map;
if (map == &models->map_top){
append_ss(&bar_text, make_lit_string(" global"));
}
else if (map == &models->map_file){
append_ss(&bar_text, make_lit_string(" file"));
}
else if (map == &models->map_ui){
append_ss(&bar_text, make_lit_string(" gui"));
}
else{
i32 map_index = (i32)(view->map - models->user_maps);
i32 map_id = models->map_id_table[map_index];
intbar_draw_string(target, &bar, line_number, base_color);
intbar_draw_string(target, &bar, make_lit_string(" -"), base_color);
if (file->settings.dos_write_mode){
intbar_draw_string(target, &bar, make_lit_string(" dos"), base_color);
}
else{
intbar_draw_string(target, &bar, make_lit_string(" nix"), base_color);
}
if (file->state.still_lexing){
intbar_draw_string(target, &bar, make_lit_string(" parsing"), pop1_color);
}
if (!file->settings.unimportant){
switch (file_get_sync(file)){
case SYNC_BEHIND_OS:
{
persist String out_of_sync = make_lit_string(" !");
intbar_draw_string(target, &bar, out_of_sync, pop2_color);
}break;
case SYNC_UNSAVED:
{
persist String out_of_sync = make_lit_string(" *");
intbar_draw_string(target, &bar, out_of_sync, pop2_color);
}break;
}
append_ss (&bar_text, make_lit_string(" user:"));
append_int_to_str(&bar_text, map_id);
}
intbar_draw_string(target, &bar, bar_text, base_color);
if (file->state.still_lexing){
intbar_draw_string(target, &bar, make_lit_string(" parsing"), pop1_color);
}
if (!file->settings.unimportant){
switch (file_get_sync(file)){
case SYNC_BEHIND_OS:
{
persist String out_of_sync = make_lit_string(" !");
intbar_draw_string(target, &bar, out_of_sync, pop2_color);
}break;
case SYNC_UNSAVED:
{
persist String out_of_sync = make_lit_string(" *");
intbar_draw_string(target, &bar, out_of_sync, pop2_color);
}break;
}
}
}

View File

@ -82,8 +82,11 @@
; BEFORE I SHIP
;
; [] tokens in the custom API
; [] auto indent on the custom side
; [X] tokens in the custom API
; [X] auto indent on the custom side
; [] clean up and comment the auto indent code to allow for customizations
; [] more built in options for auto indenting
; [] token seeking on custom side
; [] expose dirty flags
; [] option to not open *messages* every startup
; [] commands for resizing panels
@ -96,7 +99,12 @@
; [] hook on exit
; [] read only files
; [] occasionally missing the (!) mark on files on windows
; [] don't execute frames on events dealing only with ctrl/alt/shift
; [] case insensitive interactive switch buffer
; [] option to hide hidden files
; [] tab to complete folder names in the new file dialogue
; [] view fails to follow cursor when the view is shrunk
; [] view fails to follow cursor after deleting long line
; [] scroll down on compilation buffer durring compilation
;
; TODOS
@ -134,6 +142,7 @@
; [X] full screen option
; [X] add to APIs
; [X] try to make win32 version better
; [X] don't execute frames on events dealing only with ctrl/alt/shift
;
; [] support full length unicode file names
; [] switch based word complete

View File

@ -18,12 +18,12 @@
# define FSTRING_C
# include "4coder_string.h"
#include "4coder_version.h"
# include "4coder_version.h"
# include "4coder_keycodes.h"
# include "4coder_style.h"
# include "4coder_rect.h"
# include "4coder_mem.h"
# include "4cpp_lexer.h"
// TODO(allen): This is duplicated from 4coder_custom.h
// I need to work out a way to avoid this.
@ -111,11 +111,7 @@ struct Control_Keys{
b8 l_alt;
b8 r_alt;
};
inline Control_Keys
control_keys_zero(){
Control_Keys result = {0};
return(result);
}
static Control_Keys null_control_keys;
struct Win32_Input_Chunk_Transient{
Key_Input_Data key_data;
@ -1837,7 +1833,8 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
win32vars.input_chunk.pers.mouse_l = 0;
win32vars.input_chunk.pers.mouse_r = 0;
win32vars.input_chunk.pers.controls = control_keys_zero();
win32vars.input_chunk.pers.control_keys[MDFR_SHIFT_INDEX] = 0;
win32vars.input_chunk.pers.controls = null_control_keys;
}break;
case WM_SIZE: