view api working, some examples in custom.cpp

master
Allen Webster 2016-02-24 00:16:08 -05:00
parent eeb7c7c6df
commit 29a405e8df
7 changed files with 882 additions and 574 deletions

78
4coder_buffer_types.h Normal file
View File

@ -0,0 +1,78 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 23.02.2016
*
* Types shared by custom and application
*
*/
// TOP
#ifndef FRED_BUFFER_TYPES_H
#define FRED_BUFFER_TYPES_H
typedef struct Full_Cursor{
int pos;
int line, character;
float unwrapped_x, unwrapped_y;
float wrapped_x, wrapped_y;
} Full_Cursor;
typedef enum{
buffer_seek_pos,
buffer_seek_wrapped_xy,
buffer_seek_unwrapped_xy,
buffer_seek_line_char
} Buffer_Seek_Type;
typedef struct Buffer_Seek{
Buffer_Seek_Type type;
union{
struct { int pos; };
struct { int round_down; float x, y; };
struct { int line, character; };
};
} Buffer_Seek;
static Buffer_Seek
seek_pos(int pos){
Buffer_Seek result;
result.type = buffer_seek_pos;
result.pos = pos;
return(result);
}
static Buffer_Seek
seek_wrapped_xy(float x, float y, int round_down){
Buffer_Seek result;
result.type = buffer_seek_wrapped_xy;
result.x = x;
result.y = y;
result.round_down = round_down;
return(result);
}
static Buffer_Seek
seek_unwrapped_xy(float x, float y, int round_down){
Buffer_Seek result;
result.type = buffer_seek_unwrapped_xy;
result.x = x;
result.y = y;
result.round_down = round_down;
return(result);
}
static Buffer_Seek
seek_line_char(int line, int character){
Buffer_Seek result;
result.type = buffer_seek_line_char;
result.line = line;
result.character = character;
return(result);
}
#endif
// BOTTOM

View File

@ -89,8 +89,87 @@ CUSTOM_COMMAND_SIG(write_increment){
// is usually ready, but when a buffer has just been opened it is possible that the contents
// haven't been filled yet. If the buffer is not ready trying to read or write it is invalid.
// (See my_file_settings for comments on the exists field).
char text[] = "++";
int size = sizeof(text) - 1;
if (buffer.exists && buffer.ready){
app->buffer_replace_range(cmd_context, &buffer, buffer.file_cursor_pos, buffer.file_cursor_pos, "++", 2);
app->buffer_replace_range(cmd_context, &buffer, buffer.file_cursor_pos, buffer.file_cursor_pos, text, size);
}
}
CUSTOM_COMMAND_SIG(write_decrement){
Buffer_Summary buffer = app->get_active_buffer(cmd_context);
char text[] = "--";
int size = sizeof(text) - 1;
if (buffer.exists && buffer.ready){
app->buffer_replace_range(cmd_context, &buffer, buffer.file_cursor_pos, buffer.file_cursor_pos, text, size);
}
}
CUSTOM_COMMAND_SIG(open_long_braces){
File_View_Summary view;
Buffer_Summary buffer;
view = app->get_active_view(cmd_context);
if (view.exists){
buffer = app->get_active_buffer(cmd_context);
char text[] = "{\n\n}";
int size = sizeof(text) - 1;
int pos;
if (buffer.exists && buffer.ready){
pos = view.cursor.pos;
app->buffer_replace_range(cmd_context, &buffer, pos, pos, text, size);
app->view_set_cursor(cmd_context, &view, seek_pos(pos + 2), 1);
push_parameter(app, cmd_context, par_range_start, pos);
push_parameter(app, cmd_context, par_range_end, pos + size);
push_parameter(app, cmd_context, par_clear_blank_lines, 0);
exec_command(cmd_context, cmdid_auto_tab_range);
}
}
}
CUSTOM_COMMAND_SIG(ifdef_off){
File_View_Summary view;
Buffer_Summary buffer;
view = app->get_active_view(cmd_context);
if (view.exists){
buffer = app->get_active_buffer(cmd_context);
char text1[] = "#if 0\n";
int size1 = sizeof(text1) - 1;
char text2[] = "#endif\n";
int size2 = sizeof(text2) - 1;
int pos, c, m;
if (buffer.exists && buffer.ready){
c = view.cursor.pos;
m = view.mark.pos;
pos = (c<m)?(c):(m);
app->buffer_replace_range(cmd_context, &buffer, pos, pos, text1, size1);
push_parameter(app, cmd_context, par_range_start, pos);
push_parameter(app, cmd_context, par_range_end, pos);
exec_command(cmd_context, cmdid_auto_tab_range);
app->refresh_view(cmd_context, &view);
c = view.cursor.pos;
m = view.mark.pos;
pos = (c>m)?(c):(m);
app->buffer_replace_range(cmd_context, &buffer, pos, pos, text2, size2);
push_parameter(app, cmd_context, par_range_start, pos);
push_parameter(app, cmd_context, par_range_end, pos);
exec_command(cmd_context, cmdid_auto_tab_range);
}
}
}
@ -278,6 +357,9 @@ extern "C" GET_BINDING_DATA(get_bindings){
bind(context, ' ', MDFR_SHIFT, cmdid_write_character);
bind(context, '=', MDFR_CTRL, write_increment);
bind(context, '-', MDFR_CTRL, write_decrement);
bind(context, '[', MDFR_CTRL, open_long_braces);
bind(context, 'i', MDFR_ALT, ifdef_off);
end_map(context);
@ -333,7 +415,7 @@ extern "C" GET_BINDING_DATA(get_bindings){
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
bind(context, 'f', MDFR_CTRL, cmdid_search);
bind(context, 'r', MDFR_CTRL, cmdid_rsearch);
bind(context, 'r', MDFR_CTRL, cmdid_reverse_search);
bind(context, 'g', MDFR_CTRL, cmdid_goto_line);
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer);

View File

@ -1,4 +1,6 @@
#include "4coder_buffer_types.h"
#define MDFR_NONE 0
#define MDFR_CTRL 1
#define MDFR_ALT 2
@ -63,7 +65,7 @@ enum Command_ID{
cmdid_seek_alphanumeric_or_camel_left,
cmdid_seek_alphanumeric_or_camel_right,
cmdid_search,
cmdid_rsearch,
cmdid_reverse_search,
cmdid_word_complete,
cmdid_goto_line,
cmdid_set_mark,
@ -124,6 +126,8 @@ enum Command_ID{
};
enum Param_ID{
par_range_start,
par_range_end,
par_name,
par_lex_as_cpp_file,
par_wrap_lines,
@ -133,6 +137,7 @@ enum Param_ID{
par_cli_command,
par_cli_overlap_with_conflict,
par_cli_always_bind_to_view,
par_clear_blank_lines,
// never below this
par_type_count
};
@ -216,10 +221,10 @@ struct Extra_Font{
int size;
};
// NOTE(allen): None of the members of *_Summary structs nor any of the
// data pointed to by the members should be modified, I would have made
// them all const... but that causes a lot problems for C++ reasons.
struct Buffer_Summary{
// NOTE(allen): None of these members nor any of the data pointed to
// by these members should be modified, I would have made them const...
// but that causes a lot problems for C++ reasons.
int exists;
int ready;
int file_id;
@ -236,6 +241,15 @@ struct Buffer_Summary{
int map_id;
};
struct File_View_Summary{
int exists;
int view_id;
int file_id;
Full_Cursor cursor;
Full_Cursor mark;
};
#ifndef FRED_STRING_STRUCT
#define FRED_STRING_STRUCT
struct String{
@ -274,10 +288,21 @@ extern "C"{
#define GET_ACTIVE_BUFFER_SIG(name) Buffer_Summary name(void *cmd_context)
#define GET_BUFFER_BY_NAME(name) Buffer_Summary name(void *cmd_context, String filename)
#define REFRESH_BUFFER_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer)
#define BUFFER_SEEK_DELIMITER_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, char delim, int *out)
#define BUFFER_READ_RANGE_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, int end, char *out)
#define BUFFER_REPLACE_RANGE_SIG(name) int name(void *cmd_context, Buffer_Summary *buffer, int start, int end, char *str, int len)
// File view manipulation
#define GET_VIEW_MAX_INDEX_SIG(name) int name(void *cmd_context)
#define GET_VIEW_SIG(name) File_View_Summary name(void *cmd_context, int index)
#define GET_ACTIVE_VIEW_SIG(name) File_View_Summary name(void *cmd_context)
#define REFRESH_VIEW_SIG(name) int name(void *cmd_context, File_View_Summary *view)
#define VIEW_SET_CURSOR_SIG(name) int name(void *cmd_context, File_View_Summary *view, Buffer_Seek seek, int set_preferred_x)
#define VIEW_SET_MARK_SIG(name) int name(void *cmd_context, File_View_Summary *view, Buffer_Seek seek)
#define VIEW_SET_FILE_SIG(name) int name(void *cmd_context, File_View_Summary *view, int file_id)
extern "C"{
// Command exectuion
typedef EXECUTE_COMMAND_SIG(Exec_Command_Function);
@ -296,9 +321,20 @@ extern "C"{
typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function);
typedef GET_BUFFER_BY_NAME(Get_Buffer_By_Name_Function);
typedef REFRESH_BUFFER_SIG(Refresh_Buffer_Function);
typedef BUFFER_SEEK_DELIMITER_SIG(Buffer_Seek_Delimiter_Function);
typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function);
typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
// View manipulation
typedef GET_VIEW_MAX_INDEX_SIG(Get_View_Max_Index_Function);
typedef GET_VIEW_SIG(Get_View_Function);
typedef GET_ACTIVE_VIEW_SIG(Get_Active_View_Function);
typedef REFRESH_VIEW_SIG(Refresh_View_Function);
typedef VIEW_SET_CURSOR_SIG(View_Set_Cursor_Function);
typedef VIEW_SET_MARK_SIG(View_Set_Mark_Function);
typedef VIEW_SET_FILE_SIG(View_Set_File_Function);
}
struct Application_Links{
@ -319,9 +355,20 @@ struct Application_Links{
Get_Active_Buffer_Function *get_active_buffer;
Get_Buffer_By_Name_Function *get_buffer_by_name;
Refresh_Buffer_Function *refresh_buffer;
Buffer_Seek_Delimiter_Function *buffer_seek_delimiter;
Buffer_Read_Range_Function *buffer_read_range;
Buffer_Replace_Range_Function *buffer_replace_range;
// View manipulation
Get_View_Max_Index_Function *get_view_max_index;
Get_View_Function *get_view;
Get_Active_View_Function *get_active_view;
Refresh_View_Function *refresh_view;
View_Set_Cursor_Function *view_set_cursor;
View_Set_Mark_Function *view_set_mark;
View_Set_File_Function *view_set_file;
};
struct Custom_API{

View File

@ -92,61 +92,34 @@ end_map(Bind_Helper *helper){
helper->group = 0;
}
struct Bind_Target{
short code;
unsigned char modifiers;
};
inline Bind_Target
tkey(short code, unsigned char modifiers){
Bind_Target target;
target.code = code;
target.modifiers = modifiers;
return target;
}
inline void
bind(Bind_Helper *helper, Bind_Target target, int cmdid){
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = unit_binding;
unit.binding.command_id = cmdid;
unit.binding.code = target.code;
unit.binding.modifiers = target.modifiers;
unit.binding.code = code;
unit.binding.modifiers = modifiers;
write_unit(helper, unit);
}
inline void
bind(Bind_Helper *helper, Bind_Target target, Custom_Command_Function *func){
bind(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = unit_callback;
unit.callback.func = func;
unit.callback.code = target.code;
unit.callback.modifiers = target.modifiers;
unit.callback.code = code;
unit.callback.modifiers = modifiers;
write_unit(helper, unit);
}
inline void
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
Bind_Target target;
target = tkey(code, modifiers);
bind(helper, target, cmdid);
}
inline void
bind(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
Bind_Target target;
target = tkey(code, modifiers);
bind(helper, target, func);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, int cmdid){
bind(helper, 0, 0, cmdid);

235
4ed.cpp
View File

@ -434,7 +434,7 @@ COMMAND_DECL(search){
view->isearch.pos = view->cursor.pos - 1;
}
COMMAND_DECL(rsearch){
COMMAND_DECL(reverse_search){
ProfileMomentFunction();
REQ_FILE_VIEW(view);
REQ_FILE(fixed, view);
@ -1268,10 +1268,37 @@ COMMAND_DECL(auto_tab_range){
REQ_FILE(file, view);
USE_LAYOUT(layout);
USE_MEM(mem);
int r_start = 0, r_end = 0;
int start_set = 0, end_set = 0;
int clear_blank_lines = 1;
Command_Parameter *end = param_stack_end(&command->part);
Command_Parameter *param = param_stack_first(&command->part, end);
for (; param < end; param = param_next(param, end)){
int p = dynamic_to_int(&param->param.param);
switch (p){
case par_range_start:
start_set = 1;
r_start = dynamic_to_int(&param->param.value);
break;
case par_range_end:
end_set = 1;
r_end = dynamic_to_int(&param->param.value);
break;
case par_clear_blank_lines:
clear_blank_lines = dynamic_to_bool(&param->param.value);
break;
}
}
if (file->state.token_stack.tokens && file->state.tokens_complete){
Range range = get_range(view->cursor.pos, view->mark);
view_auto_tab_tokens(system, mem, view, layout, range.start, range.end, 1);
if (start_set) range.start = r_start;
if (end_set) range.end = r_end;
view_auto_tab_tokens(system, mem, view, layout, range.start, range.end, clear_blank_lines);
}
}
@ -1282,9 +1309,22 @@ COMMAND_DECL(auto_tab_line_at_cursor){
USE_LAYOUT(layout);
USE_MEM(mem);
int clear_blank_lines = 0;
Command_Parameter *end = param_stack_end(&command->part);
Command_Parameter *param = param_stack_first(&command->part, end);
for (; param < end; param = param_next(param, end)){
int p = dynamic_to_int(&param->param.param);
switch (p){
case par_clear_blank_lines:
clear_blank_lines = dynamic_to_bool(&param->param.value);
break;
}
}
if (file->state.token_stack.tokens && file->state.tokens_complete){
i32 pos = view->cursor.pos;
view_auto_tab_tokens(system, mem, view, layout, pos, pos, 0);
view_auto_tab_tokens(system, mem, view, layout, pos, pos, clear_blank_lines);
}
}
@ -1695,7 +1735,6 @@ COMMAND_DECL(set_settings){
REQ_FILE_LOADING(file, view);
USE_VARS(vars);
USE_MEM(mem);
AllowLocal(mem);
Command_Parameter *end = param_stack_end(&command->part);
Command_Parameter *param = param_stack_first(&command->part, end);
@ -2026,6 +2065,17 @@ fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *wor
buffer->map_id = file->settings.base_map_id;
}
internal void
fill_view_summary(File_View_Summary *view, File_View *file_view, Live_Views *live_set, Working_Set *working_set){
view->exists = 1;
view->view_id = (int)((char*)file_view - (char*)live_set->views) / live_set->stride;
if (file_view->file){
view->file_id = (int)(file_view->file - working_set->files);
view->mark = view_compute_cursor_from_pos(file_view, file_view->mark);
view->cursor = file_view->cursor;
}
}
extern "C"{
EXECUTE_COMMAND_SIG(external_exec_command_keep_stack){
Command_Data *cmd = (Command_Data*)cmd_context;
@ -2079,29 +2129,22 @@ extern "C"{
GET_BUFFER_MAX_INDEX_SIG(external_get_buffer_max_index){
Command_Data *cmd = (Command_Data*)cmd_context;
Working_Set *working_set;
int max;
working_set = cmd->working_set;
max = working_set->file_index_count;
Working_Set *working_set = cmd->working_set;
int max = working_set->file_index_count;
return(max);
}
GET_BUFFER_SIG(external_get_buffer){
Command_Data *cmd = (Command_Data*)cmd_context;
Editing_File *file;
Working_Set *working_set;
int max;
Working_Set *working_set = cmd->working_set;
int max = working_set->file_index_count;
Buffer_Summary buffer = {};
working_set = cmd->working_set;
max = working_set->file_index_count;
if (index >= 0 && index < max){
file = working_set->files + index;
if (!file->state.is_dummy){
#if BUFFER_EXPERIMENT_SCALPEL <= 0
fill_buffer_summary(&buffer, file, working_set);
#endif
}
}
@ -2121,9 +2164,7 @@ extern "C"{
working_set = cmd->working_set;
if (file && !file->state.is_dummy){
#if BUFFER_EXPERIMENT_SCALPEL <= 0
fill_buffer_summary(&buffer, file, working_set);
#endif
}
}
@ -2141,15 +2182,20 @@ extern "C"{
if (table_find(&working_set->table, filename, &index)){
file = working_set->files + index;
if (!file->state.is_dummy && file_is_ready(file)){
#if BUFFER_EXPERIMENT_SCALPEL <= 0
fill_buffer_summary(&buffer, file, working_set);
#endif
}
}
return(buffer);
}
REFRESH_BUFFER_SIG(external_refresh_buffer){
int result;
*buffer = external_get_buffer(cmd_context, buffer->file_id);
result = buffer->exists;
return(result);
}
BUFFER_SEEK_DELIMITER_SIG(external_buffer_seek_delimiter){
Command_Data *cmd = (Command_Data*)cmd_context;
Editing_File *file;
@ -2237,6 +2283,135 @@ extern "C"{
return(result);
}
GET_VIEW_MAX_INDEX_SIG(external_get_view_max_index){
Command_Data *cmd = (Command_Data*)cmd_context;
Live_Views *live_set = cmd->live_set;
int max = live_set->max;
return(max);
}
GET_VIEW_SIG(external_get_view){
Command_Data *cmd = (Command_Data*)cmd_context;
Live_Views *live_set = cmd->live_set;
int max = live_set->max;
View *vptr;
File_View *file_view;
File_View_Summary view = {};
if (index >= 0 && index < max){
vptr = (View*)((char*)live_set->views + live_set->stride*index);
file_view = view_to_file_view(vptr);
if (file_view){
fill_view_summary(&view, file_view, cmd->live_set, cmd->working_set);
}
}
return(view);
}
GET_ACTIVE_VIEW_SIG(external_get_active_view){
Command_Data *cmd = (Command_Data*)cmd_context;
File_View_Summary view = {};
File_View *file_view;
file_view = view_to_file_view(cmd->view);
if (file_view){
fill_view_summary(&view, file_view, cmd->live_set, cmd->working_set);
}
return(view);
}
REFRESH_VIEW_SIG(external_refresh_view){
int result;
*view = external_get_view(cmd_context, view->view_id);
result = view->exists;
return(result);
}
VIEW_SET_CURSOR_SIG(external_view_set_cursor){
Command_Data *cmd = (Command_Data*)cmd_context;
Live_Views *live_set;
View *vptr;
File_View *file_view;
int result = 0;
if (view->exists){
live_set = cmd->live_set;
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
file_view = view_to_file_view(vptr);
if (file_view){
result = 1;
file_view->cursor = view_compute_cursor(file_view, seek);
if (set_preferred_x){
file_view->preferred_x = view_get_cursor_x(file_view);
}
fill_view_summary(view, file_view, cmd->live_set, cmd->working_set);
}
}
return(result);
}
VIEW_SET_MARK_SIG(external_view_set_mark){
Command_Data *cmd = (Command_Data*)cmd_context;
Live_Views *live_set;
View *vptr;
File_View *file_view;
Full_Cursor cursor;
int result = 0;
if (view->exists){
live_set = cmd->live_set;
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
file_view = view_to_file_view(vptr);
if (file_view){
result = 1;
if (seek.type != buffer_seek_pos){
cursor = view_compute_cursor(file_view, seek);
file_view->mark = cursor.pos;
}
else{
file_view->mark = seek.pos;
}
fill_view_summary(view, file_view, cmd->live_set, cmd->working_set);
}
}
return(result);
}
VIEW_SET_FILE_SIG(external_view_set_file){
Command_Data *cmd = (Command_Data*)cmd_context;
Live_Views *live_set;
View *vptr;
File_View *file_view;
Editing_File *file;
Working_Set *working_set;
int max, result = 0;
if (view->exists){
live_set = cmd->live_set;
vptr = (View*)((char*)live_set->views + live_set->stride * view->view_id);
file_view = view_to_file_view(vptr);
if (file_view){
working_set = cmd->working_set;
max = working_set->file_index_count;
if (file_id >= 0 && file_id < max){
file = working_set->files + file_id;
if (!file->state.is_dummy){
view_set_file(cmd->system, file_view, file, cmd->vars->font_set, cmd->style,
cmd->vars->hooks[hook_open_file], cmd, &app_links);
}
}
fill_view_summary(view, file_view, cmd->live_set, cmd->working_set);
}
}
return(result);
}
}
inline void
@ -2250,18 +2425,24 @@ app_links_init(System_Functions *system){
app_links.directory_has_file = system->directory_has_file;
app_links.directory_cd = system->directory_cd;
app_links.get_buffer_max_index = external_get_buffer_max_index;
app_links.get_buffer = external_get_buffer;
app_links.get_buffer_by_name = external_get_buffer_by_name;
app_links.get_buffer_max_index = external_get_buffer_max_index;
app_links.get_buffer = external_get_buffer;
app_links.get_active_buffer = external_get_active_buffer;
app_links.get_buffer_by_name = external_get_buffer_by_name;
app_links.refresh_buffer = external_refresh_buffer;
app_links.buffer_seek_delimiter = external_buffer_seek_delimiter;
app_links.buffer_read_range = external_buffer_read_range;
app_links.buffer_replace_range = external_buffer_replace_range;
app_links.get_view_max_index = external_get_view_max_index;
app_links.get_view = external_get_view;
app_links.get_active_view = external_get_active_view;
app_links.refresh_view = external_refresh_view;
app_links.view_set_cursor = external_view_set_cursor;
app_links.view_set_mark = external_view_set_mark;
app_links.view_set_file = external_view_set_file;
}
#if FRED_INTERNAL
@ -2338,9 +2519,9 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co
map_add(commands, 'u', MDFR_CTRL, command_to_uppercase);
map_add(commands, 'j', MDFR_CTRL, command_to_lowercase);
map_add(commands, '~', MDFR_CTRL, command_clean_all_lines);
map_add(commands, 'f', MDFR_CTRL, command_search);
map_add(commands, 'r', MDFR_CTRL, command_rsearch);
map_add(commands, 'f', MDFR_CTRL, command_search);
map_add(commands, 'r', MDFR_CTRL, command_reverse_search);
map_add(commands, 'g', MDFR_CTRL, command_goto_line);
map_add(commands, '\n', MDFR_NONE, compose_write_auto_tab_line);
@ -2404,7 +2585,7 @@ setup_command_table(){
SET(seek_alphanumeric_or_camel_right);
SET(seek_alphanumeric_or_camel_left);
SET(search);
SET(rsearch);
SET(reverse_search);
SET(word_complete);
SET(goto_line);
SET(set_mark);

View File

@ -1207,7 +1207,6 @@ file_post_history(General_Memory *general, Editing_File *file,
inline Full_Cursor
view_compute_cursor_from_pos(File_View *view, i32 pos){
#if BUFFER_EXPERIMENT_SCALPEL <= 3
Editing_File *file = view->file;
Style *style = view->style;
Render_Font *font = get_font_info(view->font_set, style->font_id)->font;
@ -1219,16 +1218,11 @@ view_compute_cursor_from_pos(File_View *view, i32 pos){
max_width, (f32)view->font_height, font->advance_data);
}
return result;
#else
return view->cursor;
#endif
}
inline Full_Cursor
view_compute_cursor_from_unwrapped_xy(File_View *view, f32 seek_x, f32 seek_y,
b32 round_down = 0){
#if BUFFER_EXPERIMENT_SCALPEL <= 3
Editing_File *file = view->file;
Style *style = view->style;
Render_Font *font = get_font_info(view->font_set, style->font_id)->font;
@ -1242,16 +1236,11 @@ view_compute_cursor_from_unwrapped_xy(File_View *view, f32 seek_x, f32 seek_y,
}
return result;
#else
return view->cursor;
#endif
}
internal Full_Cursor
view_compute_cursor_from_wrapped_xy(File_View *view, f32 seek_x, f32 seek_y,
b32 round_down = 0){
#if BUFFER_EXPERIMENT_SCALPEL <= 3
Editing_File *file = view->file;
Style *style = view->style;
Render_Font *font = get_font_info(view->font_set, style->font_id)->font;
@ -1265,15 +1254,10 @@ view_compute_cursor_from_wrapped_xy(File_View *view, f32 seek_x, f32 seek_y,
}
return result;
#else
return view->cursor;
#endif
}
internal Full_Cursor
view_compute_cursor_from_line_pos(File_View *view, i32 line, i32 pos){
#if BUFFER_EXPERIMENT_SCALPEL <= 3
Editing_File *file = view->file;
Style *style = view->style;
Render_Font *font = get_font_info(view->font_set, style->font_id)->font;
@ -1286,10 +1270,31 @@ view_compute_cursor_from_line_pos(File_View *view, i32 line, i32 pos){
}
return result;
}
inline Full_Cursor
view_compute_cursor(File_View *view, Buffer_Seek seek){
Full_Cursor result = {};
#else
return view->cursor;
#endif
switch(seek.type){
case buffer_seek_pos:
result = view_compute_cursor_from_pos(view, seek.pos);
break;
case buffer_seek_wrapped_xy:
result = view_compute_cursor_from_wrapped_xy(view, seek.x, seek.y);
break;
case buffer_seek_unwrapped_xy:
result = view_compute_cursor_from_unwrapped_xy(view, seek.x, seek.y);
break;
case buffer_seek_line_char:
result = view_compute_cursor_from_line_pos(view, seek.line, seek.character);
break;
}
return result;
}
inline Full_Cursor
@ -2383,8 +2388,8 @@ view_clean_whitespace(System_Functions *system, Mem_Options *mem, File_View *vie
for (i32 line_i = 0; line_i < line_count; ++line_i){
i32 start = file->state.buffer.line_starts[line_i];
i32 preferred_indentation;
bool32 all_whitespace = 0;
bool32 all_space = 0;
b32 all_whitespace = 0;
b32 all_space = 0;
i32 hard_start =
buffer_find_hard_start(&file->state.buffer, start, &all_whitespace, &all_space,
&preferred_indentation, 4);
@ -3389,14 +3394,14 @@ kill_file(System_Functions *system, Exchange *exchange,
internal void
command_search(System_Functions*,Command_Data*,Command_Binding);
internal void
command_rsearch(System_Functions*,Command_Data*,Command_Binding);
command_reverse_search(System_Functions*,Command_Data*,Command_Binding);
internal
HANDLE_COMMAND_SIG(handle_command_file_view){
File_View *file_view = (File_View*)(view);
Editing_File *file = file_view->file;
AllowLocal(file);
switch (file_view->widget.type){
case FWIDG_NONE:
case FWIDG_TIMELINES:
@ -3418,12 +3423,12 @@ HANDLE_COMMAND_SIG(handle_command_file_view){
if (result.made_a_change ||
binding.function == command_search ||
binding.function == command_rsearch){
bool32 step_forward = 0;
bool32 step_backward = 0;
binding.function == command_reverse_search){
b32 step_forward = 0;
b32 step_backward = 0;
if (binding.function == command_search) step_forward = 1;
if (binding.function == command_rsearch) step_backward = 1;
if (binding.function == command_reverse_search) step_backward = 1;
i32 start_pos = file_view->isearch.pos;
if (step_forward){

View File

@ -1,481 +1,423 @@
/*
* Mr. 4th Dimention - Allen Webster
* Four Tech
*
* public domain -- no warranty is offered or implied; use this code at your own risk
*
* 23.10.2015
*
* Items shared by gap buffer types
*
*/
// TOP
#ifndef inline_4tech
#define inline_4tech inline
#endif
#ifndef internal_4tech
#define internal_4tech static
#endif
#ifndef memset_4tech
#define memset_4tech memset
#endif
#ifndef memzero_4tech
#define memzero_4tech(x) ((x) = {})
#endif
#ifndef memcpy_4tech
#define memcpy_4tech memcpy
#endif
#ifndef memmove_4tech
#define memmove_4tech memmove
#endif
#ifndef debug_4tech
#define debug_4tech(x) x
#endif
#ifndef assert_4tech
#define assert_4tech assert
#endif
#ifndef ceil_4tech
#define ceil_4tech CEIL32
#endif
#ifndef div_ceil_4tech
#define div_ceil_4tech DIVCEIL32
#endif
#ifndef cat_4tech
#define cat_4tech_(a,b) a##b
#define cat_4tech(a,b) cat_4tech_(a,b)
#endif
#ifndef round_up_4tech
internal_4tech int
lroundup_(int x, int granularity){
int original_x;
original_x = x;
x /= granularity;
x *= granularity;
if (x < original_x) x += granularity;
return x;
}
#define round_up_4tech(x,g) lroundup_(x,g)
#endif
#ifndef round_pot_4tech
#define round_pot_4tech ROUNDPOT32
#endif
#define measure_character(a,c) ((a)[c])
typedef struct Buffer_Edit{
int str_start, len;
int start, end;
} Buffer_Edit;
typedef struct Buffer_Batch_State{
int i;
int shift_total;
} Buffer_Batch_State;
typedef enum{
buffer_seek_pos,
buffer_seek_wrapped_xy,
buffer_seek_unwrapped_xy,
buffer_seek_line_char
} Buffer_Seek_Type;
typedef struct Buffer_Seek{
Buffer_Seek_Type type;
union{
struct { int pos; };
struct { int round_down; float x, y; };
struct { int line, character; };
};
} Buffer_Seek;
inline_4tech Buffer_Seek
seek_pos(int pos){
Buffer_Seek result;
result.type = buffer_seek_pos;
result.pos = pos;
return(result);
}
inline_4tech Buffer_Seek
seek_wrapped_xy(float x, float y, int round_down){
Buffer_Seek result;
result.type = buffer_seek_wrapped_xy;
result.x = x;
result.y = y;
result.round_down = round_down;
return(result);
}
inline_4tech Buffer_Seek
seek_unwrapped_xy(float x, float y, int round_down){
Buffer_Seek result;
result.type = buffer_seek_unwrapped_xy;
result.x = x;
result.y = y;
result.round_down = round_down;
return(result);
}
inline_4tech Buffer_Seek
seek_line_char(int line, int character){
Buffer_Seek result;
result.type = buffer_seek_line_char;
result.line = line;
result.character = character;
return(result);
}
typedef struct Full_Cursor{
int pos;
int line, character;
float unwrapped_x, unwrapped_y;
float wrapped_x, wrapped_y;
} Full_Cursor;
#define BRFlag_Special_Character (1 << 0)
typedef struct Buffer_Render_Item{
int index;
unsigned short glyphid;
unsigned short flags;
float x0, y0;
float x1, y1;
} Buffer_Render_Item;
inline_4tech void
write_render_item(Buffer_Render_Item *item, int index, unsigned short glyphid,
float x, float y, float w, float h){
item->index = index;
item->glyphid = glyphid;
item->x0 = x;
item->y0 = y;
item->x1 = x + w;
item->y1 = y + h;
}
inline_4tech float
write_render_item_inline(Buffer_Render_Item *item, int index, unsigned short glyphid,
float x, float y, float *advance_data, float h){
float ch_width;
ch_width = measure_character(advance_data, (char)glyphid);
write_render_item(item, index, glyphid, x, y, ch_width, h);
return(ch_width);
}
inline_4tech Full_Cursor
make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){
Full_Cursor hint;
hint.pos = starts[line_index];
hint.line = line_index + 1;
hint.character = 1;
hint.unwrapped_y = (float)(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{
int pos, index;
} Cursor_With_Index;
inline_4tech void
write_cursor_with_index(Cursor_With_Index *positions, int *count, int pos){
positions[*count].index = *count;
positions[*count].pos = pos;
++*count;
}
#define CursorSwap__(a,b) { Cursor_With_Index t = a; a = b; b = t; }
internal_4tech void
buffer_quick_sort_cursors(Cursor_With_Index *positions, int start, int pivot){
int i, mid;
int pivot_pos;
mid = start;
pivot_pos = positions[pivot].pos;
for (i = mid; i < pivot; ++i){
if (positions[i].pos < pivot_pos){
CursorSwap__(positions[mid], positions[i]);
++mid;
}
}
CursorSwap__(positions[mid], positions[pivot]);
if (start < mid - 1) buffer_quick_sort_cursors(positions, start, mid - 1);
if (mid + 1 < pivot) buffer_quick_sort_cursors(positions, mid + 1, pivot);
}
internal_4tech void
buffer_quick_unsort_cursors(Cursor_With_Index *positions, int start, int pivot){
int i, mid;
int pivot_index;
mid = start;
pivot_index = positions[pivot].index;
for (i = mid; i < pivot; ++i){
if (positions[i].index < pivot_index){
CursorSwap__(positions[mid], positions[i]);
++mid;
}
}
CursorSwap__(positions[mid], positions[pivot]);
if (start < mid - 1) buffer_quick_unsort_cursors(positions, start, mid - 1);
if (mid + 1 < pivot) buffer_quick_unsort_cursors(positions, mid + 1, pivot);
}
#undef CursorSwap__
inline_4tech void
buffer_sort_cursors(Cursor_With_Index *positions, int count){
assert_4tech(count > 0);
buffer_quick_sort_cursors(positions, 0, count-1);
}
inline_4tech void
buffer_unsort_cursors(Cursor_With_Index *positions, int count){
assert_4tech(count > 0);
buffer_quick_unsort_cursors(positions, 0, count-1);
}
internal_4tech void
buffer_update_cursors(Cursor_With_Index *sorted_positions, int count, int start, int end, int len){
Cursor_With_Index *position;
int shift_amount;
shift_amount = (len - (end - start));
position = sorted_positions + count - 1;
for (; position >= sorted_positions && position->pos >= end; --position) position->pos += shift_amount;
for (; position >= sorted_positions && position->pos >= start; --position) position->pos = start;
}
internal_4tech int
buffer_batch_debug_sort_check(Buffer_Edit *sorted_edits, int edit_count){
Buffer_Edit *edit;
int i, result, start_point;
result = 1;
start_point = 0;
edit = sorted_edits;
for (i = 0; i < edit_count; ++i, ++edit){
if (start_point > edit->start){
result = 0; break;
}
start_point = (edit->end < edit->start + 1)?edit->start + 1:edit->end;
}
return(result);
}
internal_4tech int
buffer_batch_edit_max_shift(Buffer_Edit *sorted_edits, int edit_count){
Buffer_Edit *edit;
int i, result;
int shift_total, shift_max;
result = 0;
shift_total = 0;
shift_max = 0;
edit = sorted_edits;
for (i = 0; i < edit_count; ++i, ++edit){
shift_total += (edit->len - (edit->end - edit->start));
if (shift_total > shift_max) shift_max = shift_total;
}
return(shift_max);
}
internal_4tech void
buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, int count, Buffer_Edit *sorted_edits, int edit_count){
Cursor_With_Index *position, *end_position;
Buffer_Edit *edit, *end_edit;
int start, end;
int shift_amount;
position = sorted_positions;
end_position = sorted_positions + count;
edit = sorted_edits;
end_edit = sorted_edits + edit_count;
shift_amount = 0;
for (; edit < end_edit && position < end_position; ++edit){
start = edit->start;
end = edit->end;
for (; position->pos < start && position < end_position; ++position){
position->pos += shift_amount;
}
for (; position->pos < end && position < end_position; ++position){
position->pos = start + shift_amount;
}
shift_amount += (edit->len - (end - start));
}
for (; position < end_position; ++position){
position->pos += shift_amount;
}
}
internal_4tech int
eol_convert_in(char *dest, char *src, int size){
int i, j, k;
i = 0;
k = 0;
j = 0;
for (; j < size && src[j] != '\r'; ++j);
memcpy_4tech(dest, src, j);
if (j < size){
k = 1;
++j;
for (i = j; i < size; ++i){
if (src[i] == '\r'){
memcpy_4tech(dest + j - k, src + j, i - j);
++k;
j = i+1;
}
}
memcpy_4tech(dest + j - k, src + j, i - j);
j = i - k;
}
return(j);
}
internal_4tech int
eol_in_place_convert_in(char *data, int size){
int i, j, k;
i = 0;
k = 0;
j = 0;
for (; j < size && data[j] != '\r'; ++j);
if (j < size){
k = 1;
++j;
for (i = j; i < size; ++i){
if (data[i] == '\r'){
memmove_4tech(data + j - k, data + j, i - j);
++k;
j = i+1;
}
}
memmove_4tech(data + j - k, data + j, i - j);
j = i - k;
}
return(j);
}
internal_4tech int
eol_convert_out(char *dest, int max, char *src, int size, int *size_out){
int result;
int i, j;
// TODO(allen): iterative memory check?
result = 1;
i = 0;
j = 0;
for (; i < size; ++i, ++j){
if (src[i] == '\n'){
dest[j] = '\r';
++j;
dest[j] = '\n';
}
else dest[j] = src[i];
}
*size_out = j;
return(result);
}
internal_4tech int
eol_in_place_convert_out(char *data, int size, int max, int *size_out){
int result;
int i;
// TODO(allen): iterative memory check?
result = 1;
i = 0;
for (; i < size; ++i){
if (data[i] == '\n'){
memmove_4tech(data + i + 1, data + i, size - i);
data[i] = '\r';
++i;
++size;
}
}
*size_out = size;
return(result);
}
inline_4tech int
is_whitespace(char c){
int result;
result = (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v');
return(result);
}
inline_4tech int
is_alphanumeric_true(char c){
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9');
}
inline_4tech int
is_alphanumeric(char c){
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_');
}
inline_4tech int
is_upper(char c){
return (c >= 'A' && c <= 'Z');
}
inline_4tech int
is_lower(char c){
return (c >= 'a' && c <= 'z');
}
internal_4tech int
is_match(char *a, char *b, int len){
int result;
result = 1;
for (;len > 0; --len, ++a, ++b)
if (*a != *b) { result = 0; break; }
return(result);
}
// BOTTOM
/*
* Mr. 4th Dimention - Allen Webster
* Four Tech
*
* public domain -- no warranty is offered or implied; use this code at your own risk
*
* 23.10.2015
*
* Items shared by gap buffer types
*
*/
// TOP
#include "../4coder_buffer_types.h"
#ifndef inline_4tech
#define inline_4tech inline
#endif
#ifndef internal_4tech
#define internal_4tech static
#endif
#ifndef memset_4tech
#define memset_4tech memset
#endif
#ifndef memzero_4tech
#define memzero_4tech(x) ((x) = {})
#endif
#ifndef memcpy_4tech
#define memcpy_4tech memcpy
#endif
#ifndef memmove_4tech
#define memmove_4tech memmove
#endif
#ifndef debug_4tech
#define debug_4tech(x) x
#endif
#ifndef assert_4tech
#define assert_4tech assert
#endif
#ifndef ceil_4tech
#define ceil_4tech CEIL32
#endif
#ifndef div_ceil_4tech
#define div_ceil_4tech DIVCEIL32
#endif
#ifndef cat_4tech
#define cat_4tech_(a,b) a##b
#define cat_4tech(a,b) cat_4tech_(a,b)
#endif
#ifndef round_up_4tech
internal_4tech int
lroundup_(int x, int granularity){
int original_x;
original_x = x;
x /= granularity;
x *= granularity;
if (x < original_x) x += granularity;
return x;
}
#define round_up_4tech(x,g) lroundup_(x,g)
#endif
#ifndef round_pot_4tech
#define round_pot_4tech ROUNDPOT32
#endif
#define measure_character(a,c) ((a)[c])
typedef struct Buffer_Edit{
int str_start, len;
int start, end;
} Buffer_Edit;
typedef struct Buffer_Batch_State{
int i;
int shift_total;
} Buffer_Batch_State;
#define BRFlag_Special_Character (1 << 0)
typedef struct Buffer_Render_Item{
int index;
unsigned short glyphid;
unsigned short flags;
float x0, y0;
float x1, y1;
} Buffer_Render_Item;
inline_4tech void
write_render_item(Buffer_Render_Item *item, int index, unsigned short glyphid,
float x, float y, float w, float h){
item->index = index;
item->glyphid = glyphid;
item->x0 = x;
item->y0 = y;
item->x1 = x + w;
item->y1 = y + h;
}
inline_4tech float
write_render_item_inline(Buffer_Render_Item *item, int index, unsigned short glyphid,
float x, float y, float *advance_data, float h){
float ch_width;
ch_width = measure_character(advance_data, (char)glyphid);
write_render_item(item, index, glyphid, x, y, ch_width, h);
return(ch_width);
}
inline_4tech Full_Cursor
make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){
Full_Cursor hint;
hint.pos = starts[line_index];
hint.line = line_index + 1;
hint.character = 1;
hint.unwrapped_y = (float)(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{
int pos, index;
} Cursor_With_Index;
inline_4tech void
write_cursor_with_index(Cursor_With_Index *positions, int *count, int pos){
positions[*count].index = *count;
positions[*count].pos = pos;
++*count;
}
#define CursorSwap__(a,b) { Cursor_With_Index t = a; a = b; b = t; }
internal_4tech void
buffer_quick_sort_cursors(Cursor_With_Index *positions, int start, int pivot){
int i, mid;
int pivot_pos;
mid = start;
pivot_pos = positions[pivot].pos;
for (i = mid; i < pivot; ++i){
if (positions[i].pos < pivot_pos){
CursorSwap__(positions[mid], positions[i]);
++mid;
}
}
CursorSwap__(positions[mid], positions[pivot]);
if (start < mid - 1) buffer_quick_sort_cursors(positions, start, mid - 1);
if (mid + 1 < pivot) buffer_quick_sort_cursors(positions, mid + 1, pivot);
}
internal_4tech void
buffer_quick_unsort_cursors(Cursor_With_Index *positions, int start, int pivot){
int i, mid;
int pivot_index;
mid = start;
pivot_index = positions[pivot].index;
for (i = mid; i < pivot; ++i){
if (positions[i].index < pivot_index){
CursorSwap__(positions[mid], positions[i]);
++mid;
}
}
CursorSwap__(positions[mid], positions[pivot]);
if (start < mid - 1) buffer_quick_unsort_cursors(positions, start, mid - 1);
if (mid + 1 < pivot) buffer_quick_unsort_cursors(positions, mid + 1, pivot);
}
#undef CursorSwap__
inline_4tech void
buffer_sort_cursors(Cursor_With_Index *positions, int count){
assert_4tech(count > 0);
buffer_quick_sort_cursors(positions, 0, count-1);
}
inline_4tech void
buffer_unsort_cursors(Cursor_With_Index *positions, int count){
assert_4tech(count > 0);
buffer_quick_unsort_cursors(positions, 0, count-1);
}
internal_4tech void
buffer_update_cursors(Cursor_With_Index *sorted_positions, int count, int start, int end, int len){
Cursor_With_Index *position;
int shift_amount;
shift_amount = (len - (end - start));
position = sorted_positions + count - 1;
for (; position >= sorted_positions && position->pos >= end; --position) position->pos += shift_amount;
for (; position >= sorted_positions && position->pos >= start; --position) position->pos = start;
}
internal_4tech int
buffer_batch_debug_sort_check(Buffer_Edit *sorted_edits, int edit_count){
Buffer_Edit *edit;
int i, result, start_point;
result = 1;
start_point = 0;
edit = sorted_edits;
for (i = 0; i < edit_count; ++i, ++edit){
if (start_point > edit->start){
result = 0; break;
}
start_point = (edit->end < edit->start + 1)?edit->start + 1:edit->end;
}
return(result);
}
internal_4tech int
buffer_batch_edit_max_shift(Buffer_Edit *sorted_edits, int edit_count){
Buffer_Edit *edit;
int i, result;
int shift_total, shift_max;
result = 0;
shift_total = 0;
shift_max = 0;
edit = sorted_edits;
for (i = 0; i < edit_count; ++i, ++edit){
shift_total += (edit->len - (edit->end - edit->start));
if (shift_total > shift_max) shift_max = shift_total;
}
return(shift_max);
}
internal_4tech void
buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, int count, Buffer_Edit *sorted_edits, int edit_count){
Cursor_With_Index *position, *end_position;
Buffer_Edit *edit, *end_edit;
int start, end;
int shift_amount;
position = sorted_positions;
end_position = sorted_positions + count;
edit = sorted_edits;
end_edit = sorted_edits + edit_count;
shift_amount = 0;
for (; edit < end_edit && position < end_position; ++edit){
start = edit->start;
end = edit->end;
for (; position->pos < start && position < end_position; ++position){
position->pos += shift_amount;
}
for (; position->pos < end && position < end_position; ++position){
position->pos = start + shift_amount;
}
shift_amount += (edit->len - (end - start));
}
for (; position < end_position; ++position){
position->pos += shift_amount;
}
}
internal_4tech int
eol_convert_in(char *dest, char *src, int size){
int i, j, k;
i = 0;
k = 0;
j = 0;
for (; j < size && src[j] != '\r'; ++j);
memcpy_4tech(dest, src, j);
if (j < size){
k = 1;
++j;
for (i = j; i < size; ++i){
if (src[i] == '\r'){
memcpy_4tech(dest + j - k, src + j, i - j);
++k;
j = i+1;
}
}
memcpy_4tech(dest + j - k, src + j, i - j);
j = i - k;
}
return(j);
}
internal_4tech int
eol_in_place_convert_in(char *data, int size){
int i, j, k;
i = 0;
k = 0;
j = 0;
for (; j < size && data[j] != '\r'; ++j);
if (j < size){
k = 1;
++j;
for (i = j; i < size; ++i){
if (data[i] == '\r'){
memmove_4tech(data + j - k, data + j, i - j);
++k;
j = i+1;
}
}
memmove_4tech(data + j - k, data + j, i - j);
j = i - k;
}
return(j);
}
internal_4tech int
eol_convert_out(char *dest, int max, char *src, int size, int *size_out){
int result;
int i, j;
// TODO(allen): iterative memory check?
result = 1;
i = 0;
j = 0;
for (; i < size; ++i, ++j){
if (src[i] == '\n'){
dest[j] = '\r';
++j;
dest[j] = '\n';
}
else dest[j] = src[i];
}
*size_out = j;
return(result);
}
internal_4tech int
eol_in_place_convert_out(char *data, int size, int max, int *size_out){
int result;
int i;
// TODO(allen): iterative memory check?
result = 1;
i = 0;
for (; i < size; ++i){
if (data[i] == '\n'){
memmove_4tech(data + i + 1, data + i, size - i);
data[i] = '\r';
++i;
++size;
}
}
*size_out = size;
return(result);
}
inline_4tech int
is_whitespace(char c){
int result;
result = (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v');
return(result);
}
inline_4tech int
is_alphanumeric_true(char c){
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9');
}
inline_4tech int
is_alphanumeric(char c){
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_');
}
inline_4tech int
is_upper(char c){
return (c >= 'A' && c <= 'Z');
}
inline_4tech int
is_lower(char c){
return (c >= 'a' && c <= 'z');
}
internal_4tech int
is_match(char *a, char *b, int len){
int result;
result = 1;
for (;len > 0; --len, ++a, ++b)
if (*a != *b) { result = 0; break; }
return(result);
}
// BOTTOM