/* The implementation for the custom API */ // TOP internal void fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *working_set){ *buffer = buffer_summary_zero(); if (!file->is_dummy){ buffer->exists = 1; buffer->ready = file_is_ready(file); buffer->is_lexed = file->settings.tokens_exist; buffer->buffer_id = file->id.id; buffer->size = file->state.buffer.size; buffer->buffer_cursor_pos = file->state.cursor_pos; buffer->file_name_len = file->name.source_path.size; buffer->buffer_name_len = file->name.live_name.size; buffer->file_name = file->name.source_path.str; buffer->buffer_name = file->name.live_name.str; buffer->map_id = file->settings.base_map_id; } } internal void fill_view_summary(View_Summary *view, View *vptr, Live_Views *live_set, Working_Set *working_set){ i32 lock_level; int buffer_id; *view = view_summary_zero(); if (vptr->in_use){ view->exists = 1; view->view_id = (int)(vptr - live_set->views) + 1; view->line_height = (float)(vptr->line_height); view->unwrapped_lines = vptr->file_data.unwrapped_lines; view->show_whitespace = vptr->file_data.show_whitespace; if (vptr->file_data.file){ lock_level = view_lock_level(vptr); buffer_id = vptr->file_data.file->id.id; if (lock_level <= 0){ view->buffer_id = buffer_id; } else{ view->buffer_id = 0; } if (lock_level <= 1){ view->locked_buffer_id = buffer_id; } else{ view->locked_buffer_id = 0; } if (lock_level <= 2){ view->hidden_buffer_id = buffer_id; } else{ view->hidden_buffer_id = 0; } view->mark = view_compute_cursor_from_pos(vptr, vptr->recent->mark); view->cursor = vptr->recent->cursor; view->preferred_x = vptr->recent->preferred_x; view->file_region = vptr->file_region; view->scroll_vars = *vptr->current_scroll; } } } internal Editing_File* get_file_from_identifier(System_Functions *system, Working_Set *working_set, Buffer_Identifier buffer){ i32 buffer_id = buffer.id; i32 buffer_name_len = buffer.name_len; char *buffer_name = buffer.name; Editing_File *file = 0; if (buffer_id){ file = working_set_get_active_file(working_set, buffer_id); } else if (buffer_name){ file = working_set_contains(system, working_set, make_string(buffer_name, buffer_name_len)); } return(file); } String make_string_terminated(Partition *part, char *str, int len){ char *space = (char*)push_array(part, char, len + 1); String string = make_string(str, len, len+1); copy_fast_unsafe(space, string); string.str = space; terminate_with_null(&string); return(string); } EXEC_COMMAND_SIG(external_exec_command){ Command_Data *cmd = (Command_Data*)app->cmd_context; Command_Function function = command_table[command_id]; Command_Binding binding = {}; binding.function = function; if (function) function(cmd->system, cmd, binding); update_command_data(cmd->vars, cmd); } // TODO(allen): This is a bit of a mess and needs to be fixed soon EXEC_SYSTEM_COMMAND_SIG(external_exec_system_command){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; App_Vars *vars = cmd->vars; Models *models = cmd->models; char feedback_space[256]; String feedback_str = make_fixed_width_string(feedback_space); Working_Set *working_set = &models->working_set; CLI_Process *procs = vars->cli_processes.procs, *proc = 0; Editing_File *file = 0; b32 bind_to_new_view = true; General_Memory *general = &models->mem.general; Partition *part = &models->mem.part; Temp_Memory temp = begin_temp_memory(part); View *vptr = 0; int result = true; if (view->exists){ Live_Views *live_set = cmd->live_set; i32 view_id = view->view_id - 1; if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; } } if (vptr == 0){ result = false; goto done; } if (vars->cli_processes.count < vars->cli_processes.max){ file = get_file_from_identifier(system, working_set, buffer); if (file){ if (file->settings.read_only == 0){ append(&feedback_str, "ERROR: "); append(&feedback_str, file->name.live_name); append(&feedback_str, " is not a read-only buffer\n"); do_feedback_message(system, models, feedback_str); result = false; goto done; } if (file->settings.never_kill){ append(&feedback_str, "The buffer "); append(&feedback_str, file->name.live_name); append(&feedback_str, " is not killable"); do_feedback_message(system, models, feedback_str); result = false; goto done; } } else if (buffer.name){ file = working_set_alloc_always(working_set, general); if (file == 0){ append(&feedback_str, "ERROR: unable to allocate a new buffer\n"); do_feedback_message(system, models, feedback_str); result = false; goto done; } file_create_read_only(system, models, file, buffer.name); working_set_add(system, working_set, file, general); } if (file){ i32 proc_count = vars->cli_processes.count; View_Iter iter; i32 i; for (i = 0; i < proc_count; ++i){ if (procs[i].out_file == file){ if (flags & CLI_OverlapWithConflict){ procs[i].out_file = 0; } else{ file = 0; } break; } } if (file){ file_clear(system, models, file, 1); file->settings.unimportant = 1; if (!(flags & CLI_AlwaysBindToView)){ iter = file_view_iter_init(&models->layout, file, 0); if (file_view_iter_good(iter)){ bind_to_new_view = 0; } } } else{ append(&feedback_str, "did not begin command-line command because the target buffer is already in use\n"); do_feedback_message(system, models, feedback_str); result = false; goto done; } } String path_string = {0}; if (!path){ terminate_with_null(&models->hot_directory.string); path_string = models->hot_directory.string; } else{ path_string = make_string_terminated(part, path, path_len); } { String command_string = {0}; if (!command){ #define NO_SCRIPT " echo no script specified" command_string.str = NO_SCRIPT; command_string.size = sizeof(NO_SCRIPT)-1; #undef NO_SCRIPT } else{ command_string = make_string_terminated(part, command, command_len); } if (bind_to_new_view){ view_set_file(vptr, file, models); view_show_file(vptr); } proc = procs + vars->cli_processes.count++; proc->out_file = file; if (!system->cli_call(path_string.str, command_string.str, &proc->cli)){ --vars->cli_processes.count; } } } else{ append(&feedback_str, "ERROR: no available process slot\n"); do_feedback_message(system, models, feedback_str); result = false; goto done; } done: end_temp_memory(temp); return(result); } DIRECTORY_GET_HOT_SIG(external_directory_get_hot){ Command_Data *cmd = (Command_Data*)app->cmd_context; Hot_Directory *hot = &cmd->models->hot_directory; i32 copy_max = capacity - 1; hot_directory_clean_end(hot); if (copy_max > hot->string.size) copy_max = hot->string.size; memcpy(out, hot->string.str, copy_max); out[copy_max] = 0; return(hot->string.size); } #define external_get_4ed_path system->get_4ed_path #define external_file_exists system->file_exists #define external_directory_cd system->directory_cd GET_FILE_LIST_SIG(external_get_file_list){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; File_List result = {}; system->set_file_list(&result, make_string(dir, len)); return(result); } FREE_FILE_LIST_SIG(external_free_file_list){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; system->set_file_list(&list, make_string(0, 0)); } CLIPBOARD_POST_SIG(external_clipboard_post){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; Models *models = cmd->models; General_Memory *general = &models->mem.general; Working_Set *working = &models->working_set; int result = false; String *dest = working_set_next_clipboard_string(general, working, len); copy(dest, make_string(str, len)); system->post_clipboard(*dest); return(result); } CLIPBOARD_COUNT_SIG(external_clipboard_count){ Command_Data *cmd = (Command_Data*)app->cmd_context; Working_Set *working = &cmd->models->working_set; int count = working->clipboard_size; return(count); } CLIPBOARD_INDEX_SIG(external_clipboard_index){ Command_Data *cmd = (Command_Data*)app->cmd_context; Working_Set *working = &cmd->models->working_set; int size = 0; String *str = working_set_clipboard_index(working, index); if (str){ size = str->size; if (out){ copy_fast_unsafe(out, *str); } } return(size); } GET_BUFFER_FIRST_SIG(external_get_buffer_first){ Command_Data *cmd = (Command_Data*)app->cmd_context; Working_Set *working_set = &cmd->models->working_set; Buffer_Summary result = {}; if (working_set->file_count > 0){ fill_buffer_summary(&result, (Editing_File*)working_set->used_sentinel.next, working_set); } return(result); } GET_BUFFER_NEXT_SIG(external_get_buffer_next){ Command_Data *cmd = (Command_Data*)app->cmd_context; Working_Set *working_set = &cmd->models->working_set; Editing_File *file; file = working_set_get_active_file(working_set, buffer->buffer_id); if (file){ file = (Editing_File*)file->node.next; fill_buffer_summary(buffer, file, working_set); } else{ *buffer = buffer_summary_zero(); } } GET_BUFFER_SIG(external_get_buffer){ Command_Data *cmd = (Command_Data*)app->cmd_context; Working_Set *working_set = &cmd->models->working_set; Buffer_Summary buffer = {}; Editing_File *file; file = working_set_get_active_file(working_set, index); if (file){ fill_buffer_summary(&buffer, file, working_set); } return(buffer); } GET_PARAMETER_BUFFER_SIG(external_get_parameter_buffer){ Command_Data *cmd = (Command_Data*)app->cmd_context; Models *models = cmd->models; Buffer_Summary buffer = {}; if (param_index >= 0 && param_index < models->buffer_param_count){ buffer = external_get_buffer(app, models->buffer_param_indices[param_index]); } return(buffer); } GET_BUFFER_BY_NAME_SIG(external_get_buffer_by_name){ Command_Data *cmd = (Command_Data*)app->cmd_context; Buffer_Summary buffer = {}; Editing_File *file; Working_Set *working_set = &cmd->models->working_set; file = working_set_contains(cmd->system, working_set, make_string(filename, len)); if (file && !file->is_dummy){ fill_buffer_summary(&buffer, file, working_set); } return(buffer); } REFRESH_BUFFER_SIG(external_refresh_buffer){ int result; *buffer = external_get_buffer(app, buffer->buffer_id); result = buffer->exists; return(result); } BUFFER_SEEK_SIG(external_buffer_seek){ Command_Data *cmd = (Command_Data*)app->cmd_context; Editing_File *file; Working_Set *working_set; int result = 0; if (buffer->exists){ working_set = &cmd->models->working_set; file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ // TODO(allen): reduce duplication? { i32 size = buffer_size(&file->state.buffer); i32 pos[4] = {0}; i32 new_pos = 0; if (start_pos < 0){ start_pos = 0; } else if (start_pos > size){ start_pos = size; } if (seek_forward){ for (i32 i = 0; i < ArrayCount(pos); ++i) pos[i] = size; if (flags & (1)){ pos[0] = buffer_seek_whitespace_right(&file->state.buffer, start_pos); } if (flags & (1 << 1)){ if (file->state.tokens_complete){ pos[1] = seek_token_right(&file->state.token_stack, start_pos); } else{ pos[1] = buffer_seek_whitespace_right(&file->state.buffer, start_pos); } } if (flags & (1 << 2)){ pos[2] = buffer_seek_alphanumeric_right(&file->state.buffer, start_pos); if (flags & (1 << 3)){ pos[3] = buffer_seek_range_camel_right(&file->state.buffer, start_pos, pos[2]); } } else{ if (flags & (1 << 3)){ pos[3] = buffer_seek_alphanumeric_or_camel_right(&file->state.buffer, start_pos); } } new_pos = size; for (i32 i = 0; i < ArrayCount(pos); ++i){ if (pos[i] < new_pos) new_pos = pos[i]; } } else{ if (flags & (1)){ pos[0] = buffer_seek_whitespace_left(&file->state.buffer, start_pos); } if (flags & (1 << 1)){ if (file->state.tokens_complete){ pos[1] = seek_token_left(&file->state.token_stack, start_pos); } else{ pos[1] = buffer_seek_whitespace_left(&file->state.buffer, start_pos); } } if (flags & (1 << 2)){ pos[2] = buffer_seek_alphanumeric_left(&file->state.buffer, start_pos); if (flags & (1 << 3)){ pos[3] = buffer_seek_range_camel_left(&file->state.buffer, start_pos, pos[2]); } } else{ if (flags & (1 << 3)){ pos[3] = buffer_seek_alphanumeric_or_camel_left(&file->state.buffer, start_pos); } } new_pos = 0; for (i32 i = 0; i < ArrayCount(pos); ++i){ if (pos[i] > new_pos) new_pos = pos[i]; } } result = new_pos; } fill_buffer_summary(buffer, file, working_set); } } return(result); } BUFFER_READ_RANGE_SIG(external_buffer_read_range){ Command_Data *cmd = (Command_Data*)app->cmd_context; Editing_File *file; Working_Set *working_set; int result = 0; int size; if (buffer->exists){ working_set = &cmd->models->working_set; file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ size = buffer_size(&file->state.buffer); if (0 <= start && start <= end && end <= size){ result = 1; buffer_stringify(&file->state.buffer, start, end, out); } fill_buffer_summary(buffer, file, working_set); } } return(result); } BUFFER_REPLACE_RANGE_SIG(external_buffer_replace_range){ Command_Data *cmd = (Command_Data*)app->cmd_context; Editing_File *file; Working_Set *working_set; Models *models; int result = 0; int size; int next_cursor, pos; if (buffer->exists){ models = cmd->models; working_set = &models->working_set; file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ size = buffer_size(&file->state.buffer); if (0 <= start && start <= end && end <= size){ result = 1; pos = file->state.cursor_pos; if (pos < start) next_cursor = pos; else if (pos < end) next_cursor = start; else next_cursor = pos + end - start - len; file_replace_range(cmd->system, models, file, start, end, str, len, next_cursor); } fill_buffer_summary(buffer, file, working_set); } } return(result); } #if 0 BUFFER_SET_POS_SIG(external_buffer_set_pos){ Command_Data *cmd = (Command_Data*)app->cmd_context; Editing_File *file; Working_Set *working_set; int result = 0; int size; if (buffer->exists){ working_set = &cmd->models->working_set; file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ result = 1; size = buffer_size(&file->state.buffer); if (pos < 0) pos = 0; if (pos > size) pos = size; file->state.cursor_pos = pos; fill_buffer_summary(buffer, file, working_set); } } return(result); } #endif BUFFER_SET_SETTING_SIG(external_buffer_set_setting){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; Models *models = cmd->models; Editing_File *file; Working_Set *working_set; int result = false; i32 new_mapid = 0; if (buffer->exists){ working_set = &models->working_set; file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && file_is_ready(file)){ result = true; switch (setting){ case BufferSetting_Lex: { #if BUFFER_EXPERIMENT_SCALPEL <= 0 if (file->settings.tokens_exist){ if (!value){ file_kill_tokens(system, &models->mem.general, file); } } else{ if (value){ file_first_lex_parallel(system, &models->mem.general, file); } } #endif }break; case BufferSetting_WrapLine: { file->settings.unwrapped_lines = !value; }break; case BufferSetting_MapID: { if (value == mapid_global){ file->settings.base_map_id = mapid_global; } else if (value == mapid_file){ file->settings.base_map_id = mapid_file; } else if (value < mapid_global){ new_mapid = get_map_index(models, value); if (new_mapid < models->user_map_count){ file->settings.base_map_id = value; } else{ file->settings.base_map_id = mapid_file; } } for (View_Iter iter = file_view_iter_init(&models->layout, file, 0); file_view_iter_good(iter); iter = file_view_iter_next(iter)){ iter.view->map = get_map(models, file->settings.base_map_id); } }break; } } fill_buffer_summary(buffer, file, working_set); } return(result); } BUFFER_SAVE_SIG(external_buffer_save){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; Models *models = cmd->models; Editing_File *file; Working_Set *working_set; int result = false; if (buffer->exists){ working_set = &models->working_set; file = working_set_get_active_file(working_set, buffer->buffer_id); if (file && !file->is_dummy && file_is_ready(file)){ result = true; String name = make_string(filename, filename_len); view_save_file(system, models, file, 0, name, 0); } } return(result); } GET_VIEW_FIRST_SIG(external_get_view_first){ Command_Data *cmd = (Command_Data*)app->cmd_context; Editing_Layout *layout = &cmd->models->layout; View_Summary view = {}; Panel *panel = layout->used_sentinel.next; Assert(panel != &layout->used_sentinel); fill_view_summary(&view, panel->view, &cmd->vars->live_set, &cmd->models->working_set); return(view); } GET_VIEW_NEXT_SIG(external_get_view_next){ Command_Data *cmd = (Command_Data*)app->cmd_context; Editing_Layout *layout = &cmd->models->layout; Live_Views *live_set = &cmd->vars->live_set; View *vptr; Panel *panel; int index = view->view_id - 1; if (index >= 0 && index < live_set->max){ vptr = live_set->views + index; panel = vptr->panel; if (panel) panel = panel->next; if (panel && panel != &layout->used_sentinel){ fill_view_summary(view, panel->view, &cmd->vars->live_set, &cmd->models->working_set); } else{ *view = view_summary_zero(); } } else{ *view = view_summary_zero(); } } GET_VIEW_SIG(external_get_view){ Command_Data *cmd = (Command_Data*)app->cmd_context; View_Summary view = {}; Live_Views *live_set = cmd->live_set; int max = live_set->max; View *vptr; index -= 1; if (index >= 0 && index < max){ vptr = live_set->views + index; fill_view_summary(&view, vptr, live_set, &cmd->models->working_set); } return(view); } GET_ACTIVE_VIEW_SIG(external_get_active_view){ Command_Data *cmd = (Command_Data*)app->cmd_context; View_Summary view = {}; fill_view_summary(&view, cmd->view, &cmd->vars->live_set, &cmd->models->working_set); return(view); } REFRESH_VIEW_SIG(external_refresh_view){ int result; *view = external_get_view(app, view->view_id); result = view->exists; return(result); } VIEW_AUTO_TAB_SIG(external_view_auto_tab){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; Models *models = cmd->models; int result = false; Live_Views *live_set; Editing_File *file; View *vptr; int view_id; if (view->exists){ live_set = cmd->live_set; view_id = view->view_id - 1; if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; file = vptr->file_data.file; if (file && file->state.token_stack.tokens && file->state.tokens_complete && !file->state.still_lexing){ result = true; Indent_Options opts; opts.empty_blank_lines = (flags & AutoTab_ClearLine); opts.use_tabs = (flags & AutoTab_UseTab); opts.tab_width = tab_width; view_auto_tab_tokens(system, models, vptr, start, end, opts); } } } return(result); } VIEW_COMPUTE_CURSOR_SIG(external_view_compute_cursor){ Command_Data *cmd = (Command_Data*)app->cmd_context; Live_Views *live_set; View *vptr; Editing_File *file; Full_Cursor result = {0}; int view_id; if (view->exists){ live_set = cmd->live_set; view_id = view->view_id - 1; if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; file = vptr->file_data.file; if (file && !file->is_loading){ if (seek.type == buffer_seek_line_char && seek.character <= 0){ seek.character = 1; } result = view_compute_cursor(vptr, seek); fill_view_summary(view, vptr, live_set, &cmd->models->working_set); } } } return(result); } VIEW_SET_CURSOR_SIG(external_view_set_cursor){ Command_Data *cmd = (Command_Data*)app->cmd_context; Live_Views *live_set; View *vptr; Editing_File *file; int result = 0; int view_id; if (view->exists){ live_set = cmd->live_set; view_id = view->view_id - 1; if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; file = vptr->file_data.file; if (file && !file->is_loading){ result = 1; if (seek.type == buffer_seek_line_char && seek.character <= 0){ seek.character = 1; } vptr->recent->cursor = view_compute_cursor(vptr, seek); if (set_preferred_x){ vptr->recent->preferred_x = view_get_cursor_x(vptr); } fill_view_summary(view, vptr, live_set, &cmd->models->working_set); file->state.cursor_pos = vptr->recent->cursor.pos; } } } return(result); } VIEW_SET_MARK_SIG(external_view_set_mark){ Command_Data *cmd = (Command_Data*)app->cmd_context; Live_Views *live_set; View *vptr; Full_Cursor cursor; int result = 0; int view_id; if (view->exists){ live_set = cmd->live_set; view_id = view->view_id - 1; if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; result = 1; if (seek.type != buffer_seek_pos){ cursor = view_compute_cursor(vptr, seek); vptr->recent->mark = cursor.pos; } else{ vptr->recent->mark = seek.pos; } fill_view_summary(view, vptr, live_set, &cmd->models->working_set); } } return(result); } VIEW_SET_HIGHLIGHT_SIG(external_view_set_highlight){ Command_Data *cmd = (Command_Data*)app->cmd_context; Live_Views *live_set; View *vptr; int result = 0; int view_id; if (view->exists){ live_set = cmd->live_set; view_id = view->view_id - 1; if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; result = 1; if (turn_on){ view_set_temp_highlight(vptr, start, end); } else{ vptr->file_data.show_temp_highlight = 0; } fill_view_summary(view, vptr, live_set, &cmd->models->working_set); } } return(result); } VIEW_SET_BUFFER_SIG(external_view_set_buffer){ Command_Data *cmd = (Command_Data*)app->cmd_context; Live_Views *live_set; View *vptr; Editing_File *file; Working_Set *working_set; Models *models; int result = 0; int view_id; if (view->exists){ models = cmd->models; live_set = cmd->live_set; view_id = view->view_id - 1; if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; working_set = &models->working_set; file = working_set_get_active_file(working_set, buffer_id); if (file){ result = 1; if (file != vptr->file_data.file){ view_set_file(vptr, file, models); view_show_file(vptr); } } fill_view_summary(view, vptr, live_set, working_set); } } return(result); } VIEW_OPEN_FILE_SIG(external_view_open_file){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; Models *models = cmd->models; Working_Set *working_set = &models->working_set; Live_Views *live_set = cmd->live_set; int result = false; // TODO(allen): do in background option Partition *part = &models->mem.part; Temp_Memory temp = begin_temp_memory(part); String string = make_string_terminated(part, filename, filename_len); if (do_in_background){ result = true; view_open_file(system, models, 0, string); } else if (view){ View *vptr = 0; int view_id = view->view_id - 1; if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; result = true; view_open_file(system, models, 0, string); fill_view_summary(view, vptr, live_set, working_set); } } end_temp_memory(temp); return(result); } VIEW_KILL_BUFFER_SIG(external_view_kill_buffer){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; Live_Views *live_set; View *vptr; Editing_File *file; Working_Set *working_set; Models *models; int result = false; int view_id; if (view->exists){ models = cmd->models; live_set = cmd->live_set; view_id = view->view_id - 1; if (view_id >= 0 && view_id < live_set->max){ vptr = live_set->views + view_id; working_set = &models->working_set; file = get_file_from_identifier(system, working_set, buffer); if (file){ result = true; try_kill_file(system, models, file, vptr, string_zero()); fill_view_summary(view, vptr, live_set, working_set); } } } return(result); } GET_USER_INPUT_SIG(external_get_user_input){ Command_Data *cmd = (Command_Data*)app->cmd_context; System_Functions *system = cmd->system; Coroutine *coroutine = (Coroutine*)app->current_coroutine; User_Input result = {0}; if (app->type_coroutine == Co_Command){ Assert(coroutine); *((u32*)coroutine->out+0) = get_type; *((u32*)coroutine->out+1) = abort_type; system->yield_coroutine(coroutine); result = *(User_Input*)coroutine->in; } return(result); } GET_COMMAND_INPUT_SIG(external_get_command_input){ Command_Data *cmd = (Command_Data*)app->cmd_context; User_Input result; result.type = UserInputKey; result.abort = 0; result.key = cmd->key; result.command = 0; return(result); } GET_MOUSE_STATE_SIG(external_get_mouse_state){ Command_Data *cmd = (Command_Data*)app->cmd_context; App_Vars *vars = cmd->vars; Mouse_State mouse = direct_get_mouse_state(&vars->available_input); return(mouse); } GET_EVENT_MESSAGE_SIG(external_get_event_message){ Event_Message message = {0}; System_Functions *system = (System_Functions*)app->system_links; Coroutine *coroutine = (Coroutine*)app->current_coroutine; if (app->type_coroutine == Co_View){ Assert(coroutine); system->yield_coroutine(coroutine); message = *(Event_Message*)coroutine->in; } return(message); } START_QUERY_BAR_SIG(external_start_query_bar){ Command_Data *cmd = (Command_Data*)app->cmd_context; Query_Slot *slot = 0; View *vptr; vptr = cmd->view; slot = alloc_query_slot(&vptr->query_set); slot->query_bar = bar; return(slot != 0); } END_QUERY_BAR_SIG(external_end_query_bar){ Command_Data *cmd = (Command_Data*)app->cmd_context; View *vptr; vptr = cmd->view; free_query_slot(&vptr->query_set, bar); } PRINT_MESSAGE_SIG(external_print_message){ Command_Data *cmd = (Command_Data*)app->cmd_context; Models *models = cmd->models; do_feedback_message(cmd->system, models, make_string(string, len)); } #if 0 GET_GUI_FUNCTIONS_SIG(external_get_gui_functions){ GUI_Functions *guifn = 0; NotImplemented; return(guifn); } GET_GUI_SIG(external_get_gui){ GUI *gui = 0; NotImplemented; return(gui); } #endif CHANGE_THEME_SIG(external_change_theme){ Command_Data *cmd = (Command_Data*)app->cmd_context; Style_Library *styles = &cmd->models->styles; String theme_name = make_string(name, len); Style *s; i32 i, count; count = styles->count; s = styles->styles; for (i = 0; i < count; ++i, ++s){ if (match(s->name, theme_name)){ style_copy(main_style(cmd->models), s); break; } } } CHANGE_FONT_SIG(external_change_font){ Command_Data *cmd = (Command_Data*)app->cmd_context; Font_Set *set = cmd->models->font_set; Style_Font *global_font = &cmd->models->global_font; String font_name = make_string(name, len); i16 font_id; if (font_set_extract(set, font_name, &font_id)){ global_font->font_id = font_id; global_font->font_changed = 1; } } SET_THEME_COLORS_SIG(external_set_theme_colors){ Command_Data *cmd = (Command_Data*)app->cmd_context; Style *style = main_style(cmd->models); Theme_Color *theme_color; u32 *color; i32 i; theme_color = colors; for (i = 0; i < count; ++i, ++theme_color){ color = style_index_by_tag(&style->main, theme_color->tag); if (color) *color = theme_color->color | 0xFF000000; } } // BOTTOM