summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pacman/callback.c89
-rw-r--r--src/pacman/package.c15
-rw-r--r--src/pacman/util.c73
3 files changed, 130 insertions, 47 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;
}
diff --git a/src/pacman/package.c b/src/pacman/package.c
index cc4be139..7019e7e6 100644
--- a/src/pacman/package.c
+++ b/src/pacman/package.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
+#include <wchar.h>
#include <alpm.h>
#include <alpm_list.h>
@@ -48,6 +49,8 @@ void dump_pkg_full(pmpkg_t *pkg, int level)
char bdatestr[50] = "", idatestr[50] = "";
const alpm_list_t *i;
alpm_list_t *requiredby = NULL, *depstrings = NULL;
+ wchar_t *wcstr;
+ int len;
if(pkg == NULL) {
return;
@@ -86,8 +89,6 @@ void dump_pkg_full(pmpkg_t *pkg, int level)
requiredby = alpm_pkg_compute_requiredby(pkg);
}
- descheader = _("Description : ");
-
/* actual output */
if(level == 0) {
string_display(_("Filename :"), alpm_pkg_get_filename(pkg));
@@ -136,8 +137,16 @@ void dump_pkg_full(pmpkg_t *pkg, int level)
}
/* printed using a variable to make i18n safe */
+ descheader = _("Description : ");
+ /* len goes from # bytes -> # chars -> # cols */
+ len = strlen(descheader) + 1;
+ wcstr = calloc(len, sizeof(wchar_t));
+ len = mbstowcs(wcstr, descheader, len);
+ len = wcswidth(wcstr, len);
+ free(wcstr);
+ /* we can finally print the darn thing */
printf("%s", descheader);
- indentprint(alpm_pkg_get_desc(pkg), mbstowcs(NULL, descheader, 0));
+ indentprint(alpm_pkg_get_desc(pkg), len);
printf("\n\n");
/* Print additional package info if info flag passed more than once */
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 2dae832f..229f65a2 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -34,6 +34,7 @@
#include <dirent.h>
#include <unistd.h>
#include <limits.h>
+#include <wchar.h>
#include <alpm.h>
#include <alpm_list.h>
@@ -219,41 +220,54 @@ char *mdirname(const char *path)
*/
void indentprint(const char *str, int indent)
{
- const char *p = str;
- int cidx = indent;
+ wchar_t *wcstr;
+ const wchar_t *p;
+ int len, cidx;
+
+ if(!str) {
+ return;
+ }
+
+ len = strlen(str) + 1;
+ wcstr = calloc(len, sizeof(wchar_t));
+ len = mbstowcs(wcstr, str, len);
+ p = wcstr;
+ cidx = indent;
if(!p) {
return;
}
while(*p) {
- if(*p == ' ') {
- const char *next = NULL;
- int len;
+ if(*p == L' ') {
+ const wchar_t *q, *next;
p++;
- if(p == NULL || *p == ' ') continue;
- next = strchr(p, ' ');
+ if(p == NULL || *p == L' ') continue;
+ next = wcschr(p, L' ');
if(next == NULL) {
- next = p + mbstowcs(NULL, p, 0);
+ next = p + wcslen(p);
+ }
+ /* len captures # cols */
+ len = 0;
+ q = p;
+ while(q < next) {
+ len += wcwidth(*q++);
}
- len = next - p;
if(len > (getcols() - cidx - 1)) {
- /* newline */
- int i;
- fprintf(stdout, "\n");
- for(i = 0; i < indent; i++) {
- fprintf(stdout, " ");
- }
+ /* wrap to a newline and reindent */
+ fprintf(stdout, "\n%-*s", indent, "");
cidx = indent;
} else {
printf(" ");
cidx++;
}
+ continue;
}
- fprintf(stdout, "%c", *p);
+ fprintf(stdout, "%lc", (wint_t)*p);
+ cidx += wcwidth(*p);
p++;
- cidx++;
}
+ free(wcstr);
}
/* Convert a string to uppercase
@@ -393,14 +407,31 @@ void list_display(const char *title, const alpm_list_t *list)
{
const alpm_list_t *i;
int cols, len;
-
- len = mbstowcs(NULL, title, 0);
- printf("%s ", title);
+ wchar_t *wcstr;
+
+ if(title) {
+ /* len goes from # bytes -> # chars -> # cols */
+ len = strlen(title) + 1;
+ wcstr = calloc(len, sizeof(wchar_t));
+ len = mbstowcs(wcstr, title, len);
+ len = wcswidth(wcstr, len);
+ free(wcstr);
+ printf("%s ", title);
+ } else {
+ len = 0;
+ }
if(list) {
for(i = list, cols = len; i; i = alpm_list_next(i)) {
char *str = alpm_list_getdata(i);
- int s = mbstowcs(NULL, str, 0) + 2;
+ /* s goes from # bytes -> # chars -> # cols */
+ int s = strlen(str) + 1;
+ wcstr = calloc(s, sizeof(wchar_t));
+ s = mbstowcs(wcstr, str, s);
+ s = wcswidth(wcstr, s);
+ free(wcstr);
+ /* two additional spaces are added to the length */
+ s += 2;
int maxcols = getcols();
if(s + cols >= maxcols) {
int i;