diff options
Diffstat (limited to 'src/pacman/callback.c')
-rw-r--r-- | src/pacman/callback.c | 89 |
1 files changed, 66 insertions, 23 deletions
diff --git a/src/pacman/callback.c b/src/pacman/callback.c index d4de0567..b16c79ee 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -34,8 +34,6 @@ #include "util.h" #include "conf.h" -#define FILENAME_TRIM_LEN 23 - /* download progress bar */ static float rate_last; static int xfered_last; @@ -313,8 +311,11 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent, /* size of line to allocate for text printing (e.g. not progressbar) */ const int infolen = 50; - int tmp, digits, oprlen, textlen, remainlen; + int tmp, digits, textlen; char *opr = NULL; + /* used for wide character width determination and printing */ + int len, wclen, wcwid, padwid; + wchar_t *wcstr; if(config->noprogressbar) { return; @@ -363,27 +364,41 @@ void cb_trans_progress(pmtransprog_t event, const char *pkgname, int percent, while((tmp /= 10)) { ++digits; } - /* determine room left for non-digits text [not ( 1/12) part] */ textlen = infolen - 3 - (2 * digits); - oprlen = mbstowcs(NULL, opr, 0); - /* room left (eg for package name) */ - remainlen = textlen - oprlen - 1; + /* In order to deal with characters from all locales, we have to worry + * about wide characters and their column widths. A lot of stuff is + * done here to figure out the actual number of screen columns used + * by the output, and then pad it accordingly so we fill the terminal. + */ + /* len = opr len + pkgname len (if available) + space + null */ + len = strlen(opr) + ((pkgname) ? strlen(pkgname) : 0) + 2; + wcstr = calloc(len, sizeof(wchar_t)); + /* print our strings to the alloc'ed memory */ + wclen = swprintf(wcstr, len, L"%s %s", opr, pkgname); + wcwid = wcswidth(wcstr, wclen); + padwid = textlen - wcwid; + /* if padwid is < 0, we need to trim the string so padwid = 0 */ + if(padwid < 0) { + int i = textlen - 3; + wchar_t *p = wcstr; + /* grab the max number of char columns we can fill */ + while(i > 0 && wcwidth(*p) < i) { + i -= wcwidth(*p); + p++; + } + /* then add the ellipsis and fill out any extra padding */ + wcscpy(p, L"..."); + padwid = i; - switch (event) { - case PM_TRANS_PROGRESS_ADD_START: - case PM_TRANS_PROGRESS_UPGRADE_START: - case PM_TRANS_PROGRESS_REMOVE_START: - printf("(%*d/%*d) %s %-*.*s", digits, remain, digits, howmany, - opr, remainlen, remainlen, pkgname); - break; - case PM_TRANS_PROGRESS_CONFLICTS_START: - printf("(%*d/%*d) %s %-*s", digits, remain, digits, howmany, - opr, remainlen, ""); - break; } + printf("(%*d/%*d) %ls%-*s", digits, remain, digits, howmany, + wcstr, padwid, ""); + + free(wcstr); + /* call refactored fill progress function */ fill_progress(percent, percent, getcols() - infolen); @@ -405,7 +420,11 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total, int list_xfered, int list_total) { const int infolen = 50; + const int filenamelen = infolen - 27; char *fname, *p; + /* used for wide character width determination and printing */ + int len, wclen, wcwid, padwid; + wchar_t *wcfname; float rate = 0.0, timediff = 0.0, f_xfered = 0.0; unsigned int eta_h = 0, eta_m = 0, eta_s = 0; @@ -485,8 +504,30 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total, if((p = strstr(fname, PKGEXT)) || (p = strstr(fname, DBEXT))) { *p = '\0'; } - if(strlen(fname) > FILENAME_TRIM_LEN) { - strcpy(fname + FILENAME_TRIM_LEN -3,"..."); + /* In order to deal with characters from all locales, we have to worry + * about wide characters and their column widths. A lot of stuff is + * done here to figure out the actual number of screen columns used + * by the output, and then pad it accordingly so we fill the terminal. + */ + /* len = filename len + null */ + len = strlen(filename) + 1; + wcfname = calloc(len, sizeof(wchar_t)); + wclen = mbstowcs(wcfname, fname, len); + wcwid = wcswidth(wcfname, wclen); + padwid = filenamelen - wcwid; + /* if padwid is < 0, we need to trim the string so padwid = 0 */ + if(padwid < 0) { + int i = filenamelen - 3; + wchar_t *p = wcfname; + /* grab the max number of char columns we can fill */ + while(i > 0 && wcwidth(*p) < i) { + i -= wcwidth(*p); + p++; + } + /* then add the ellipsis and fill out any extra padding */ + wcscpy(p, L"..."); + padwid = i; + } /* Awesome formatting for progress bar. We need a mess of Kb->Mb->Gb stuff @@ -516,10 +557,12 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total, } } - printf(" %-*s %6.1f%c %#6.1f%c/s %02u:%02u:%02u", FILENAME_TRIM_LEN, fname, - f_xfered, xfered_size, rate, rate_size, eta_h, eta_m, eta_s); + printf(" %ls%-*s %6.1f%c %#6.1f%c/s %02u:%02u:%02u", wcfname, + padwid, "", f_xfered, xfered_size, + rate, rate_size, eta_h, eta_m, eta_s); free(fname); + free(wcfname); /* The progress bar is based on the file percent regardless of the * TotalDownload option. */ @@ -532,7 +575,7 @@ void cb_dl_progress(const char *filename, int file_xfered, int file_total, /* Callback to handle notifications from the library */ void cb_log(pmloglevel_t level, char *fmt, va_list args) { - if(!strlen(fmt)) { + if(!fmt || strlen(fmt) == 0) { return; } |