Signed-off-by: Daniel Wallace <daniel.wallace@gatech.edu> --- src/pacman/color.c | 728 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/pacman/color.h | 70 ++++++ src/pacman/util.c | 35 ++- src/pacman/util.h | 6 + 4 files changed, 830 insertions(+), 9 deletions(-) create mode 100644 src/pacman/color.c create mode 100644 src/pacman/color.h diff --git a/src/pacman/color.c b/src/pacman/color.c new file mode 100644 index 0000000..d1b2d5e --- /dev/null +++ b/src/pacman/color.c @@ -0,0 +1,728 @@ +/* + * util.c + * + * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <time.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdint.h> /* intmax_t */ +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <dirent.h> +#include <unistd.h> +#include <limits.h> +#include <wchar.h> +#ifdef HAVE_TERMIOS_H +#include <termios.h> /* tcflush */ +#endif + +#include <alpm.h> +#include <alpm_list.h> + +/* pacman */ +#include "util.h" +#include "conf.h" +#include "callback.h" +#include "color.h" + +#define COLOR_LEN 8 + +typedef struct __colortab_t { + char red[COLOR_LEN + 1]; + char green[COLOR_LEN + 1]; + char yellow[COLOR_LEN + 1]; + char blue[COLOR_LEN + 1]; + char magenta[COLOR_LEN + 1]; + char cyan[COLOR_LEN + 1]; + char white[COLOR_LEN + 1]; + char none[COLOR_LEN + 1]; +} colortab_t; + +static colortab_t colortab; + + +void color_list_display(const colordata_t *colors_title, const char *title, const alpm_list_t *list, + unsigned short maxcols) +{ + const alpm_list_t *i; + size_t len = 0; + + if(title) { + len = string_length(title) + 1; + color_printf(colors_title, "%s ", title); + } + + if(!list) { + printf("%s\n", _("None")); + } else { + size_t cols = len; + const char *str = list->data; + fputs(str, stdout); + cols += string_length(str); + for(i = alpm_list_next(list); i; i = alpm_list_next(i)) { + str = i->data; + size_t s = string_length(str); + /* wrap only if we have enough usable column space */ + if(maxcols > len && cols + s + 2 >= maxcols) { + size_t j; + cols = len; + printf("\n"); + for(j = 1; j <= len; j++) { + printf(" "); + } + } else if(cols != len) { + /* 2 spaces are added if this is not the first element on a line. */ + printf(" "); + cols += 2; + } + fputs(str, stdout); + cols += s; + } + putchar('\n'); + } +} + +void color_list_display_linebreak(const colordata_t *colors_title, const char *title, const alpm_list_t *list, + unsigned short maxcols) +{ + unsigned short len = 0; + + if(title) { + len = (unsigned short)string_length(title) + 1; + color_printf(colors_title, "%s ", title); + } + + if(!list) { + printf("%s\n", _("None")); + } else { + const alpm_list_t *i; + /* Print the first element */ + indentprint((const char *)list->data, len, maxcols); + printf("\n"); + /* Print the rest */ + for(i = alpm_list_next(list); i; i = alpm_list_next(i)) { + size_t j; + for(j = 1; j <= len; j++) { + printf(" "); + } + indentprint((const char *)i->data, len, maxcols); + printf("\n"); + } + } +} + +/* prepare a list of pkgs to display */ +void _color_display_targets(alpm_list_t *targets, int verbose) +{ + char *str; + const char *label; + double size; + off_t isize = 0, rsize = 0, dlsize = 0; + unsigned short cols; + alpm_list_t *i, *rows = NULL, *names = NULL; + + if(!targets) { + return; + } + + /* gather package info */ + for(i = targets; i; i = alpm_list_next(i)) { + pm_target_t *target = i->data; + + if(target->install) { + dlsize += alpm_pkg_download_size(target->install); + isize += alpm_pkg_get_isize(target->install); + } + if(target->remove) { + /* add up size of all removed packages */ + rsize += alpm_pkg_get_isize(target->remove); + } + } + + /* form data for both verbose and non-verbose display */ + for(i = targets; i; i = alpm_list_next(i)) { + pm_target_t *target = i->data; + + rows = alpm_list_add(rows, create_verbose_row(target)); + if(target->install) { + pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(target->install), + alpm_pkg_get_version(target->install)); + } else if(isize == 0) { + pm_asprintf(&str, "%s-%s", alpm_pkg_get_name(target->remove), + alpm_pkg_get_version(target->remove)); + } else { + pm_asprintf(&str, "%s-%s [removal]", alpm_pkg_get_name(target->remove), + alpm_pkg_get_version(target->remove)); + } + names = alpm_list_add(names, str); + } + + /* print to screen */ + pm_asprintf(&str, _("Targets (%d):"), alpm_list_count(targets)); + printf("\n"); + + cols = getcols(fileno(stdout)); + if(verbose) { + alpm_list_t *header = create_verbose_header(); + if(table_display(str, header, rows, cols) != 0) { + /* fallback to list display if table wouldn't fit */ + color_list_display(COLOR_YELLOW_ALL, str, names, cols); + } + alpm_list_free(header); + } else { + color_list_display(COLOR_YELLOW_ALL, str, names, cols); + } + printf("\n"); + + /* rows is a list of lists of strings, free inner lists here */ + for(i = rows; i; i = alpm_list_next(i)) { + alpm_list_t *lp = i->data; + FREELIST(lp); + } + alpm_list_free(rows); + FREELIST(names); + free(str); + + if(dlsize > 0 || config->op_s_downloadonly) { + size = humanize_size(dlsize, 'M', 2, &label); + color_printf(COLOR_WHITE_COLON, _("Total Download Size: %.2f %s\n"), size, label); + } + if(!config->op_s_downloadonly) { + if(isize > 0) { + size = humanize_size(isize, 'M', 2, &label); + color_printf(COLOR_WHITE_COLON, _("Total Installed Size: %.2f %s\n"), size, label); + } + if(rsize > 0 && isize == 0) { + size = humanize_size(rsize, 'M', 2, &label); + color_printf(COLOR_WHITE_COLON, _("Total Removed Size: %.2f %s\n"), size, label); + } + /* only show this net value if different from raw installed size */ + if(isize > 0 && rsize > 0) { + size = humanize_size(isize - rsize, 'M', 2, &label); + color_printf(COLOR_WHITE_COLON, _("Net Upgrade Size: %.2f %s\n"), size, label); + } + } +} +void color_display_repo_list(const char *dbname, alpm_list_t *list, + unsigned short cols) +{ + const char *prefix= " "; + + color_printf(COLOR_BLUE_ALL, ":: "); + color_printf(COLOR_WHITE_ALL, _("Repository %s\n"), dbname); + color_list_display(NULL, prefix, list, cols); +} + +/* presents a prompt and gets a Y/N answer */ +static int color_question(const colordata_t *colors, short preset, char *fmt, va_list args) +{ + char response[32]; + FILE *stream; + + if(config->noconfirm) { + stream = stdout; + } else { + /* Use stderr so questions are always displayed when redirecting output */ + stream = stderr; + } + + /* ensure all text makes it to the screen before we prompt the user */ + fflush(stdout); + fflush(stderr); + + color_vfprintf(stream, colors, fmt, args); + + if(preset) { + fprintf(stream, " %s ", _("[Y/n]")); + } else { + fprintf(stream, " %s ", _("[y/N]")); + } + + if(config->noconfirm) { + fprintf(stream, "\n"); + return preset; + } + + fflush(stream); + flush_term_input(fileno(stdin)); + + if(fgets(response, sizeof(response), stdin)) { + strtrim(response); + if(strlen(response) == 0) { + return preset; + } + + /* if stdin is piped, response does not get printed out, and as a result + * a \n is missing, resulting in broken output (FS#27909) */ + if(!isatty(fileno(stdin))) { + fprintf(stream, "%s\n", response); + } + + if(strcasecmp(response, _("Y")) == 0 || strcasecmp(response, _("YES")) == 0) { + return 1; + } else if(strcasecmp(response, _("N")) == 0 || strcasecmp(response, _("NO")) == 0) { + return 0; + } + } + return 0; +} + +int color_yesno(const colordata_t *colors, char *fmt, ...) +{ + int ret; + va_list args; + + va_start(args, fmt); + ret = color_question(colors, 1, fmt, args); + va_end(args); + + return ret; +} + +int color_noyes(const colordata_t *colors, char *fmt, ...) +{ + int ret; + va_list args; + + va_start(args, fmt); + ret = color_question(colors, 0, fmt, args); + va_end(args); + + return ret; +} + +int color_pm_vasprintf(char **string, alpm_loglevel_t level, const char *format, va_list args) +{ + int ret = 0; + char *msg = NULL; + + /* if current logmask does not overlap with level, do not print msg */ + if(!(config->logmask & level)) { + return ret; + } + + /* print the message using va_arg list */ + ret = vasprintf(&msg, format, args); + + /* print a prefix to the message */ + if(isatty(fileno(stdout))) { + switch(level) { + case ALPM_LOG_ERROR: + pm_asprintf(string, "%s%s%s%s", colortab.red, _("error: "), colortab.none, msg); + break; + case ALPM_LOG_WARNING: + pm_asprintf(string, "%s%s%s%s", colortab.yellow, _("warning: "), colortab.none, msg); + break; + case ALPM_LOG_DEBUG: + pm_asprintf(string, "debug: %s", msg); + break; + case ALPM_LOG_FUNCTION: + pm_asprintf(string, "function: %s", msg); + break; + default: + pm_asprintf(string, "%s", msg); + break; + } + } else { + switch(level) { + case ALPM_LOG_ERROR: + pm_asprintf(string, _("error: %s"), msg); + break; + case ALPM_LOG_WARNING: + pm_asprintf(string, _("warning: %s"), msg); + break; + case ALPM_LOG_DEBUG: + pm_asprintf(string, "debug: %s", msg); + break; + case ALPM_LOG_FUNCTION: + pm_asprintf(string, "function: %s", msg); + break; + default: + pm_asprintf(string, "%s", msg); + break; + } + } + free(msg); + + return ret; +} + +int color_pm_vfprintf(FILE *stream, alpm_loglevel_t level, const char *format, va_list args) +{ + int ret = 0; + + /* if current logmask does not overlap with level, do not print msg */ + if(!(config->logmask & level)) { + return ret; + } + +#if defined(PACMAN_DEBUG) + /* If debug is on, we'll timestamp the output */ + if(config->logmask & ALPM_LOG_DEBUG) { + time_t t; + struct tm *tmp; + char timestr[10] = {0}; + + t = time(NULL); + tmp = localtime(&t); + strftime(timestr, 9, "%H:%M:%S", tmp); + timestr[8] = '\0'; + + fprintf(stream, "[%s] ", timestr); + } +#endif + + /* print a prefix to the message */ + switch(level) { + case ALPM_LOG_ERROR: + color_fprintf(stream, COLOR_RED_ALL, _("error: ")); + break; + case ALPM_LOG_WARNING: + color_fprintf(stream, COLOR_YELLOW_ALL, _("warning: ")); + break; + case ALPM_LOG_DEBUG: + fprintf(stream, "debug: "); + break; + case ALPM_LOG_FUNCTION: + fprintf(stream, "function: "); + break; + default: + break; + } + + /* print the message using va_arg list */ + ret = vfprintf(stream, format, args); + return ret; +} + +/* pacman-color */ + +int _set_color_sequence(const char* name, char* dest) +{ + int ret = 0; + + if(strcmp(name, "black") == 0) { + strncpy(dest, "\033[0;30m", COLOR_LEN); + } else if(strcmp(name, "red") == 0) { + strncpy(dest, "\033[0;31m", COLOR_LEN); + } else if(strcmp(name, "green") == 0) { + strncpy(dest, "\033[0;32m", COLOR_LEN); + } else if(strcmp(name, "yellow") == 0) { + strncpy(dest, "\033[0;33m", COLOR_LEN); + } else if(strcmp(name, "blue") == 0) { + strncpy(dest, "\033[0;34m", COLOR_LEN); + } else if(strcmp(name, "magenta") == 0) { + strncpy(dest, "\033[0;35m", COLOR_LEN); + } else if(strcmp(name, "cyan") == 0) { + strncpy(dest, "\033[0;36m", COLOR_LEN); + } else if(strcmp(name, "white") == 0) { + strncpy(dest, "\033[0;37m", COLOR_LEN); + } else if(strcmp(name, "gray") == 0) { + strncpy(dest, "\033[1;30m", COLOR_LEN); + } else if(strcmp(name, "intensive red") == 0) { + strncpy(dest, "\033[1;31m", COLOR_LEN); + } else if(strcmp(name, "intensive green") == 0) { + strncpy(dest, "\033[1;32m", COLOR_LEN); + } else if(strcmp(name, "intensive yellow") == 0) { + strncpy(dest, "\033[1;33m", COLOR_LEN); + } else if(strcmp(name, "intensive blue") == 0) { + strncpy(dest, "\033[1;34m", COLOR_LEN); + } else if(strcmp(name, "intensive magenta") == 0) { + strncpy(dest, "\033[1;35m", COLOR_LEN); + } else if(strcmp(name, "intensive cyan") == 0) { + strncpy(dest, "\033[1;36m", COLOR_LEN); + } else if(strcmp(name, "intensive white") == 0) { + strncpy(dest, "\033[1;37m", COLOR_LEN); + } else if(strcmp(name, "intensive foreground") == 0) { + strncpy(dest, "\033[m\033[1m", COLOR_LEN); + } else if(strcmp(name, "none") == 0) { + strncpy(dest, "\033[m", COLOR_LEN); + } else { + ret = 1; + } + dest[COLOR_LEN] = '\0'; + return(ret); +} + +void _insert_color(FILE* stream, color_t color) +{ + switch(color) { + case COLOR_RED: + fprintf(stream, colortab.red); + break; + case COLOR_GREEN: + fprintf(stream, colortab.green); + break; + case COLOR_YELLOW: + fprintf(stream, colortab.yellow); + break; + case COLOR_BLUE: + fprintf(stream, colortab.blue); + break; + case COLOR_MAGENTA: + fprintf(stream, colortab.magenta); + break; + case COLOR_CYAN: + fprintf(stream, colortab.cyan); + break; + case COLOR_WHITE: + fprintf(stream, colortab.white); + break; + case COLOR_NONE: + fprintf(stream, colortab.none); + break; + default:; + } +} + +int _parsecolorconfig(colortab_t* colortab, char* file) +{ + _set_color_sequence("intensive red", colortab->red); + _set_color_sequence("intensive green", colortab->green); + _set_color_sequence("intensive yellow", colortab->yellow); + _set_color_sequence("intensive blue", colortab->blue); + _set_color_sequence("intensive magenta", colortab->magenta); + _set_color_sequence("intensive cyan", colortab->cyan); + _set_color_sequence("intensive foreground", colortab->white); + _set_color_sequence("none", colortab->none); + + FILE* fp = NULL; + int linenum = 0; + char line[PATH_MAX+1]; + char* ptr; + + fp = fopen(file, "r"); + if(fp == NULL) { + pm_printf(ALPM_LOG_ERROR, _("config file %s could not be read.\n"), file); + return 1; + } + while(fgets(line, PATH_MAX, fp)) { + linenum++; + strtrim(line); + + if(strlen(line) == 0 || line[0] == '#') { + continue; + } + if((ptr = strchr(line, '#'))) { + *ptr = '\0'; + } + + char* key = line; + ptr = line; + strsep(&ptr, "="); + strtrim(key); + strtrim(ptr); + + if(key == NULL) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: syntax error in config file- missing key.\n"), + file, linenum); + return 1; + } + if(strcmp(key, "Red") == 0) { + if(_set_color_sequence(ptr, colortab->red)) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"), + file, linenum, ptr); + } + } else if(strcmp(key, "Green") == 0) { + if(_set_color_sequence(ptr, colortab->green)) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"), + file, linenum, ptr); + } + } else if(strcmp(key, "Yellow") == 0) { + if(_set_color_sequence(ptr, colortab->yellow)) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"), + file, linenum, ptr); + } + } else if(strcmp(key, "Blue") == 0) { + if(_set_color_sequence(ptr, colortab->blue)) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"), + file, linenum, ptr); + } + } else if(strcmp(key, "Magenta") == 0) { + if(_set_color_sequence(ptr, colortab->magenta)) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"), + file, linenum, ptr); + } + } else if(strcmp(key, "Cyan") == 0) { + if(_set_color_sequence(ptr, colortab->cyan)) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"), + file, linenum, ptr); + } + } else if(strcmp(key, "White") == 0) { + if(_set_color_sequence(ptr, colortab->white)) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: color '%s' not recognized.\n"), + file, linenum, ptr); + } + } else { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' not recognized.\n"), + file, linenum, key); + return(1); + } + } + return(0); +} + +int parsecolorconfig() +{ + return(_parsecolorconfig(&colortab, config->colorfile)); +} + +int color_vfprintf(FILE* stream, const colordata_t* colors, const char* format, va_list args) +{ + int ret = 0; + + if(isatty(fileno(stream)) && colors) { + char* msg = NULL; + ret = vasprintf(&msg, format, args); + if(msg == NULL) { + return(ret); + } + + const colordata_t* colorpos = colors; + color_t colorlast = COLOR_NONE; + int len = strlen(msg) + 1; + wchar_t* wcstr = calloc(len, sizeof(wchar_t)); + len = mbstowcs(wcstr, msg, len); + free(msg); + const wchar_t *strpos = wcstr; + + while(*strpos) { + if(colorpos->color != COLOR_END && + ((colorpos->separator == SEP_ANY) || + (colorpos->separator == SEP_LINE && *strpos == L'\n') || + (colorpos->separator == SEP_COLON && (*strpos == L':' || *strpos == L':')))) { + _insert_color(stream, colorpos->color); + colorlast = colorpos->color; + colorpos++; + } + fprintf(stream, "%lc", (wint_t)*strpos); + strpos++; + } + free(wcstr); + + if(colorlast != COLOR_NONE) { + _insert_color(stream, COLOR_NONE); + } + } else { + ret = vfprintf(stream, format, args); + } + return(ret); +} + +int color_fprintf(FILE* stream, const colordata_t* colors, const char* format, ...) +{ + int ret; + va_list args; + va_start(args, format); + ret = color_vfprintf(stream, colors, format, args); + va_end(args); + return(ret); +} + +int color_printf(const colordata_t* colors, const char* format, ...) +{ + int ret; + va_list args; + va_start(args, format); + ret = color_vfprintf(stdout, colors, format, args); + va_end(args); + return(ret); +} + +void color_string_display(const colordata_t* colors_title, const char* title, const colordata_t* colors_string, const char* string) +{ + if(title) { + color_printf(colors_title, "%s ", title); + } + if(string == NULL || string[0] == '\0') { + printf(_("None")); + } else { + color_printf(colors_string, "%s", string); + } + printf("\n"); +} + +const colordata_t COLOR_WHITE_ALL[] = { + { SEP_ANY, COLOR_WHITE }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +const colordata_t COLOR_GREEN_ALL[] = { + { SEP_ANY, COLOR_GREEN }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +const colordata_t COLOR_RED_ALL[] = { + { SEP_ANY, COLOR_RED }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +const colordata_t COLOR_BLUE_ALL[] = { + { SEP_ANY, COLOR_BLUE }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +const colordata_t COLOR_YELLOW_ALL[] = { + { SEP_ANY, COLOR_YELLOW }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +const colordata_t COLOR_MAGENTA_ALL[] = { + { SEP_ANY, COLOR_MAGENTA }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +const colordata_t COLOR_CYAN_ALL[] = { + { SEP_ANY, COLOR_CYAN }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +const colordata_t COLOR_DOUBLECOLON[] = { + { SEP_ANY, COLOR_BLUE }, + { SEP_ANY, COLOR_SAME }, + { SEP_ANY, COLOR_WHITE }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +const colordata_t COLOR_DOUBLECOLON2[] = { + { SEP_ANY, COLOR_BLUE }, + { SEP_ANY, COLOR_SAME }, + { SEP_ANY, COLOR_WHITE }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_BLUE }, + { SEP_ANY, COLOR_SAME }, + { SEP_ANY, COLOR_WHITE }, + { SEP_LINE, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +const colordata_t COLOR_WHITE_COLON[] = { + { SEP_ANY, COLOR_WHITE }, + { SEP_COLON, COLOR_SAME }, + { SEP_ANY, COLOR_NONE }, + { SEP_ANY, COLOR_END } }; + +/* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/color.h b/src/pacman/color.h new file mode 100644 index 0000000..c833e2e --- /dev/null +++ b/src/pacman/color.h @@ -0,0 +1,70 @@ +#ifndef _PM_COLOR_H +#define _PM_COLOR_H + +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include <alpm_list.h> + +/* pacman-color */ +typedef enum _separator_t { + SEP_ANY = 0, + SEP_LINE, + SEP_COLON, +} separator_t; + +typedef enum _color_t { + COLOR_END = 0, + COLOR_SAME, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW, + COLOR_BLUE, + COLOR_MAGENTA, + COLOR_CYAN, + COLOR_WHITE, + COLOR_NONE, +} color_t; + +typedef struct _colordata_t { + separator_t separator; + color_t color; +} colordata_t; + +extern const colordata_t COLOR_WHITE_ALL[]; +extern const colordata_t COLOR_GREEN_ALL[]; +extern const colordata_t COLOR_RED_ALL[]; +extern const colordata_t COLOR_BLUE_ALL[]; +extern const colordata_t COLOR_YELLOW_ALL[]; +extern const colordata_t COLOR_MAGENTA_ALL[]; +extern const colordata_t COLOR_CYAN_ALL[]; +extern const colordata_t COLOR_DOUBLECOLON[]; +extern const colordata_t COLOR_DOUBLECOLON2[]; +extern const colordata_t COLOR_WHITE_COLON[]; + +/* util.c */ + +void color_list_display(const colordata_t *colors_title, const char *title, const alpm_list_t *list, + unsigned short maxcols); +void color_list_display_linebreak(const colordata_t *colors_title, const char *title, const alpm_list_t *list, + unsigned short maxcols); +void _color_display_targets(alpm_list_t *targets, int verbose); +void color_display_repo_list(const char *dbname, alpm_list_t *list, + unsigned short col); +int color_yesno(const colordata_t *colors, char *fmt, ...); +int color_noyes(const colordata_t *colors, char *fmt, ...); +int color_pm_vasprintf(char **string, alpm_loglevel_t level, const char *format, va_list args); +int color_pm_vfprintf(FILE *stream, alpm_loglevel_t level, const char *format, va_list args); +int _set_color_sequence(const char* name, char* dest); +void _insert_color(FILE* stream, color_t color); +int parsecolorconfig(); +int color_fprintf(FILE* stream, const colordata_t* colors, const char* format, ...) __attribute__((format(printf,3,4))); +int color_printf(const colordata_t* colors, const char* format, ...) __attribute__((format(printf,2,3))); + +int color_vfprintf(FILE* stream, const colordata_t* colors, const char* format, va_list args) __attribute__((format(printf,3,0))); + +void color_string_display(const colordata_t* colors_title, const char* title, const colordata_t* colors_string, const char* string); + +#endif +/* vim: set ts=2 sw=2 noet: */ diff --git a/src/pacman/util.c b/src/pacman/util.c index 7f7f6a7..f750542 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -45,6 +45,7 @@ #include "util.h" #include "conf.h" #include "callback.h" +#include "color.h" int trans_init(alpm_transflag_t flags, int check_valid) @@ -130,7 +131,7 @@ int check_syncdbs(size_t need_repos, int check_valid) } /* discard unhandled input on the terminal's input buffer */ -static int flush_term_input(int fd) { +int flush_term_input(int fd) { #ifdef HAVE_TCFLUSH if(isatty(fd)) { return tcflush(fd, TCIFLUSH); @@ -442,7 +443,7 @@ alpm_list_t *strsplit(const char *str, const char splitchar) return list; } -static size_t string_length(const char *s) +size_t string_length(const char *s) { int len; wchar_t *wcstr; @@ -605,7 +606,7 @@ static size_t table_calc_widths(const alpm_list_t *header, * @param cols the number of columns available in the terminal * @return -1 if not enough terminal cols available, else 0 */ -static int table_display(const char *title, const alpm_list_t *header, +int table_display(const char *title, const alpm_list_t *header, const alpm_list_t *rows, unsigned short cols) { const unsigned short padding = 2; @@ -794,7 +795,7 @@ void signature_display(const char *title, alpm_siglist_t *siglist, } /* creates a header row for use with table_display */ -static alpm_list_t *create_verbose_header(void) +alpm_list_t *create_verbose_header(void) { alpm_list_t *res = NULL; char *str; @@ -814,7 +815,7 @@ static alpm_list_t *create_verbose_header(void) } /* returns package info as list of strings */ -static alpm_list_t *create_verbose_row(pm_target_t *target) +alpm_list_t *create_verbose_row(pm_target_t *target) { char *str; off_t size = 0; @@ -1007,7 +1008,11 @@ void display_targets(void) } targets = alpm_list_msort(targets, alpm_list_count(targets), target_cmp); - _display_targets(targets, config->verbosepkglists); + if (config->color) { + _color_display_targets(targets, config->verbosepkglists); + } else { + _display_targets(targets, config->verbosepkglists); + } FREELIST(targets); } @@ -1263,7 +1268,11 @@ void select_display(const alpm_list_t *pkglist) if(!dbname) dbname = alpm_db_get_name(db); if(strcmp(alpm_db_get_name(db), dbname) != 0) { - display_repo_list(dbname, list, cols); + if (config->color) { + color_display_repo_list(dbname, list, cols); + } else { + display_repo_list(dbname, list, cols); + } FREELIST(list); dbname = alpm_db_get_name(db); } @@ -1272,7 +1281,11 @@ void select_display(const alpm_list_t *pkglist) list = alpm_list_add(list, string); nth++; } - display_repo_list(dbname, list, cols); + if (config->color) { + color_display_repo_list(dbname, list, cols); + } else { + display_repo_list(dbname, list, cols); + } FREELIST(list); } @@ -1551,7 +1564,11 @@ int pm_printf(alpm_loglevel_t level, const char *format, ...) /* print the message using va_arg list */ va_start(args, format); - ret = pm_vfprintf(stderr, level, format, args); + if (config->color) { + ret = color_pm_vfprintf(stderr, level, format, args); + } else { + ret = pm_vfprintf(stderr, level, format, args); + } va_end(args); return ret; diff --git a/src/pacman/util.h b/src/pacman/util.h index 0dfdc85..d15164f 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -47,6 +47,7 @@ int trans_init(alpm_transflag_t flags, int check_valid); int trans_release(void); int needs_root(void); int check_syncdbs(size_t need_repos, int check_valid); +int flush_term_input(int fd); unsigned short getcols(int fd); int rmrf(const char *path); const char *mbasename(const char *path); @@ -55,15 +56,20 @@ void indentprint(const char *str, unsigned short indent, unsigned short cols); size_t strtrim(char *str); char *strreplace(const char *str, const char *needle, const char *replace); alpm_list_t *strsplit(const char *str, const char splitchar); +size_t string_length(const char *s); void string_display(const char *title, const char *string, unsigned short cols); double humanize_size(off_t bytes, const char target_unit, int precision, const char **label); +int table_display(const char *title, const alpm_list_t *header, + const alpm_list_t *rows, unsigned short cols); void list_display(const char *title, const alpm_list_t *list, unsigned short maxcols); void list_display_linebreak(const char *title, const alpm_list_t *list, unsigned short maxcols); void signature_display(const char *title, alpm_siglist_t *siglist, unsigned short maxcols); +alpm_list_t *create_verbose_header(void); +alpm_list_t *create_verbose_row(pm_target_t *target); void display_targets(void); int str_cmp(const void *s1, const void *s2); void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg); -- 1.7.11.4