Date: Wed, 19 Jul 2006 13:49:29 GMT From: "Kęstas Paulikas" <kestas@elen.ktu.lt> To: freebsd-gnats-submit@FreeBSD.org Subject: bin/100535: cal and ncal does not take into account multibyte locale strings Message-ID: <200607191349.k6JDnTKH078401@www.freebsd.org> Resent-Message-ID: <200607191350.k6JDoGNQ059219@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 100535 >Category: bin >Synopsis: cal and ncal does not take into account multibyte locale strings >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Jul 19 13:50:15 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Kęstas Paulikas >Release: FreeBSD 6.1-RELEASE i386 >Organization: Kaunas University of Technology >Environment: FreeBSD silke.prudas.lt 6.1-RELEASE FreeBSD 6.1-RELEASE #0: Wed Jun 7 17:04:57 EEST 2006 root@silke.prudas.lt:/usr/obj/usr/src/sys/SILKE i386 >Description: cal and ncal utilities do not handle multibyte (utf8) locale strings correctly, producing incorectly aligned output. >How-To-Repeat: setenv LANG lt_LT.UTF-8 ncal ncal -y cal -y Short weekday name for Saturday length is 1 instead of 2, day numbers are shifted left. Month names are incorrectly alligned. >Fix: Here is patch. Please review it for errors :) --- src/usr.bin/ncal/ncal.c.orig Wed Nov 24 00:57:17 2004 +++ src/usr.bin/ncal/ncal.c Sun Jul 16 01:03:07 2006 @@ -40,6 +40,7 @@ #include <sysexits.h> #include <time.h> #include <unistd.h> +#include <wchar.h> /* Width of one month with backward compatibility */ #define MONTH_WIDTH_B_J 27 @@ -53,13 +54,13 @@ typedef struct date date; struct monthlines { - char name[MAX_WIDTH + 1]; + wchar_t name[MAX_WIDTH + 1]; char lines[7][MAX_WIDTH + 1]; char weeks[MAX_WIDTH + 1]; }; struct weekdays { - char names[7][4]; + wchar_t names[7][4]; }; /* The switches from Julian to Gregorian in some countries */ @@ -159,6 +160,7 @@ int nswitchb; /* switch date for backward compatibility */ char *center(char *s, char *t, int w); +wchar_t* wcenter(wchar_t *s, wchar_t *t, int w); void mkmonth(int year, int month, int jd_flag, struct monthlines * monthl); void mkmonthb(int year, int month, int jd_flag, struct monthlines * monthl); void mkweekdays(struct weekdays * wds); @@ -418,9 +420,9 @@ mkmonth(y, m - 1, jd_flag, &month); mkweekdays(&wds); - printf(" %s %d\n", month.name, y); + wprintf(L" %S %d\n", month.name, y); for (i = 0; i != 7; i++) - printf("%.2s%s\n", wds.names[i], month.lines[i]); + wprintf(L"%.2S%s\n", wds.names[i], month.lines[i]); if (flag_weeks) printf(" %s\n", month.weeks); } @@ -430,7 +432,7 @@ { struct monthlines month; struct weekdays wds; - char s[MAX_WIDTH], t[MAX_WIDTH]; + wchar_t s[MAX_WIDTH], t[MAX_WIDTH]; int i; int mw; @@ -439,15 +441,15 @@ mw = jd_flag ? MONTH_WIDTH_B_J : MONTH_WIDTH_B; - sprintf(s, "%s %d", month.name, y); - printf("%s\n", center(t, s, mw)); + swprintf(s, MAX_WIDTH, L"%S %d", month.name, y); + wprintf(L"%S\n", wcenter(t, s, mw)); if (jd_flag) - printf(" %s %s %s %s %s %s %.2s\n", wds.names[6], wds.names[0], + wprintf(L" %S %S %S %S %S %S %.2S\n", wds.names[6], wds.names[0], wds.names[1], wds.names[2], wds.names[3], wds.names[4], wds.names[5]); else - printf("%s%s%s%s%s%s%.2s\n", wds.names[6], wds.names[0], + wprintf(L"%S%S%S%S%S%S%.2S\n", wds.names[6], wds.names[0], wds.names[1], wds.names[2], wds.names[3], wds.names[4], wds.names[5]); @@ -475,17 +477,17 @@ printf("%s\n", center(t, s, mpl * mw)); for (j = 0; j != 12; j += mpl) { - printf(" %-*s%-*s", + wprintf(L" %-*S%-*S", mw, year[j].name, mw, year[j + 1].name); if (mpl == 3) - printf("%s\n", year[j + 2].name); + wprintf(L"%S\n", year[j + 2].name); else - printf("%-*s%s\n", + wprintf(L"%-*S%S\n", mw, year[j + 2].name, year[j + 3].name); for (i = 0; i != 7; i++) { - printf("%.2s%-*s%-*s", + wprintf(L"%.2S%-*s%-*s", wds.names[i], mw, year[j].lines[i], mw, year[j + 1].lines[i]); @@ -518,6 +520,7 @@ struct monthlines year[12]; struct weekdays wds; char s[80], t[80]; + wchar_t wcs[80], wct[80]; int i, j; int mpl; int mw; @@ -532,17 +535,17 @@ printf("%s\n\n", center(t, s, mw * mpl + mpl)); for (j = 0; j != 12; j += mpl) { - printf("%-*s ", mw, center(s, year[j].name, mw)); + wprintf(L"%-*S ", mw, wcenter(wcs, year[j].name, mw)); if (mpl == 2) - printf("%s\n", center(s, year[j + 1].name, mw)); + wprintf(L"%S\n", wcenter(wcs, year[j + 1].name, mw)); else - printf("%-*s %s\n", mw, - center(s, year[j + 1].name, mw), - center(t, year[j + 2].name, mw)); + wprintf(L"%-*S %S\n", mw, + wcenter(wcs, year[j + 1].name, mw), + wcenter(wct, year[j + 2].name, mw)); if (mpl == 2) - printf(" %s %s %s %s %s %s %s " - " %s %s %s %s %s %s %.2s\n", + wprintf(L" %S %S %S %S %S %S %S " + " %S %S %S %S %S %S %.2S\n", wds.names[6], wds.names[0], wds.names[1], wds.names[2], wds.names[3], wds.names[4], wds.names[5], @@ -550,9 +553,9 @@ wds.names[2], wds.names[3], wds.names[4], wds.names[5]); else - printf("%s%s%s%s%s%s%s " - "%s%s%s%s%s%s%s " - "%s%s%s%s%s%s%.2s\n", + wprintf(L"%S%S%S%S%S%S%S " + "%S%S%S%S%S%S%S " + "%S%S%S%S%S%S%.2S\n", wds.names[6], wds.names[0], wds.names[1], wds.names[2], wds.names[3], wds.names[4], wds.names[5], @@ -596,8 +599,8 @@ /* Set name of month. */ memset(&tm, 0, sizeof(tm)); tm.tm_mon = m; - strftime(mlines->name, sizeof(mlines->name), "%OB", &tm); - mlines->name[0] = toupper((unsigned char)mlines->name[0]); + wcsftime(mlines->name, sizeof(mlines->name)/sizeof(mlines->name[0]), L"%OB", &tm); + mlines->name[0] = towupper((wint_t)mlines->name[0]); /* * Set first and last to the day number of the first day of this @@ -688,8 +691,8 @@ /* Set name of month centered */ memset(&tm, 0, sizeof(tm)); tm.tm_mon = m; - strftime(mlines->name, sizeof(mlines->name), "%OB", &tm); - mlines->name[0] = toupper((unsigned char)mlines->name[0]); + wcsftime(mlines->name, sizeof(mlines->name)/sizeof(mlines->name[0]), L"%OB", &tm); + mlines->name[0] = towupper((wint_t)mlines->name[0]); /* * Set first and last to the day number of the first day of this @@ -754,18 +757,18 @@ { int i, len; struct tm tm; - char buf[20]; + wchar_t buf[20]; memset(&tm, 0, sizeof(tm)); for (i = 0; i != 7; i++) { tm.tm_wday = (i+1) % 7; - strftime(buf, sizeof(buf), "%a", &tm); - len = strlen(buf); + wcsftime(buf, sizeof(buf)/sizeof(buf[0]), L"%a", &tm); + len = wcslen(buf); if (len > 2) len = 2; - strcpy(wds->names[i], " "); - strncpy(wds->names[i] + 2 - len, buf, len); + wcscpy(wds->names[i], L" "); + wcsncpy(wds->names[i] + 2 - len, buf, len); } } @@ -855,6 +858,17 @@ memset(blanks, ' ', sizeof(blanks)); sprintf(s, "%.*s%s", (int)(w - strlen(t)) / 2, blanks, t); + return (s); +} + +/* Center string t in string s of length w by putting enough leading blanks (wchar_t version) */ +wchar_t * +wcenter(wchar_t *s, wchar_t *t, int w) +{ + char blanks[80]; + + memset(blanks, ' ', sizeof(blanks)); + swprintf(s, 80, L"%.*s%S", (int)(w - wcslen(t)) / 2, blanks, t); return (s); } >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200607191349.k6JDnTKH078401>