diff options
Diffstat (limited to 'src/output.c')
| -rw-r--r-- | src/output.c | 135 |
1 files changed, 122 insertions, 13 deletions
diff --git a/src/output.c b/src/output.c index 45f04a6..3cf68af 100644 --- a/src/output.c +++ b/src/output.c @@ -5,6 +5,7 @@ * vim:ts=4:sw=4:expandtab */ +#include <stdlib.h> #include <string.h> #include <unistd.h> #include <ctype.h> @@ -27,7 +28,13 @@ #define DM_OUT_FORMAT_MAX_LEN 80 -#define out_vsep fputc('|', stdout) +#define box_cross '+' +#define box_hsep '-' +#define box_vsep '|' + +#define out_cross() fputc(box_cross, stdout) +#define out_hsep() fputc(box_hsep, stdout) +#define out_vsep() fputc(box_vsep, stdout) #define out_print_newline() fputc('\n', stdout) #define out_print_fname(x) printf(" %s ", x->fname) @@ -42,7 +49,12 @@ void out_print_time_by_option(struct list_node *ptr); void out_print_type(struct list_node *ptr); void out_print_user_name(struct list_node *ptr); -void out_print_format_string_header(const char *format); +void out_print_format_string_header(const char *format, size_t longest_fname); + +size_t get_longest_filename(struct list_head *list); + + +char *global_sep_line = NULL; /* === IMPLEMENTATION === */ @@ -85,6 +97,19 @@ inline int fputc_width_x(char c, size_t x, FILE *fdout) { return 1; } +/* basic 4 due to formatted output */ +inline size_t get_longest_filename(struct list_head *list) { + size_t rc = 4, tmp = 0; + struct list_node *ptr = NULL; + if (list == NULL) { return 0; } + ptr = list->first; + while (ptr != NULL) { + tmp = strlen(ptr->fname); + if (tmp>rc) { rc = tmp; } + ptr = ptr->next; + } + return rc; +} /* === FORMATTING RELATED FUNCTIONS === */ @@ -289,24 +314,44 @@ inline void out_print_permissions(struct list_node *ptr) { printf(" %4o ", mode); } -inline void out_print_format_string_header(const char *format) { - size_t i=0, format_len=0; - char header[4096] = ""; +inline void out_print_format_string_header(const char *format, size_t longest_fname) { + size_t i=0, j=0, k=0, format_len=0, tmp = 0; + char header[4096] = "", sep_line[4096] = ""; char *pos = header; - if (format == NULL) return; + if (format == NULL || longest_fname == 0) return; DBGTRC("DEBUG: format string: \"%s\"\n", format); format_len = strnlen(format, DM_OUT_FORMAT_MAX_LEN); + + if (option_print_boxed_table) { + if (global_sep_line != NULL) { free(global_sep_line); } + pos[0] = box_vsep; + pos++; + sep_line[j++] = box_cross; + } + +#define LOCAL_EXTEND_SEP_LINE() { \ + if (option_print_boxed_table) { \ + tmp = strlen(pos); \ + for (k=0; k<tmp; k++) { sep_line[j++] = box_hsep; } \ + sep_line[j++] = box_cross; pos[tmp] = box_vsep; } } + /* Prevent buffer overflow, with the header string 32 byte buffer */ for (i=0; (i < format_len) && (strlen(header) < 4064); i++) { switch (format[i]) { case 'n': sprintf(pos, " FILE "); + tmp = strlen(pos); + for (k=0; k<longest_fname-4; k++) { + pos[tmp+k] = ' '; + } + LOCAL_EXTEND_SEP_LINE(); break; case 's': sprintf(pos, " %11s ", "SIZE "); + LOCAL_EXTEND_SEP_LINE(); break; case 't': if (option_timestamp_long) { @@ -314,6 +359,7 @@ inline void out_print_format_string_header(const char *format) { } else { sprintf(pos, " %c%-7s ", toupper(option_time_field), "TIME"); } + LOCAL_EXTEND_SEP_LINE(); break; case 'A': if (option_timestamp_long) { @@ -321,6 +367,7 @@ inline void out_print_format_string_header(const char *format) { } else { sprintf(pos, " %-8s ", "ATIME"); } + LOCAL_EXTEND_SEP_LINE(); break; case 'C': if (option_timestamp_long) { @@ -328,6 +375,7 @@ inline void out_print_format_string_header(const char *format) { } else { sprintf(pos, " %-8s ", "CTIME"); } + LOCAL_EXTEND_SEP_LINE(); break; case 'M': if (option_timestamp_long) { @@ -335,24 +383,31 @@ inline void out_print_format_string_header(const char *format) { } else { sprintf(pos, " %-8s ", "MTIME"); } + LOCAL_EXTEND_SEP_LINE(); break; case 'T': sprintf(pos, " %-12s ", "TYPE"); + LOCAL_EXTEND_SEP_LINE(); break; case 'u': sprintf(pos, " %-4s ", "UID"); + LOCAL_EXTEND_SEP_LINE(); break; case 'g': sprintf(pos, " %-4s ", "GID"); + LOCAL_EXTEND_SEP_LINE(); break; case 'U': sprintf(pos, " %-10s ", "USER"); + LOCAL_EXTEND_SEP_LINE(); break; case 'G': sprintf(pos, " %-10s ", "GROUP"); + LOCAL_EXTEND_SEP_LINE(); break; case 'p': sprintf(pos, " %-4s ", "PERM"); + LOCAL_EXTEND_SEP_LINE(); break; case ' ': break; @@ -362,9 +417,24 @@ inline void out_print_format_string_header(const char *format) { }; pos = &header[strlen(header)]; } - printf("%s\n", header); - fputc_width_x('-', strlen(header), stdout); + /* Output to stdout */ + if (option_print_boxed_table) { + fputs(sep_line, stdout); + out_print_newline(); + } + fputs(header, stdout); out_print_newline(); + if (option_print_boxed_table) { + tmp = strlen(sep_line); + fputs(sep_line, stdout); + if ((global_sep_line = calloc(tmp+1, sizeof(char))) != NULL) { + memcpy(global_sep_line, sep_line, tmp); + } + } else { + fputc_width_x('-', strlen(header), stdout); + } + out_print_newline(); +#undef LOCAL_EXTEND_SEP_LINE } /* === END OF FORMATTING FUNCTIONS === */ @@ -375,6 +445,7 @@ void print_list(struct list_head *list) { struct list_head *lh = list; struct list_node *ptr; size_t total_size = 0; + size_t longest_fname = 0, i = 0; if (list == NULL) return; if (option_sort_reverse_order) { @@ -385,15 +456,24 @@ void print_list(struct list_head *list) { } } + longest_fname = get_longest_filename(list); + if (option_print_header) { - out_print_format_string_header("stn"); + out_print_format_string_header("stn", longest_fname); } ptr = lh->first; while (ptr != NULL) { + if (option_print_boxed_table) out_vsep(); out_print_size(ptr); + if (option_print_boxed_table) out_vsep(); out_print_time_by_option(ptr); + if (option_print_boxed_table) out_vsep(); out_print_fname(ptr); + if (option_print_boxed_table) { + for (i=0; i<(longest_fname-strlen(ptr->fname)); i++) fputc(' ', stdout); + out_vsep(); + } out_print_newline(); /* Linux: Neither man stat(2) nor stat(3type) declare why struct stat field st_size @@ -405,7 +485,12 @@ void print_list(struct list_head *list) { total_size += (ptr->ln_stat.st_size>0) ? (unsigned long int)ptr->ln_stat.st_size : 0; ptr = ptr->next; } - fputc_all_cols('=', stdout); + if (option_print_boxed_table && global_sep_line != NULL) { + fputs(global_sep_line, stdout); + } else { + fputc_all_cols('=', stdout); + } + out_print_newline(); printf("\nTotal size: %lu %s\n", ((total_size>1024) ? total_size/1024 : total_size), ((total_size >= 1024) ? "kB" : "")); @@ -432,7 +517,8 @@ void print_list(struct list_head *list) { void print_list_formatted(const char *format, struct list_head *list) { struct list_head *lh = list; struct list_node *ptr; - size_t format_len = 0, i = 0; + size_t format_len = 0, i = 0, j = 0; + size_t longest_fname = 0; size_t total_size = 0; if (format == NULL || format[0] == '\0') { @@ -458,49 +544,67 @@ void print_list_formatted(const char *format, struct list_head *list) { format_len = strnlen(format, DM_OUT_FORMAT_MAX_LEN); DBGTRC("DEBUG: format_len = %lu\n", format_len); + longest_fname = get_longest_filename(list); + if (option_print_header) { - out_print_format_string_header(format); + out_print_format_string_header(format, longest_fname); } ptr = lh->first; while (ptr != NULL) { + if (option_print_boxed_table) { out_vsep(); } for (i=0; i < format_len; i++) { switch (format[i]) { case 'n': out_print_fname(ptr); + for (j=0; j<(longest_fname - strlen(ptr->fname)); j++) { + fputc(' ', stdout); + } + if (option_print_boxed_table) { out_vsep(); } break; case 's': out_print_size(ptr); + if (option_print_boxed_table) { out_vsep(); } break; case 't': out_print_time_by_option(ptr); + if (option_print_boxed_table) { out_vsep(); } break; case 'A': out_print_time(ptr->ln_stat.st_atim.tv_sec); + if (option_print_boxed_table) { out_vsep(); } break; case 'C': out_print_time(ptr->ln_stat.st_ctim.tv_sec); + if (option_print_boxed_table) { out_vsep(); } break; case 'M': out_print_time(ptr->ln_stat.st_mtim.tv_sec); + if (option_print_boxed_table) { out_vsep(); } break; case 'T': out_print_type(ptr); + if (option_print_boxed_table) { out_vsep(); } break; case 'u': out_print_uid(ptr); + if (option_print_boxed_table) { out_vsep(); } break; case 'g': out_print_gid(ptr); + if (option_print_boxed_table) { out_vsep(); } break; case 'U': out_print_user_name(ptr); + if (option_print_boxed_table) { out_vsep(); } break; case 'G': out_print_group_name(ptr); + if (option_print_boxed_table) { out_vsep(); } break; case 'p': out_print_permissions(ptr); + if (option_print_boxed_table) { out_vsep(); } break; case ' ': /* just ignore this without warning */ break; @@ -513,7 +617,12 @@ void print_list_formatted(const char *format, struct list_head *list) { total_size += (ptr->ln_stat.st_size>0) ? (unsigned long int)ptr->ln_stat.st_size : 0; ptr = ptr->next; } - fputc_all_cols('=', stdout); + if (option_print_boxed_table && global_sep_line != NULL) { + fputs(global_sep_line, stdout); + } else { + fputc_all_cols('=', stdout); + } + out_print_newline(); printf("\nTotal size: %lu %s\n", ((total_size>1024) ? total_size/1024 : total_size), ((total_size >= 1024) ? "kB" : "")); if (lh != list) destroy_list(lh); |
