/* AneoEngine AnchorSand Filesystem. AneoC source file */ #include //TDs TD U C U8; TD U S U16; TD U INT U32; //Kernel externs extern VD print(CC *s); extern VD printINT(INT n); extern U8 color; extern INT getkey(VD); extern VD kb_drain_mouse(VD); extern U INT cx; extern U INT cy; extern INT shift; extern VD cursor_update(VD); extern VD clear(VD); extern VD screen_get_cell(INT i, C *c, U8 *col); extern VD screen_set_cell(INT i, C c, U8 col); extern VD screen_put_at(INT x, INT y, C c, U8 col); extern INT con_x; extern INT con_y; extern INT con_w; extern INT con_h; extern INT as_save_to_disk(VD); //Macros, vars U INT saveit = 0; #define AS_MAX_NODES 64 #define AS_NAME_MAX 32 #define AS_DATA_MAX 4096 #define AS_FILE 1 #define AS_DIR 2 VD print_red(C *string) {//shell error funtion U8 oldcolor = color; color = 0xCF; print("ERROR:"); color = oldcolor; print(" "); print(string); } TD ST { C name[AS_NAME_MAX]; C data[AS_DATA_MAX]; INT size; INT type; INT used; INT parent; } ASNode; ASNode as_nodes[AS_MAX_NODES]; INT as_cwd = 0; VD as_copy_str(C *destination, CC *source) {//Copy source string to destination string. while(*source) *destination++ = *source++; *destination = 0; } INT as_compare_equal_str(CC *string_1, CC *string_2) {//Compare two strings; if both are exact, ret. while(*string_1 && *string_2) { if(*string_1 != *string_2) return 0; string_1++; string_2++; } return *string_1 == *string_2; } INT as_lengthof_str(CC *string) {//Counth string length INT index = 0; while(string[index]) index++; return index; } INT as_compare_str(CC *string_1, CC *string_2) {//Compare two strings; if both are same chars, ret 0. C string_1_chr; C string_2_chr; while(*string_1 && *string_2) { string_1_chr = *string_1; string_2_chr = *string_2; if(string_1_chr >= 'A' && string_1_chr <= 'Z') string_1_chr += 32; if(string_2_chr >= 'A' && string_2_chr <= 'Z') string_2_chr += 32; if(string_1_chr < string_2_chr) return -1; if(string_1_chr > string_2_chr) return 1; string_1++; string_2++; } if(!*string_1 && *string_2) return -1; if(*string_1 && !*string_2) return 1; return 0; } VD as_init() {//Initialize AnchorSand INT index; print("AS_MAX_NODES="); printINT(AS_MAX_NODES); print("\nAS_NAME_MAX="); printINT(AS_NAME_MAX); print("\nAS_DATA_MAX="); printINT(AS_DATA_MAX); for(index = 0; index < AS_MAX_NODES; index++) as_nodes[index].used = 0; as_nodes[0].used = index; as_nodes[0].type = AS_DIR; as_nodes[0].parent = 0; as_nodes[0].size = 0; as_copy_str(as_nodes[0].name, "/"); } INT as_node_allocator() {//Node allocator INT index; for(index = 1; index < AS_MAX_NODES; index++) { if(!as_nodes[index].used) return index; } return -1; } INT as_find_child(INT parent, CC *name) {//used child node finder with parent and name INT index; for(index = 0; index < AS_MAX_NODES; index++) { if( as_nodes[index].used && as_nodes[index].parent == parent && as_compare_equal_str(as_nodes[index].name, name) ) return index; } return -1; } VD as_split_path(CC *path, C *parent, C *name) {//splits a path into 2 seperate strings. INT length; INT index; INT last_slash; parent[0] = 0; name[0] = 0; length = as_lengthof_str(path); last_slash = -1; for(index = 0; index < length; index++) { if(path[index] == '/') last_slash = index; } if(last_slash == -1) { as_copy_str(parent, "."); as_copy_str(name, path); return; } if(last_slash == 0) { as_copy_str(parent, "/"); as_copy_str(name, path + 1); return; } for(index = 0; index < last_slash; index++) parent[index] = path[index]; parent[last_slash] = 0; as_copy_str(name, path + last_slash + 1); } INT as_resolve_path(CC *path) {//resolve FS path into node index INT current_node; INT path_index; INT part_index; INT node_index; C part[AS_NAME_MAX]; if(!path || !path[0]) return as_cwd; if(path[0] == '/') { current_node = 0; path_index = 1; } else { current_node = as_cwd; path_index = 0; } while(1) { while(path[path_index] == '/') path_index++; if(!path[path_index]) return current_node; part_index = 0; while(path[path_index] && path[path_index] != '/' && path_index < AS_NAME_MAX - 1) part[part_index++] = path[path_index++]; part[part_index] = 0; if(as_compare_equal_str(part, ".")) continue; if(as_compare_equal_str(part, "..")) { if(current_node != 0) current_node = as_nodes[current_node].parent; continue; } node_index = as_find_child(current_node, part); if(node_index == -1) return -1; current_node = node_index; } } INT as_mkdir_at(INT parent, CC *name) {//mkdir node under parent INT node_index; if(!name[0]) return -1; if(as_find_child(parent, name) != -1) return -1; node_index = as_node_allocator(); if(node_index == -1) return -1; as_nodes[node_index].used = 1; as_nodes[node_index].type = AS_DIR; as_nodes[node_index].size = 0; as_nodes[node_index].parent = parent; as_copy_str(as_nodes[node_index].name, name); if(saveit == 1) as_save_to_disk(); return 0; } INT as_touch_at(INT parent, CC *name) {//new empty node under parent. INT node_index; if(!name[0]) return -1; if(as_find_child(parent, name) != -1) return -1; node_index = as_node_allocator(); if(node_index == -1) return -1; as_nodes[node_index].used = 1; as_nodes[node_index].type = AS_FILE; as_nodes[node_index].size = 0; as_nodes[node_index].parent = parent; as_copy_str(as_nodes[node_index].name, name); as_nodes[node_index].data[0] = 0; if(saveit == 1) as_save_to_disk(); return 0; } INT as_mkdir(CC *path) {//make new directory. C parent_path[AS_NAME_MAX * 4]; C name[AS_NAME_MAX]; INT parent; as_split_path(path, parent_path, name); parent = as_resolve_path(parent_path); if(parent == -1) return -1; if(as_nodes[parent].type != AS_DIR) return -1; return as_mkdir_at(parent, name); } INT as_touch(CC *path) {//make new regular file. C parent_path[AS_NAME_MAX * 4]; C name[AS_NAME_MAX]; INT parent; as_split_path(path, parent_path, name); parent = as_resolve_path(parent_path); if(parent == -1) return -1; if(as_nodes[parent].type != AS_DIR) return -1; return as_touch_at(parent, name); } INT as_write(CC *path, CC *text) {//overwrite text file C parent_path[AS_NAME_MAX * 4]; C name[AS_NAME_MAX]; INT parent; INT node_index; INT index; as_split_path(path, parent_path, name); parent = as_resolve_path(parent_path); if(parent == -1) return -1; if(as_nodes[parent].type != AS_DIR) return -1; node_index = as_find_child(parent, name); if(node_index == -1) { if(as_touch_at(parent, name) != 0) return -1; node_index = as_find_child(parent, name); } if(as_nodes[node_index].type != AS_FILE) return -1; for(index = 0; text[index] && index < AS_DATA_MAX - 1; index++) as_nodes[node_index].data[index] = text[index]; as_nodes[node_index].data[index] = 0; as_nodes[node_index].size = index; if(saveit == 1) as_save_to_disk(); return 0; } VD as_cat(CC *path) {//cat a text file from path INT node_index; node_index = as_resolve_path(path); if(node_index == -1) { print_red("File not found\n"); return; } if(as_nodes[node_index].type != AS_FILE) { print_red("Not a readable file\n"); return; } print(as_nodes[node_index].data); print("\n"); } VD as_ls_node(INT dir) {//list nodes INT index; INT sorting_index; INT child_node_count = 0; INT entries[AS_MAX_NODES]; INT temp; print("DIR..........: .\n"); print("DIR..........: ..\n"); for(index = 0; index < AS_MAX_NODES; index++) { if( as_nodes[index].used && as_nodes[index].parent == dir && index != dir ) { entries[child_node_count++] = index; } } for(index = 0; index < child_node_count - 1; index++) { for(sorting_index = index + 1; sorting_index < child_node_count; sorting_index++) { INT node_index_1 = entries[index]; INT node_index_2 = entries[sorting_index]; INT swap = 0; if(as_nodes[node_index_1].type != as_nodes[node_index_2].type) { if(as_nodes[node_index_1].type != AS_DIR) swap = 1; } else { if(as_compare_str(as_nodes[node_index_1].name, as_nodes[node_index_2].name) > 0) swap = 1; } if(swap) { temp = entries[index]; entries[index] = entries[sorting_index]; entries[sorting_index] = temp; } } } for(index = 0; index < child_node_count; index++) { INT node_index = entries[index]; if(as_nodes[node_index].type == AS_DIR) { print("DIR..........: "); print(as_nodes[node_index].name); } else { U8 oldcolor; print("FILE.........: "); oldcolor = color; color = 0x1C; print(as_nodes[node_index].name); color = oldcolor; } print("\n"); } } VD as_ls() {//list current dir. as_ls_node(as_cwd); } VD as_ls_path(CC *path) {//list a different dir. INT node_index; node_index = as_resolve_path(path); if(node_index == -1) { print_red("Directory not found\n"); return; } if(as_nodes[node_index].type != AS_DIR) { print_red("Not a directory\n"); return; } as_ls_node(node_index); } INT as_cd(CC *path) {//change current directory. INT node_index; node_index = as_resolve_path(path); if(node_index == -1) return -1; if(as_nodes[node_index].type != AS_DIR) return -1; as_cwd = node_index; return 0; } VD as_pwd_recursively(INT node_index) {//recursively build the full path if(node_index == 0) { print("/"); return; } as_pwd_recursively(as_nodes[node_index].parent); if(as_nodes[node_index].parent != 0) print("/"); print(as_nodes[node_index].name); } VD as_pwd() {//print working directory as_pwd_recursively(as_cwd); } //macros and vars for editor #define EDIT_KEY_UP 0x101 #define EDIT_KEY_DOWN 0x102 #define EDIT_KEY_LEFT 0x103 #define EDIT_KEY_RIGHT 0x104 #define EDIT_TOP 3 #define EDIT_W 80 #define EDIT_H 60 C edit_saved_chrs[EDIT_W * EDIT_H]; U8 edit_saved_display_attributes[EDIT_W * EDIT_H]; INT as_edit_w(VD) { if(con_w > 0 && con_w <= EDIT_W) return con_w; return EDIT_W; } INT as_edit_h(VD) { if(con_h > EDIT_TOP && con_h <= EDIT_H) return con_h; return EDIT_H; } INT as_edit_line_of_pos(INT count, INT pos) { INT index; INT line; line = 0; for(index = 0; index < pos && index < as_nodes[count].size; index++) { if(as_nodes[count].data[index] == '\n') line++; } return line; } VD as_edit_save_screen(U INT *oldcx, U INT *oldcy, U8 *oldcolor) { INT x_coordinate; INT y_coordinate; INT width; INT height; INT source_index; INT destination_index; *oldcx = cx; *oldcy = cy; *oldcolor = color; width = as_edit_w(); height = as_edit_h(); for(y_coordinate = 0; y_coordinate < height; y_coordinate++) { for(x_coordinate = 0; x_coordinate < width; x_coordinate++) { source_index = (con_y + y_coordinate) * EDIT_W + con_x + x_coordinate; destination_index = y_coordinate * EDIT_W + x_coordinate; screen_get_cell(source_index, &edit_saved_chrs[destination_index], &edit_saved_display_attributes[destination_index]); } } } VD as_edit_restore_screen(U INT oldcx, U INT oldcy, U8 oldcolor) { INT x_coordinate; INT y_coordinate; INT width; INT height; INT destination_index; width = as_edit_w(); height = as_edit_h(); for(y_coordinate = 0; y_coordinate < height; y_coordinate++) { for(x_coordinate = 0; x_coordinate < width; x_coordinate++) { destination_index = y_coordinate * EDIT_W + x_coordinate; screen_put_at(con_x + x_coordinate, con_y + y_coordinate, edit_saved_chrs[destination_index], edit_saved_display_attributes[destination_index]); } } cx = oldcx; cy = oldcy; color = oldcolor; cursor_update(); } VD as_edit_put_at(INT x_coordinate, INT y_coordinate, C character, U8 col) { if(x_coordinate < 0 || x_coordinate >= as_edit_w()) return; if(y_coordinate < 0 || y_coordinate >= as_edit_h()) return; screen_put_at(con_x + x_coordinate, con_y + y_coordinate, character, col); } VD as_edit_clear_editor_area(VD) { INT x_coordinate; INT y_coordinate; for(y_coordinate = EDIT_TOP; y_coordinate < as_edit_h(); y_coordinate++) { for(x_coordinate = 0; x_coordinate < as_edit_w(); x_coordinate++) as_edit_put_at(x_coordinate, y_coordinate, ' ', color); } } INT as_edit_line_start(INT count, INT pos) { while(pos > 0 && as_nodes[count].data[pos - 1] != '\n') pos--; return pos; } INT as_edit_line_end(INT count, INT pos) { while(pos < as_nodes[count].size && as_nodes[count].data[pos] != '\n') pos++; return pos; } INT as_edit_col(INT count, INT pos) { return pos - as_edit_line_start(count, pos); } INT as_edit_prev_line(INT count, INT pos) { INT start; INT col; INT prev_end; INT prev_start; INT prev_len; start = as_edit_line_start(count, pos); if(start == 0) return pos; col = pos - start; prev_end = start - 1; prev_start = as_edit_line_start(count, prev_end); prev_len = prev_end - prev_start; if(col > prev_len) col = prev_len; return prev_start + col; } INT as_edit_next_line(INT count, INT pos) { INT col; INT end; INT next_start; INT next_end; INT next_len; col = as_edit_col(count, pos); end = as_edit_line_end(count, pos); if(end >= as_nodes[count].size) return pos; next_start = end + 1; next_end = as_edit_line_end(count, next_start); next_len = next_end - next_start; if(col > next_len) col = next_len; return next_start + col; } VD as_edit_cursor(INT count, INT pos, INT scroll) { INT index; INT x_coordinate; INT y_coordinate; INT line; x_coordinate = 0; y_coordinate = EDIT_TOP; line = 0; for(index = 0; index < pos; index++) { if(as_nodes[count].data[index] == '\n') { line++; x_coordinate = 0; } else { x_coordinate++; if(x_coordinate >= as_edit_w()) { x_coordinate = 0; line++; } } } cx = x_coordinate; cy = EDIT_TOP + (line - scroll); if(cy < EDIT_TOP) cy = EDIT_TOP; if(cy >= (U INT)as_edit_h()) cy = as_edit_h() - 1; cursor_update(); } VD as_edit_draw_header(CC *path) { clear(); cx = 0; cy = 1; print("EDITOR: "); print(path); print("\n\n"); } VD as_edit_redraw(INT count, CC *path, INT pos, INT scroll) { INT index; INT x_coordinate; INT y_coordinate; INT line; as_edit_draw_header(path); as_edit_clear_editor_area(); x_coordinate = 0; line = 0; for(index = 0; index < as_nodes[count].size; index++) { y_coordinate = EDIT_TOP + (line - scroll); if(as_nodes[count].data[index] == '\n') { x_coordinate = 0; line++; continue; } if(y_coordinate >= EDIT_TOP && y_coordinate < as_edit_h()) as_edit_put_at(x_coordinate, y_coordinate, as_nodes[count].data[index], color); x_coordinate++; if(x_coordinate >= as_edit_w()) { x_coordinate = 0; line++; } if(y_coordinate >= as_edit_h() && line > scroll + as_edit_h()) break; } as_edit_cursor(count, pos, scroll); } VD as_edit_insert(INT count, INT *pos, INT character_value) { INT index; if(as_nodes[count].size >= AS_DATA_MAX - 1) return; index = as_nodes[count].size; while(index >= *pos) { as_nodes[count].data[index + 1] = as_nodes[count].data[index]; if(index == 0) break; index--; } as_nodes[count].data[*pos] = character_value; (*pos)++; as_nodes[count].size++; as_nodes[count].data[as_nodes[count].size] = 0; } VD as_edit_backspace(INT count, INT *pos) { INT index; if(*pos <= 0) return; for(index = *pos - 1; index < as_nodes[count].size; index++) as_nodes[count].data[index] = as_nodes[count].data[index + 1]; (*pos)--; as_nodes[count].size--; if(as_nodes[count].size < 0) as_nodes[count].size = 0; as_nodes[count].data[as_nodes[count].size] = 0; } VD as_edit_restore_file(INT count, C *olddata, INT oldsize) { INT index; for(index = 0; index <= oldsize && index < AS_DATA_MAX; index++) as_nodes[count].data[index] = olddata[index]; as_nodes[count].size = oldsize; as_nodes[count].data[as_nodes[count].size] = 0; } VD as_edit_fix_scroll(INT count, INT pos, INT *scroll) { INT cursor_line; INT visible_lines; cursor_line = as_edit_line_of_pos(count, pos); visible_lines = as_edit_h() - EDIT_TOP; if(cursor_line < *scroll) *scroll = cursor_line; if(cursor_line >= *scroll + visible_lines) *scroll = cursor_line - visible_lines + 1; if(*scroll < 0) *scroll = 0; } VD as_edit(CC *path) { C parent_path[AS_NAME_MAX * 4]; C name[AS_NAME_MAX]; C olddata[AS_DATA_MAX]; INT oldsize; INT parent; INT count; INT index; INT pos; INT character_value; INT scroll; U INT oldcx; U INT oldcy; U8 oldcolor; as_edit_save_screen(&oldcx, &oldcy, &oldcolor); as_split_path(path, parent_path, name); parent = as_resolve_path(parent_path); if(parent == -1) { as_edit_restore_screen(oldcx, oldcy, oldcolor); print_red("Directory not found\n"); return; } if(as_nodes[parent].type != AS_DIR) { as_edit_restore_screen(oldcx, oldcy, oldcolor); print_red("Not a directory\n"); return; } count = as_find_child(parent, name); if(count == -1) { if(as_touch_at(parent, name) != 0) { as_edit_restore_screen(oldcx, oldcy, oldcolor); print_red("Could not create file\n"); return; } count = as_find_child(parent, name); } if(as_nodes[count].type != AS_FILE) { as_edit_restore_screen(oldcx, oldcy, oldcolor); print_red("Not a readable file\n"); return; } oldsize = as_nodes[count].size; for(index = 0; index <= oldsize && index < AS_DATA_MAX; index++) olddata[index] = as_nodes[count].data[index]; pos = as_nodes[count].size; scroll = 0; as_edit_fix_scroll(count, pos, &scroll); as_edit_redraw(count, path, pos, scroll); for(;;) { kb_drain_mouse(); character_value = getkey(); if(!character_value) continue; if(character_value == 19) { as_edit_restore_screen(oldcx, oldcy, oldcolor); if(saveit == 1) as_save_to_disk(); return; } if(character_value == 16 && shift) { as_edit_restore_file(count, olddata, oldsize); as_edit_restore_screen(oldcx, oldcy, oldcolor); return; } if(character_value == EDIT_KEY_LEFT) { if(pos > 0) pos--; as_edit_fix_scroll(count, pos, &scroll); as_edit_redraw(count, path, pos, scroll); continue; } if(character_value == EDIT_KEY_RIGHT) { if(pos < as_nodes[count].size) pos++; as_edit_fix_scroll(count, pos, &scroll); as_edit_redraw(count, path, pos, scroll); continue; } if(character_value == EDIT_KEY_UP) { pos = as_edit_prev_line(count, pos); as_edit_fix_scroll(count, pos, &scroll); as_edit_redraw(count, path, pos, scroll); continue; } if(character_value == EDIT_KEY_DOWN) { pos = as_edit_next_line(count, pos); as_edit_fix_scroll(count, pos, &scroll); as_edit_redraw(count, path, pos, scroll); continue; } if(character_value == '\b') { as_edit_backspace(count, &pos); as_edit_fix_scroll(count, pos, &scroll); as_edit_redraw(count, path, pos, scroll); continue; } as_edit_insert(count, &pos, character_value); as_edit_fix_scroll(count, pos, &scroll); as_edit_redraw(count, path, pos, scroll); } } //Per-window editor state machine. Unlike as_edit() above, //these do not block: the kernel window manager feeds keys //in one at a time, so other windows keep running. #define as_edit_wINS 6 #define AS_EDIT_PATH_MAX 128 INT as_ew_open_flag[as_edit_wINS]; INT as_ew_node[as_edit_wINS]; INT as_ew_pos[as_edit_wINS]; INT as_ew_scroll[as_edit_wINS]; INT as_ew_oldsize[as_edit_wINS]; C as_ew_old[as_edit_wINS][AS_DATA_MAX]; C as_ew_path[as_edit_wINS][AS_EDIT_PATH_MAX]; INT as_edit_win_open(INT window_id) { return window_id >= 0 && window_id < as_edit_wINS && as_ew_open_flag[window_id]; } INT as_edit_open_win(INT identifier, CC *path) {//open the editor inside window id, drawing INTo the //currently loaded console. Returns 0 on success. C parent_path[AS_NAME_MAX * 4]; C name[AS_NAME_MAX]; INT parent; INT count; INT index; if(identifier < 0 || identifier >= as_edit_wINS) return -1; as_split_path(path, parent_path, name); parent = as_resolve_path(parent_path); if(parent == -1) { print_red("Directory not found\n"); return -1; } if(as_nodes[parent].type != AS_DIR) { print_red("Not a directory\n"); return -1; } count = as_find_child(parent, name); if(count == -1) { if(as_touch_at(parent, name) != 0) { print_red("Could not create file\n"); return -1; } count = as_find_child(parent, name); } if(as_nodes[count].type != AS_FILE) { print_red("Not a readable file\n"); return -1; } as_ew_node[identifier] = count; as_ew_oldsize[identifier] = as_nodes[count].size; for(index = 0; index <= as_ew_oldsize[identifier] && index < AS_DATA_MAX; index++) as_ew_old[identifier][index] = as_nodes[count].data[index]; index = 0; while(path[index] && index < AS_EDIT_PATH_MAX - 1) { as_ew_path[identifier][index] = path[index]; index++; } as_ew_path[identifier][index] = 0; as_ew_pos[identifier] = as_nodes[count].size; as_ew_scroll[identifier] = 0; as_ew_open_flag[identifier] = 1; as_edit_fix_scroll(as_ew_node[identifier], as_ew_pos[identifier], &as_ew_scroll[identifier]); as_edit_redraw(as_ew_node[identifier], as_ew_path[identifier], as_ew_pos[identifier], as_ew_scroll[identifier]); return 0; } VD as_edit_win_refresh(INT window_id) {//redraw the editor, e.g. after the window was resized if(!as_edit_win_open(window_id)) return; as_edit_fix_scroll(as_ew_node[window_id], as_ew_pos[window_id], &as_ew_scroll[window_id]); as_edit_redraw(as_ew_node[window_id], as_ew_path[window_id], as_ew_pos[window_id], as_ew_scroll[window_id]); } VD as_edit_win_close(INT window_id) {//drop editor state without touching the file if(window_id >= 0 && window_id < as_edit_wINS) as_ew_open_flag[window_id] = 0; } INT as_edit_win_mem(INT window_id) {//bytes of editor state held open for this window if(!as_edit_win_open(window_id)) return 0; return AS_DATA_MAX + AS_EDIT_PATH_MAX + 5 * (INT)sizeof(INT); } CC *as_edit_win_path(INT window_id) {//path of the file being edited in this window if(!as_edit_win_open(window_id)) return ""; return as_ew_path[window_id]; } INT as_edit_key_win(INT identifier, INT character_code) {//handle one key for the window editor. //Returns 1 when the editor closed, 0 otherwise. INT count; if(!as_edit_win_open(identifier)) return 1; count = as_ew_node[identifier]; if(character_code == 19) { as_ew_open_flag[identifier] = 0; if(saveit == 1) as_save_to_disk(); return 1; } if(character_code == 16 && shift) { as_edit_restore_file(count, as_ew_old[identifier], as_ew_oldsize[identifier]); as_ew_open_flag[identifier] = 0; return 1; } if(character_code == EDIT_KEY_LEFT) { if(as_ew_pos[identifier] > 0) as_ew_pos[identifier]--; } else if(character_code == EDIT_KEY_RIGHT) { if(as_ew_pos[identifier] < as_nodes[count].size) as_ew_pos[identifier]++; } else if(character_code == EDIT_KEY_UP) as_ew_pos[identifier] = as_edit_prev_line(count, as_ew_pos[identifier]); else if(character_code == EDIT_KEY_DOWN) as_ew_pos[identifier] = as_edit_next_line(count, as_ew_pos[identifier]); else if(character_code == '\b') as_edit_backspace(count, &as_ew_pos[identifier]); else if(character_code == '\n' || (character_code >= 32 && character_code < 127)) as_edit_insert(count, &as_ew_pos[identifier], character_code); else return 0; as_edit_fix_scroll(count, as_ew_pos[identifier], &as_ew_scroll[identifier]); as_edit_redraw(count, as_ew_path[identifier], as_ew_pos[identifier], as_ew_scroll[identifier]); return 0; } INT as_get_file_data(CC *path, C **data, INT *size) { INT count; count = as_resolve_path(path); if(count == -1) return -1; if(as_nodes[count].type != AS_FILE) return -1; *data = as_nodes[count].data; *size = as_nodes[count].size; return 0; } VD as_rm_recursive(INT node) { INT index; if (!as_nodes[node].used) return; /* Delete children first if directory */ if (as_nodes[node].type == AS_DIR) { for (index = 0; index < AS_MAX_NODES; index++) { if (as_nodes[index].used && as_nodes[index].parent == node) as_rm_recursive(index); } } as_nodes[node].used = 0; as_nodes[node].size = 0; as_nodes[node].name[0] = 0; as_nodes[node].data[0] = 0; as_nodes[node].parent = -1; } VD as_rm(C *name) { INT index; for (index = 0; index < AS_MAX_NODES; index++) { if (as_nodes[index].used && as_nodes[index].parent == as_cwd && as_compare_equal_str(as_nodes[index].name, name)) { as_rm_recursive(index); if(saveit == 1) as_save_to_disk(); print("Removed: "); print(name); print("\n"); return; } } print("rm: not found\n"); } INT as_path_parent_name(CC *path, INT *parent, C *name) { C parent_path[AS_NAME_MAX * 4]; as_split_path(path, parent_path, name); if(!name[0]) return -1; *parent = as_resolve_path(parent_path); if(*parent == -1) return -1; if(as_nodes[*parent].type != AS_DIR) return -1; return 0; } INT as_copy_node_recursive(INT src, INT dst_parent, CC *newname) { INT count; INT index; if(as_find_child(dst_parent, newname) != -1) return -1; count = as_node_allocator(); if(count == -1) return -1; as_nodes[count] = as_nodes[src]; as_nodes[count].parent = dst_parent; as_copy_str(as_nodes[count].name, newname); if(as_nodes[src].type == AS_DIR) { for(index = 0; index < AS_MAX_NODES; index++) { if(as_nodes[index].used && as_nodes[index].parent == src && index != src) { if(as_copy_node_recursive(index, count, as_nodes[index].name) != 0) return -1; } } } return 0; } INT as_cp(CC *src_path, CC *dst_path) { INT src; INT dst_parent; C dst_name[AS_NAME_MAX]; src = as_resolve_path(src_path); if(src == -1) { print_red("cp: source not found\n"); return -1; } if(src == 0) { print_red("cp: cannot copy root\n"); return -1; } if(as_path_parent_name(dst_path, &dst_parent, dst_name) != 0) { print_red("cp: bad destination\n"); return -1; } if(as_copy_node_recursive(src, dst_parent, dst_name) != 0) { print_red("cp: failed\n"); return -1; } if(saveit == 1) as_save_to_disk(); return 0; } INT as_mv(CC *src_path, CC *dst_path) { INT src; INT dst_parent; C dst_name[AS_NAME_MAX]; src = as_resolve_path(src_path); if(src == -1) { print_red("mv: source not found\n"); return -1; } if(src == 0) { print_red("mv: cannot move root\n"); return -1; } if(as_path_parent_name(dst_path, &dst_parent, dst_name) != 0) { print_red("mv: bad destination\n"); return -1; } if(as_find_child(dst_parent, dst_name) != -1) { print_red("mv: destination exists\n"); return -1; } as_nodes[src].parent = dst_parent; as_copy_str(as_nodes[src].name, dst_name); if(saveit == 1) as_save_to_disk(); return 0; }