// Do a three step traversal: by file, then fn, then line. // Returns a pointer to the line CC, creates a new one if necessary. static LineCC* get_lineCC(Addr origAddr) { Char file[FILE_LEN], fn[FN_LEN]; Int line; CodeLoc loc; LineCC* lineCC; get_debug_info(origAddr, file, fn, &line); VGP_PUSHCC(VgpGetLineCC); loc.file = file; loc.fn = fn; loc.line = line; lineCC = VG_(OSet_Lookup)(CC_table, &loc); if (!lineCC) { // Allocate and zero a new node. lineCC = VG_(OSet_AllocNode)(CC_table, sizeof(LineCC)); lineCC->loc.file = get_perm_string(loc.file); lineCC->loc.fn = get_perm_string(loc.fn); lineCC->loc.line = loc.line; VG_(OSet_Insert)(CC_table, lineCC); } VGP_POPCC(VgpGetLineCC); return lineCC; }
void update_stat_window(FileView *view) { char name_buf[20]; char perm_buf[26]; char size_buf[56]; char uid_buf[26]; struct passwd *pwd_buf; int x, y; getmaxyx(stat_win, y, x); snprintf(name_buf, sizeof(name_buf), "%s", get_current_file_name(view)); describe_file_size(size_buf, sizeof(size_buf), view->dir_entry[view->list_pos].size); if((pwd_buf = getpwuid(view->dir_entry[view->list_pos].uid)) == NULL) { snprintf (uid_buf, sizeof(uid_buf), " %d", (int) view->dir_entry[view->list_pos].uid); } else { snprintf(uid_buf, sizeof(uid_buf), " %s", pwd_buf->pw_name); } get_perm_string(perm_buf, sizeof(perm_buf), view->dir_entry[view->list_pos].mode); werase(stat_win); mvwaddstr(stat_win, 0, 2, name_buf); mvwaddstr(stat_win, 0, 24, size_buf); mvwaddstr(stat_win, 0, 36, perm_buf); mvwaddstr(stat_win, 0, 46, uid_buf); snprintf(name_buf, sizeof(name_buf), "%d %s filtered", view->filtered, view->filtered == 1 ? "file" : "files"); if(view->filtered > 0) mvwaddstr(stat_win, 0, x - (strlen(name_buf) +2) , name_buf); wnoutrefresh(stat_win); update_pos_window(view); }
void redraw_file_info_dialog(void) { const dir_entry_t *entry; char perm_buf[26]; char size_buf[56]; char buf[256]; #ifndef _WIN32 char id_buf[26]; #endif int curr_y; uint64_t size; int size_not_precise; assert(view != NULL); if(resize_for_menu_like() != 0) { return; } werase(menu_win); entry = &view->dir_entry[view->list_pos]; size = 0; if(entry->type == FT_DIR) { char full_path[PATH_MAX]; get_current_full_path(view, sizeof(full_path), full_path); tree_get_data(curr_stats.dirsize_cache, full_path, &size); } if(size == 0) { size = entry->size; } size_not_precise = friendly_size_notation(size, sizeof(size_buf), size_buf); curr_y = 2; curr_y += print_item("Path: ", entry->origin, curr_y); curr_y += print_item("Name: ", entry->name, curr_y); mvwaddstr(menu_win, curr_y, 2, "Size: "); mvwaddstr(menu_win, curr_y, 8, size_buf); if(size_not_precise) { snprintf(size_buf, sizeof(size_buf), " (%" PRId64 " bytes)", size); waddstr(menu_win, size_buf); } curr_y += 2; curr_y += show_file_type(view, curr_y); curr_y += show_mime_type(view, curr_y); #ifndef _WIN32 get_perm_string(perm_buf, sizeof(perm_buf), entry->mode); curr_y += print_item("Permissions: ", perm_buf, curr_y); #else copy_str(perm_buf, sizeof(perm_buf), attr_str_long(entry->attrs)); curr_y += print_item("Attributes: ", perm_buf, curr_y); #endif format_time(entry->mtime, buf, sizeof(buf)); curr_y += print_item("Modified: ", buf, curr_y); format_time(entry->atime, buf, sizeof(buf)); curr_y += print_item("Accessed: ", buf, curr_y); format_time(entry->ctime, buf, sizeof(buf)); #ifndef _WIN32 curr_y += print_item("Changed: ", buf, curr_y); #else curr_y += print_item("Created: ", buf, curr_y); #endif #ifndef _WIN32 get_uid_string(entry, 0, sizeof(id_buf), id_buf); curr_y += print_item("Owner: ", id_buf, curr_y); get_gid_string(entry, 0, sizeof(id_buf), id_buf); curr_y += print_item("Group: ", id_buf, curr_y); #endif /* Fake use after last assignment. */ (void)curr_y; box(menu_win, 0, 0); checked_wmove(menu_win, 0, 3); wprint(menu_win, " File Information "); wrefresh(menu_win); was_redraw = 1; }
void redraw_file_info_dialog(void) { char name_buf[NAME_MAX]; char perm_buf[26]; char size_buf[56]; char buf[256]; #ifndef _WIN32 char uid_buf[26]; struct passwd *pwd_buf; struct group *grp_buf; #endif struct tm *tm_ptr; int curr_y; uint64_t size; int size_not_precise; assert(view != NULL); resize_for_menu_like(); werase(menu_win); snprintf(name_buf, sizeof(name_buf), "%s", view->dir_entry[view->list_pos].name); size = 0; if(view->dir_entry[view->list_pos].type == DIRECTORY) tree_get_data(curr_stats.dirsize_cache, view->dir_entry[view->list_pos].name, &size); if(size == 0) size = view->dir_entry[view->list_pos].size; size_not_precise = friendly_size_notation(size, sizeof(size_buf), size_buf); #ifndef _WIN32 if((pwd_buf = getpwuid(view->dir_entry[view->list_pos].uid)) == NULL) { snprintf(uid_buf, sizeof(uid_buf), "%d", (int) view->dir_entry[view->list_pos].uid); } else { snprintf(uid_buf, sizeof(uid_buf), "%s", pwd_buf->pw_name); } get_perm_string(perm_buf, sizeof(perm_buf), view->dir_entry[view->list_pos].mode); #else snprintf(perm_buf, sizeof(perm_buf), "%s", attr_str_long(view->dir_entry[view->list_pos].attrs)); #endif curr_y = 2; mvwaddstr(menu_win, curr_y, 2, "File: "); name_buf[getmaxx(menu_win) - 8] = '\0'; checked_wmove(menu_win, curr_y, 8); wprint(menu_win, name_buf); curr_y += 2; mvwaddstr(menu_win, curr_y, 2, "Size: "); mvwaddstr(menu_win, curr_y, 8, size_buf); if(size_not_precise) { snprintf(size_buf, sizeof(size_buf), " (%" PRId64 " bytes)", size); waddstr(menu_win, size_buf); } curr_y += 2; curr_y += show_file_type(view, curr_y); curr_y += show_mime_type(view, curr_y); #ifndef _WIN32 mvwaddstr(menu_win, curr_y, 2, "Permissions: "); #else mvwaddstr(menu_win, curr_y, 2, "Attributes: "); #endif mvwaddstr(menu_win, curr_y, 15, perm_buf); curr_y += 2; mvwaddstr(menu_win, curr_y, 2, "Modified: "); tm_ptr = localtime(&view->dir_entry[view->list_pos].mtime); strftime(buf, sizeof (buf), "%a %b %d %Y %I:%M %p", tm_ptr); checked_wmove(menu_win, curr_y, 13); wprint(menu_win, buf); curr_y += 2; mvwaddstr(menu_win, curr_y, 2, "Accessed: "); tm_ptr = localtime(&view->dir_entry[view->list_pos].atime); strftime(buf, sizeof (buf), "%a %b %d %Y %I:%M %p", tm_ptr); checked_wmove(menu_win, curr_y, 13); wprint(menu_win, buf); curr_y += 2; #ifndef _WIN32 mvwaddstr(menu_win, curr_y, 2, "Changed: "); #else mvwaddstr(menu_win, curr_y, 2, "Created: "); #endif tm_ptr = localtime(&view->dir_entry[view->list_pos].ctime); strftime(buf, sizeof (buf), "%a %b %d %Y %I:%M %p", tm_ptr); checked_wmove(menu_win, curr_y, 13); wprint(menu_win, buf); curr_y += 2; #ifndef _WIN32 mvwaddstr(menu_win, curr_y, 2, "Owner: "); mvwaddstr(menu_win, curr_y, 10, uid_buf); curr_y += 2; mvwaddstr(menu_win, curr_y, 2, "Group: "); if((grp_buf = getgrgid(view->dir_entry[view->list_pos].gid)) != NULL) mvwaddstr(menu_win, curr_y, 10, grp_buf->gr_name); #endif box(menu_win, 0, 0); checked_wmove(menu_win, 0, 3); wprint(menu_win, " File Information "); wrefresh(menu_win); was_redraw = 1; }
/* Expands macros in the *format string advancing the pointer as it goes. The * opt represents conditional expression state, should be zero for non-recursive * calls. Returns newly allocated string, which should be freed by the * caller. */ static char * parse_view_macros(FileView *view, const char **format, const char macros[], int opt) { const dir_entry_t *const entry = &view->dir_entry[view->list_pos]; char *result = strdup(""); size_t len = 0; char c; int nexpansions = 0; while((c = **format) != '\0') { size_t width = 0; int left_align = 0; char buf[PATH_MAX]; const char *const next = ++*format; int skip, ok; if(c != '%' || (!char_is_one_of(macros, *next) && !isdigit(*next))) { if(strappendch(&result, &len, c) != 0) { break; } continue; } if(*next == '-') { left_align = 1; ++*format; } while(isdigit(**format)) { width = width*10 + *(*format)++ - '0'; } c = *(*format)++; skip = 0; ok = 1; switch(c) { case 't': format_entry_name(entry, sizeof(buf), buf); break; case 'A': #ifndef _WIN32 get_perm_string(buf, sizeof(buf), entry->mode); #else snprintf(buf, sizeof(buf), "%s", attr_str_long(entry->attrs)); #endif break; case 'u': get_uid_string(entry, 0, sizeof(buf), buf); break; case 'g': get_gid_string(entry, 0, sizeof(buf), buf); break; case 's': friendly_size_notation(entry->size, sizeof(buf), buf); break; case 'E': { uint64_t size = 0; if(view->selected_files > 0) { int i; for(i = 0; i < view->list_rows; i++) { if(view->dir_entry[i].selected) { size += get_file_size_by_entry(view, i); } } } /* Make exception for VISUAL_MODE, since it can contain empty * selection when cursor is on ../ directory. */ else if(!vle_mode_is(VISUAL_MODE)) { size = get_file_size_by_entry(view, view->list_pos); } friendly_size_notation(size, sizeof(buf), buf); } break; case 'd': { struct tm *tm_ptr = localtime(&entry->mtime); strftime(buf, sizeof(buf), cfg.time_format, tm_ptr); } break; case '-': skip = expand_num(buf, sizeof(buf), view->filtered); break; case 'l': skip = expand_num(buf, sizeof(buf), view->list_pos + 1); break; case 'L': skip = expand_num(buf, sizeof(buf), view->list_rows + view->filtered); break; case 'S': skip = expand_num(buf, sizeof(buf), view->list_rows); break; case '%': snprintf(buf, sizeof(buf), "%%"); break; case '[': { char *const opt_str = parse_view_macros(view, format, macros, 1); copy_str(buf, sizeof(buf), opt_str); free(opt_str); break; } case ']': if(opt) { if(nexpansions == 0) { replace_string(&result, ""); } return result; } else { LOG_INFO_MSG("Unmatched %]", c); ok = 0; } break; default: LOG_INFO_MSG("Unexpected %%-sequence: %%%c", c); ok = 0; break; } if(!ok) { *format = next; if(strappendch(&result, &len, '%') != 0) { break; } continue; } check_expanded_str(buf, skip, &nexpansions); stralign(buf, width, ' ', left_align); if(strappend(&result, &len, buf) != 0) { break; } } /* Unmatched %[. */ if(opt) { (void)strprepend(&result, &len, "%["); } return result; }
/* Formats status line in the "old way" (before introduction of 'statusline' * option). */ static void update_stat_window_old(FileView *view, int lazy_redraw) { const dir_entry_t *const entry = &view->dir_entry[view->list_pos]; char name_buf[160*2 + 1]; char perm_buf[26]; char size_buf[56]; char id_buf[52]; int x; int cur_x; size_t print_width; char *filename; x = getmaxx(stdscr); wresize(stat_win, 1, x); wbkgdset(stat_win, COLOR_PAIR(cfg.cs.pair[STATUS_LINE_COLOR]) | cfg.cs.color[STATUS_LINE_COLOR].attr); filename = get_current_file_name(view); print_width = utf8_strsnlen(filename, 20 + MAX(0, x - 83)); snprintf(name_buf, MIN(sizeof(name_buf), print_width + 1), "%s", filename); friendly_size_notation(entry->size, sizeof(size_buf), size_buf); get_uid_string(entry, 0, sizeof(id_buf), id_buf); if(id_buf[0] != '\0') strcat(id_buf, ":"); get_gid_string(entry, 0, sizeof(id_buf) - strlen(id_buf), id_buf + strlen(id_buf)); #ifndef _WIN32 get_perm_string(perm_buf, sizeof(perm_buf), entry->mode); #else snprintf(perm_buf, sizeof(perm_buf), "%s", attr_str_long(entry->attrs)); #endif werase(stat_win); cur_x = 2; checked_wmove(stat_win, 0, cur_x); wprint(stat_win, name_buf); cur_x += 22; if(x > 83) cur_x += x - 83; mvwaddstr(stat_win, 0, cur_x, size_buf); cur_x += 12; mvwaddstr(stat_win, 0, cur_x, perm_buf); cur_x += 11; snprintf(name_buf, sizeof(name_buf), "%d %s filtered", view->filtered, (view->filtered == 1) ? "file" : "files"); if(view->filtered > 0) mvwaddstr(stat_win, 0, x - (strlen(name_buf) + 2), name_buf); if(cur_x + strlen(id_buf) + 1 > x - (strlen(name_buf) + 2)) break_at(id_buf, ':'); if(cur_x + strlen(id_buf) + 1 > x - (strlen(name_buf) + 2)) id_buf[0] = '\0'; mvwaddstr(stat_win, 0, cur_x, id_buf); if(lazy_redraw) { wnoutrefresh(stat_win); } else { wrefresh(stat_win); } }
static int sort_dir_list(const void *one, const void *two) { int retval; char *pfirst, *psecond; dir_entry_t *const first = (dir_entry_t *)one; dir_entry_t *const second = (dir_entry_t *)two; int first_is_dir; int second_is_dir; int dirs; if(is_parent_dir(first->name)) { return -1; } else if(is_parent_dir(second->name)) { return 1; } first_is_dir = is_directory_entry(first); second_is_dir = is_directory_entry(second); dirs = first_is_dir || second_is_dir; retval = 0; switch(sort_type) { case SORT_BY_NAME: case SORT_BY_INAME: if(first->name[0] == '.' && second->name[0] != '.') retval = -1; else if(first->name[0] != '.' && second->name[0] == '.') retval = 1; else retval = compare_file_names(dirs, first->name, second->name, sort_type == SORT_BY_INAME); break; case SORT_BY_TYPE: if(first_is_dir != second_is_dir) { retval = first_is_dir ? -1 : 1; } break; case SORT_BY_EXTENSION: pfirst = strrchr(first->name, '.'); psecond = strrchr(second->name, '.'); if(pfirst && psecond) retval = compare_file_names(dirs, ++pfirst, ++psecond, 0); else if(pfirst || psecond) retval = pfirst ? -1 : 1; else retval = compare_file_names(dirs, first->name, second->name, 0); break; case SORT_BY_SIZE: { if(first_is_dir) tree_get_data(curr_stats.dirsize_cache, first->name, &first->size); if(second_is_dir) tree_get_data(curr_stats.dirsize_cache, second->name, &second->size); retval = (first->size < second->size) ? -1 : (first->size > second->size); } break; case SORT_BY_TIME_MODIFIED: retval = first->mtime - second->mtime; break; case SORT_BY_TIME_ACCESSED: retval = first->atime - second->atime; break; case SORT_BY_TIME_CHANGED: retval = first->ctime - second->ctime; break; #ifndef _WIN32 case SORT_BY_MODE: retval = first->mode - second->mode; break; case SORT_BY_OWNER_NAME: /* FIXME */ case SORT_BY_OWNER_ID: retval = first->uid - second->uid; break; case SORT_BY_GROUP_NAME: /* FIXME */ case SORT_BY_GROUP_ID: retval = first->gid - second->gid; break; case SORT_BY_PERMISSIONS: { char first_perm[11], second_perm[11]; get_perm_string(first_perm, sizeof(first_perm), first->mode); get_perm_string(second_perm, sizeof(second_perm), second->mode); retval = strcmp(first_perm, second_perm); } break; #endif default: assert(0 && "All possible sort options should be handled"); break; } if(retval == 0) { retval = first->list_num - second->list_num; } else if(sort_descending) { retval = -retval; } return retval; }
/* Expands macros in the *format string advancing the pointer as it goes. The * opt represents conditional expression state, should be zero for non-recursive * calls. Returns newly allocated string, which should be freed by the * caller. */ static LineWithAttrs parse_view_macros(view_t *view, const char **format, const char macros[], int opt) { const dir_entry_t *const curr = get_current_entry(view); LineWithAttrs result = { .line = strdup(""), .attrs = strdup("") }; char c; int nexpansions = 0; int has_expander = 0; if(curr == NULL) { return result; } while((c = **format) != '\0') { size_t width = 0; int left_align = 0; char buf[PATH_MAX + 1]; const char *const next = ++*format; int skip, ok; if(c != '%' || (!char_is_one_of(macros, *next) && !isdigit(*next) && (*next != '=' || has_expander))) { if(strappendch(&result.line, &result.line_len, c) != 0) { break; } continue; } if(*next == '=') { (void)sync_attrs(&result, 0); if(strappend(&result.line, &result.line_len, "%=") != 0 || strappendch(&result.attrs, &result.attrs_len, '=') != 0) { break; } ++*format; has_expander = 1; continue; } if(*next == '-') { left_align = 1; ++*format; } while(isdigit(**format)) { width = width*10 + *(*format)++ - '0'; } c = *(*format)++; skip = 0; ok = 1; buf[0] = '\0'; switch(c) { case 'a': friendly_size_notation(get_free_space(curr_view->curr_dir), sizeof(buf), buf); break; case 't': format_entry_name(curr, NF_FULL, sizeof(buf), buf); break; case 'T': if(curr->type == FT_LINK) { char full_path[PATH_MAX + 1]; char link_path[PATH_MAX + 1]; //add by sim1 get_full_path_of(curr, sizeof(full_path), full_path); //mod by sim1 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if(get_link_target(full_path, link_path, sizeof(link_path)) != 0) { copy_str(buf, sizeof(buf), "Failed to resolve link"); } else { snprintf(buf, sizeof(buf), " -> %s", link_path); } //mod by sim1 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> } break; case 'f': get_short_path_of(view, curr, NF_FULL, 0, sizeof(buf), buf); break; case 'A': #ifndef _WIN32 get_perm_string(buf, sizeof(buf), curr->mode); #else copy_str(buf, sizeof(buf), attr_str_long(curr->attrs)); #endif break; case 'u': get_uid_string(curr, 0, sizeof(buf), buf); break; case 'g': get_gid_string(curr, 0, sizeof(buf), buf); break; case 's': friendly_size_notation(fentry_get_size(view, curr), sizeof(buf), buf); break; //add by sim1 ************************************************ case 'r': { char path[PATH_MAX] = {0}; get_full_path_at(view, view->list_pos, sizeof(path), path); (void)get_rating_string(buf, sizeof(buf), path); } break; case 'n': { int nitems = !fentry_is_dir(curr) ? 0 : (int)fentry_get_nitems(view, curr); snprintf(buf, sizeof(buf), "%d", nitems); } break; //add by sim1 ************************************************ case 'E': { uint64_t size = 0U; typedef int (*iter_f)(view_t *view, dir_entry_t **entry); /* No current element for visual mode, since it can contain truly * empty selection when cursor is on ../ directory. */ iter_f iter = vle_mode_is(VISUAL_MODE) ? &iter_selected_entries : &iter_selection_or_current; dir_entry_t *entry = NULL; while(iter(view, &entry)) { size += fentry_get_size(view, entry); } friendly_size_notation(size, sizeof(buf), buf); } break; case 'd': { struct tm *tm_ptr = localtime(&curr->mtime); strftime(buf, sizeof(buf), cfg.time_format, tm_ptr); } break; case '-': case 'x': skip = expand_num(buf, sizeof(buf), view->filtered); break; case 'l': skip = expand_num(buf, sizeof(buf), view->list_pos + 1); break; case 'L': skip = expand_num(buf, sizeof(buf), view->list_rows + view->filtered); break; case 'S': skip = expand_num(buf, sizeof(buf), view->list_rows); break; case '%': copy_str(buf, sizeof(buf), "%"); break; case 'z': copy_str(buf, sizeof(buf), get_tip()); break; case 'D': if(curr_stats.number_of_windows == 1) { view_t *const other = (view == curr_view) ? other_view : curr_view; //mod by sim1 //copy_str(buf, sizeof(buf), replace_home_part(other->curr_dir)); snprintf(buf, sizeof(buf), " ‖ %s", replace_home_part(other->curr_dir)); } break; case '[': { LineWithAttrs opt = parse_view_macros(view, format, macros, 1); copy_str(buf, sizeof(buf), opt.line); free(opt.line); char *attrs = opt.attrs; if(sync_attrs(&result, 0) && opt.attrs_len > 0U) { if(*attrs != ' ') { result.attrs[result.attrs_len - 1U] = *attrs; } ++attrs; } strappend(&result.attrs, &result.attrs_len, attrs); free(opt.attrs); break; } case ']': if(opt) { if(nexpansions == 0) { replace_string(&result.line, ""); replace_string(&result.attrs, ""); result.line_len = 0U; result.attrs_len = 0U; } if(sync_attrs(&result, 0)) { result.attrs[--result.attrs_len] = '\0'; } return result; } LOG_INFO_MSG("Unmatched %%]"); ok = 0; break; case '{': { /* Try to find matching closing bracket * TODO: implement the way to escape it, so that the expr may contain * closing brackets */ const char *e = strchr(*format, '}'); char *expr = NULL, *resstr = NULL; var_t res = var_false(); ParsingErrors parsing_error; /* If there's no matching closing bracket, just add the opening one * literally */ if(e == NULL) { ok = 0; break; } /* Create a NULL-terminated copy of the given expr. * TODO: we could temporarily use buf for that, to avoid extra * allocation, but explicitly named variable reads better. */ expr = calloc(e - (*format) + 1 /* NUL-term */, 1); memcpy(expr, *format, e - (*format)); /* Try to parse expr, and convert the res to string if succeed. */ parsing_error = parse(expr, 0, &res); if(parsing_error == PE_NO_ERROR) { resstr = var_to_str(res); } if(resstr != NULL) { copy_str(buf, sizeof(buf), resstr); } else { copy_str(buf, sizeof(buf), "<Invalid expr>"); } var_free(res); free(resstr); free(expr); *format = e + 1 /* closing bracket */; } break; case '*': if(width > 9) { snprintf(buf, sizeof(buf), "%%%d*", (int)width); width = 0; break; } (void)sync_attrs(&result, 1); result.attrs[result.attrs_len - 1] = '0' + width; width = 0; break; default: LOG_INFO_MSG("Unexpected %%-sequence: %%%c", c); ok = 0; break; } if(char_is_one_of("tTAugsEd", c) && fentry_is_fake(curr)) { buf[0] = '\0'; } if(!ok) { *format = next; if(strappendch(&result.line, &result.line_len, '%') != 0) { break; } continue; } check_expanded_str(buf, skip, &nexpansions); stralign(buf, width, ' ', left_align); if(strappend(&result.line, &result.line_len, buf) != 0) { break; } } /* Unmatched %[. */ if(opt) { (void)strprepend(&result.line, &result.line_len, "%["); } if(sync_attrs(&result, 0)) { result.attrs[--result.attrs_len] = '\0'; } return result; } /* Makes sure that result->attrs has at least as many elements as result->line * contains characters + extra_width. Returns non-zero if result->attrs has * extra characters compared to result->line. */ static int sync_attrs(LineWithAttrs *result, int extra_width) { const size_t nchars = utf8_strsw(result->line) + extra_width; if(result->attrs_len < nchars) { char *const new_attrs = format_str("%s%*s", result->attrs, (int)(nchars - result->attrs_len), ""); free(result->attrs); result->attrs = new_attrs; result->attrs_len = nchars; } return (result->attrs_len > nchars); } /* Prints number into the buffer. Returns non-zero if numeric value is * "empty" (zero). */ static int expand_num(char buf[], size_t buf_len, int val) { snprintf(buf, buf_len, "%d", val); return (val == 0); }
/* Formats status line in the "old way" (before introduction of 'statusline' * option). */ static void update_stat_window_old(view_t *view, int lazy_redraw) { const dir_entry_t *const curr = get_current_entry(view); char name_buf[160*2 + 1]; char perm_buf[26]; char size_buf[64]; char id_buf[52]; int x; int cur_x; size_t print_width; char *filename; if(curr == NULL || fentry_is_fake(curr)) { werase(stat_win); refresh_window(stat_win, lazy_redraw); return; } x = getmaxx(stdscr); wresize(stat_win, 1, x); ui_set_bg(stat_win, &cfg.cs.color[STATUS_LINE_COLOR], cfg.cs.pair[STATUS_LINE_COLOR]); filename = get_current_file_name(view); print_width = utf8_strsnlen(filename, 20 + MAX(0, x - 83)); copy_str(name_buf, MIN(sizeof(name_buf), print_width + 1), filename); friendly_size_notation(fentry_get_size(view, curr), sizeof(size_buf), size_buf); get_uid_string(curr, 0, sizeof(id_buf), id_buf); if(id_buf[0] != '\0') strcat(id_buf, ":"); get_gid_string(curr, 0, sizeof(id_buf) - strlen(id_buf), id_buf + strlen(id_buf)); #ifndef _WIN32 get_perm_string(perm_buf, sizeof(perm_buf), curr->mode); #else copy_str(perm_buf, sizeof(perm_buf), attr_str_long(curr->attrs)); #endif werase(stat_win); cur_x = 2; checked_wmove(stat_win, 0, cur_x); wprint(stat_win, name_buf); cur_x += 22; if(x > 83) cur_x += x - 83; mvwaddstr(stat_win, 0, cur_x, size_buf); cur_x += 12; mvwaddstr(stat_win, 0, cur_x, perm_buf); cur_x += 11; snprintf(name_buf, sizeof(name_buf), "%d %s filtered", view->filtered, (view->filtered == 1) ? "file" : "files"); if(view->filtered > 0) mvwaddstr(stat_win, 0, x - (strlen(name_buf) + 2), name_buf); if(cur_x + strlen(id_buf) + 1 > x - (strlen(name_buf) + 2)) break_at(id_buf, ':'); if(cur_x + strlen(id_buf) + 1 > x - (strlen(name_buf) + 2)) id_buf[0] = '\0'; mvwaddstr(stat_win, 0, cur_x, id_buf); refresh_window(stat_win, lazy_redraw); }
static int sort_dir_list(const void *one, const void *two) { int retval; char *pfirst, *psecond; dir_entry_t *const first = (dir_entry_t *)one; dir_entry_t *const second = (dir_entry_t *)two; int first_is_dir; int second_is_dir; if(is_parent_dir(first->name)) { return -1; } else if(is_parent_dir(second->name)) { return 1; } first_is_dir = is_directory_entry(first); second_is_dir = is_directory_entry(second); retval = 0; switch(sort_type) { case SK_BY_NAME: case SK_BY_INAME: if(custom_view) { retval = compare_entry_names(first, second, sort_type == SK_BY_INAME); } else { retval = compare_full_file_names(first->name, second->name, sort_type == SK_BY_INAME); } break; case SK_BY_DIR: if(first_is_dir != second_is_dir) { retval = first_is_dir ? -1 : 1; } break; case SK_BY_TYPE: retval = strcmp(get_type_str(first->type), get_type_str(second->type)); break; case SK_BY_FILEEXT: case SK_BY_EXTENSION: pfirst = strrchr(first->name, '.'); psecond = strrchr(second->name, '.'); if(first_is_dir && second_is_dir && sort_type == SK_BY_FILEEXT) { retval = compare_file_names(first->name, second->name, 0); } else if(first_is_dir != second_is_dir && sort_type == SK_BY_FILEEXT) { retval = first_is_dir ? -1 : 1; } else if(pfirst && psecond) { if(pfirst == first->name && psecond != second->name) { retval = -1; } else if(pfirst != first->name && psecond == second->name) { retval = 1; } else { retval = compare_file_names(++pfirst, ++psecond, 0); } } else if(pfirst || psecond) retval = pfirst ? -1 : 1; else retval = compare_file_names(first->name, second->name, 0); break; case SK_BY_SIZE: { if(first_is_dir) { char full_path[PATH_MAX]; get_full_path_of(first, sizeof(full_path), full_path); tree_get_data(curr_stats.dirsize_cache, full_path, &first->size); } if(second_is_dir) { char full_path[PATH_MAX]; get_full_path_of(second, sizeof(full_path), full_path); tree_get_data(curr_stats.dirsize_cache, full_path, &second->size); } retval = (first->size < second->size) ? -1 : (first->size > second->size); } break; case SK_BY_TIME_MODIFIED: retval = first->mtime - second->mtime; break; case SK_BY_TIME_ACCESSED: retval = first->atime - second->atime; break; case SK_BY_TIME_CHANGED: retval = first->ctime - second->ctime; break; #ifndef _WIN32 case SK_BY_MODE: retval = first->mode - second->mode; break; case SK_BY_OWNER_NAME: /* FIXME */ case SK_BY_OWNER_ID: retval = first->uid - second->uid; break; case SK_BY_GROUP_NAME: /* FIXME */ case SK_BY_GROUP_ID: retval = first->gid - second->gid; break; case SK_BY_PERMISSIONS: { char first_perm[11], second_perm[11]; get_perm_string(first_perm, sizeof(first_perm), first->mode); get_perm_string(second_perm, sizeof(second_perm), second->mode); retval = strcmp(first_perm, second_perm); } break; #endif } if(retval == 0) { retval = first->list_num - second->list_num; } else if(sort_descending) { retval = -retval; } return retval; }
int flist_find_group(const FileView *view, int next) { /* TODO: refactor/simplify this function (flist_find_group()). */ const int correction = next ? -1 : 0; const int lb = correction; const int ub = view->list_rows + correction; const int inc = next ? +1 : -1; int pos = view->list_pos; dir_entry_t *pentry = &view->dir_entry[pos]; const char *ext = get_last_ext(pentry->name); size_t char_width = utf8_chrw(pentry->name); wchar_t ch = towupper(get_first_wchar(pentry->name)); const SortingKey sorting_key = flist_custom_active(view) && cv_compare(view->custom.type) ? SK_BY_ID : abs(view->sort[0]); const int is_dir = fentry_is_dir(pentry); const char *const type_str = get_type_str(pentry->type); regmatch_t pmatch = { .rm_so = 0, .rm_eo = 0 }; #ifndef _WIN32 char perms[16]; get_perm_string(perms, sizeof(perms), pentry->mode); #endif if(sorting_key == SK_BY_GROUPS) { pmatch = get_group_match(&view->primary_group, pentry->name); } while(pos > lb && pos < ub) { dir_entry_t *nentry; pos += inc; nentry = &view->dir_entry[pos]; switch(sorting_key) { case SK_BY_FILEEXT: if(fentry_is_dir(nentry)) { if(strncmp(pentry->name, nentry->name, char_width) != 0) { return pos; } } if(strcmp(get_last_ext(nentry->name), ext) != 0) { return pos; } break; case SK_BY_EXTENSION: if(strcmp(get_last_ext(nentry->name), ext) != 0) return pos; break; case SK_BY_GROUPS: { regmatch_t nmatch = get_group_match(&view->primary_group, nentry->name); if(pmatch.rm_eo - pmatch.rm_so != nmatch.rm_eo - nmatch.rm_so || (pmatch.rm_eo != pmatch.rm_so && strncmp(pentry->name + pmatch.rm_so, nentry->name + nmatch.rm_so, pmatch.rm_eo - pmatch.rm_so + 1U) != 0)) return pos; } break; case SK_BY_TARGET: if((nentry->type == FT_LINK) != (pentry->type == FT_LINK)) { /* One of the entries is not a link. */ return pos; } if(nentry->type == FT_LINK) { /* Both entries are symbolic links. */ char full_path[PATH_MAX]; char nlink[PATH_MAX], plink[PATH_MAX]; get_full_path_of(nentry, sizeof(full_path), full_path); if(get_link_target(full_path, nlink, sizeof(nlink)) != 0) { return pos; } get_full_path_of(pentry, sizeof(full_path), full_path); if(get_link_target(full_path, plink, sizeof(plink)) != 0) { return pos; } if(stroscmp(nlink, plink) != 0) { return pos; } } break; case SK_BY_NAME: if(strncmp(pentry->name, nentry->name, char_width) != 0) return pos; break; case SK_BY_INAME: if((wchar_t)towupper(get_first_wchar(nentry->name)) != ch) return pos; break; case SK_BY_SIZE: if(nentry->size != pentry->size) return pos; break; case SK_BY_NITEMS: if(entry_get_nitems(view, nentry) != entry_get_nitems(view, pentry)) return pos; break; case SK_BY_TIME_ACCESSED: if(nentry->atime != pentry->atime) return pos; break; case SK_BY_TIME_CHANGED: if(nentry->ctime != pentry->ctime) return pos; break; case SK_BY_TIME_MODIFIED: if(nentry->mtime != pentry->mtime) return pos; break; case SK_BY_DIR: if(is_dir != fentry_is_dir(nentry)) { return pos; } break; case SK_BY_TYPE: if(get_type_str(nentry->type) != type_str) { return pos; } break; #ifndef _WIN32 case SK_BY_GROUP_NAME: case SK_BY_GROUP_ID: if(nentry->gid != pentry->gid) return pos; break; case SK_BY_OWNER_NAME: case SK_BY_OWNER_ID: if(nentry->uid != pentry->uid) return pos; break; case SK_BY_MODE: if(nentry->mode != pentry->mode) return pos; break; case SK_BY_PERMISSIONS: { char nperms[16]; get_perm_string(nperms, sizeof(nperms), nentry->mode); if(strcmp(nperms, perms) != 0) { return pos; } break; } case SK_BY_NLINKS: if(nentry->nlinks != pentry->nlinks) { return pos; } break; #endif } /* Id sorting is builtin only and is defined outside SortingKey * enumeration. */ if((int)sorting_key == SK_BY_ID) { if(nentry->id != pentry->id) { return pos; } } } return pos; } /* Finds pointer to the beginning of the last extension of the file name. * Returns the pointer, which might point to the NUL byte if there are no * extensions. */ static const char * get_last_ext(const char name[]) { const char *const ext = strrchr(name, '.'); return (ext == NULL) ? (name + strlen(name)) : (ext + 1); } int flist_find_dir_group(const FileView *view, int next) { const int correction = next ? -1 : 0; const int lb = correction; const int ub = view->list_rows + correction; const int inc = next ? +1 : -1; int pos = curr_view->list_pos; dir_entry_t *pentry = &curr_view->dir_entry[pos]; const int is_dir = fentry_is_dir(pentry); while(pos > lb && pos < ub) { dir_entry_t *nentry; pos += inc; nentry = &curr_view->dir_entry[pos]; if(is_dir != fentry_is_dir(nentry)) { break; } } return pos; } int flist_first_sibling(const FileView *view) { const int parent = view->list_pos - view->dir_entry[view->list_pos].child_pos; return (parent == view->list_pos ? 0 : parent + 1); } int flist_last_sibling(const FileView *view) { int pos = view->list_pos - view->dir_entry[view->list_pos].child_pos; if(pos == view->list_pos) { /* For top-level entry, find the last top-level entry. */ pos = view->list_rows - 1; while(view->dir_entry[pos].child_pos != 0) { pos -= view->dir_entry[pos].child_pos; } } else { /* For non-top-level entry, go to last tree item and go up until our * child. */ const int parent = pos; pos = parent + view->dir_entry[parent].child_count; while(pos - view->dir_entry[pos].child_pos != parent) { pos -= view->dir_entry[pos].child_pos; } } return pos; }
static int sort_dir_list(const void *one, const void *two) { /* TODO: refactor this function sort_dir_list(). */ int retval; const dir_entry_t *const first = one; const dir_entry_t *const second = two; const int first_is_dir = fentry_is_dir(first); const int second_is_dir = fentry_is_dir(second); if(first_is_dir && is_parent_dir(first->name)) { return -1; } if(second_is_dir && is_parent_dir(second->name)) { return 1; } retval = 0; switch(sort_type) { char *pfirst, *psecond; case SK_BY_NAME: case SK_BY_INAME: if(custom_view) { retval = compare_entry_names(first, second, sort_type == SK_BY_INAME); } else { retval = compare_full_file_names(first->name, second->name, sort_type == SK_BY_INAME); } break; case SK_BY_DIR: if(first_is_dir != second_is_dir) { retval = first_is_dir ? -1 : 1; } break; case SK_BY_TYPE: retval = strcmp(get_type_str(first->type), get_type_str(second->type)); break; case SK_BY_FILEEXT: case SK_BY_EXTENSION: pfirst = strrchr(first->name, '.'); psecond = strrchr(second->name, '.'); if(first_is_dir && second_is_dir && sort_type == SK_BY_FILEEXT) { retval = compare_file_names(first->name, second->name, 0); } else if(first_is_dir != second_is_dir && sort_type == SK_BY_FILEEXT) { retval = first_is_dir ? -1 : 1; } else if(pfirst && psecond) { if(pfirst == first->name && psecond != second->name) { retval = -1; } else if(pfirst != first->name && psecond == second->name) { retval = 1; } else { retval = compare_file_names(++pfirst, ++psecond, 0); } } else if(pfirst || psecond) retval = pfirst ? -1 : 1; else retval = compare_file_names(first->name, second->name, 0); break; case SK_BY_SIZE: retval = compare_file_sizes(first, second); break; case SK_BY_NITEMS: retval = compare_item_count(first, first_is_dir, second, second_is_dir); break; case SK_BY_GROUPS: retval = compare_group(first->name, second->name, sort_data); break; case SK_BY_TARGET: retval = compare_targets(first, second); break; case SK_BY_TIME_MODIFIED: retval = first->mtime - second->mtime; break; case SK_BY_TIME_ACCESSED: retval = first->atime - second->atime; break; case SK_BY_TIME_CHANGED: retval = first->ctime - second->ctime; break; #ifndef _WIN32 case SK_BY_MODE: retval = first->mode - second->mode; break; case SK_BY_INODE: retval = first->inode - second->inode; break; case SK_BY_OWNER_NAME: /* FIXME */ case SK_BY_OWNER_ID: retval = first->uid - second->uid; break; case SK_BY_GROUP_NAME: /* FIXME */ case SK_BY_GROUP_ID: retval = first->gid - second->gid; break; case SK_BY_PERMISSIONS: { char first_perm[11], second_perm[11]; get_perm_string(first_perm, sizeof(first_perm), first->mode); get_perm_string(second_perm, sizeof(second_perm), second->mode); retval = strcmp(first_perm, second_perm); } break; case SK_BY_NLINKS: retval = first->nlinks - second->nlinks; break; #endif } if(retval == 0) { retval = first->tag - second->tag; } else if(sort_descending) { retval = -retval; } return retval; }