From nobody@FreeBSD.org  Wed Feb 11 02:29:13 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 05EA7106568A
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 11 Feb 2009 02:29:13 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id E8D118FC15
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 11 Feb 2009 02:29:12 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n1B2TCqB048751
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 11 Feb 2009 02:29:12 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n1B2TCWK048750;
	Wed, 11 Feb 2009 02:29:12 GMT
	(envelope-from nobody)
Message-Id: <200902110229.n1B2TCWK048750@www.freebsd.org>
Date: Wed, 11 Feb 2009 02:29:12 GMT
From: robert wilson <hotaru@thinkindifferent.net>
To: freebsd-gnats-submit@FreeBSD.org
Subject: /usr/bin/cal doesn't handle multibyte characters correctly
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         131578
>Category:       bin
>Synopsis:       cal(1) doesn't handle multibyte characters correctly
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    das
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Feb 11 02:30:00 UTC 2009
>Closed-Date:    Sun Mar 22 05:45:54 UTC 2009
>Last-Modified:  Sun Mar 22 05:50:00 UTC 2009
>Originator:     robert wilson
>Release:        7.1-RELEASE
>Organization:
>Environment:
FreeBSD olorin.thinkindifferent.net 7.1-RELEASE FreeBSD 7.1-RELEASE #0: Thu Jan  1 14:37:25 UTC 2009     root@logan.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
/usr/bin/cal outputs incorrect utf-8 in certain locales.
a few locales that show this problem are is_IS.UTF-8, es_ES.UTF-8, hu_HU.UTF-8, zh_CN.UTF-8, ja_JP.UTF-8... el_GR.UTF-8 even causes it to crash with a segmentation fault!
>How-To-Repeat:
execute the command "LC_ALL=is_IS.UTF-8 /usr/bin/cal".
or, "LC_ALL=el_GR.UTF-8 /usr/bin/cal".
>Fix:


>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->feedback 
State-Changed-By: das 
State-Changed-When: Sat Feb 28 17:18:50 UTC 2009 
State-Changed-Why:  
feedback requested 


Responsible-Changed-From-To: freebsd-bugs->das 
Responsible-Changed-By: das 
Responsible-Changed-When: Sat Feb 28 17:18:50 UTC 2009 
Responsible-Changed-Why:  
over to me 

http://www.freebsd.org/cgi/query-pr.cgi?pr=131578 

From: David Schultz <das@FreeBSD.ORG>
To: robert wilson <hotaru@thinkindifferent.net>
Cc: bug-followup@FreeBSD.ORG
Subject: Re: bin/131578: /usr/bin/cal doesn't handle multibyte characters correctly
Date: Sat, 28 Feb 2009 12:21:21 -0500

 Could you please try this patch?
 
 Index: ncal.c
 ===================================================================
 --- ncal.c	(revision 187877)
 +++ ncal.c	(working copy)
 @@ -40,6 +40,8 @@
  #include <sysexits.h>
  #include <time.h>
  #include <unistd.h>
 +#include <wchar.h>
 +#include <wctype.h>
  
  /* Width of one month with backward compatibility */
  #define MONTH_WIDTH_B_J 27
 @@ -53,13 +55,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 +161,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 +421,9 @@
  
  	mkmonth(y, m - 1, jd_flag, &month);
  	mkweekdays(&wds);
 -	printf("    %s %d\n", month.name, y);
 +	printf("    %ls %d\n", month.name, y);
  	for (i = 0; i != 7; i++)
 -		printf("%.2s%s\n", wds.names[i], month.lines[i]);
 +		printf("%.2ls%s\n", wds.names[i], month.lines[i]);
  	if (flag_weeks)
  		printf("  %s\n", month.weeks);
  }
 @@ -430,7 +433,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 +442,16 @@
  
  	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"%ls %d", month.name, y);
 +	wprintf(L"%ls\n", wcenter(t, s, mw));
  
  	if (jd_flag)
 -		printf(" %s %s %s %s %s %s %.2s\n", wds.names[6], wds.names[0],
 +		printf(" %ls %ls %ls %ls %ls %ls %.2ls\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],
 +		printf("%ls%ls%ls%ls%ls%ls%.2ls\n", wds.names[6], wds.names[0],
  			wds.names[1], wds.names[2], wds.names[3],
  			wds.names[4], wds.names[5]);
  
 @@ -475,17 +479,17 @@
  	printf("%s\n", center(t, s, mpl * mw));
  
  	for (j = 0; j != 12; j += mpl) {
 -		printf("    %-*s%-*s",
 +		printf("    %-*ls%-*ls",
  		    mw, year[j].name,
  		    mw, year[j + 1].name);
  		if (mpl == 3)
 -			printf("%s\n", year[j + 2].name);
 +			printf("%ls\n", year[j + 2].name);
  		else
 -			printf("%-*s%s\n",
 +			printf("%-*ls%ls\n",
  		    	    mw, year[j + 2].name,
  		    	    year[j + 3].name);
  		for (i = 0; i != 7; i++) {
 -			printf("%.2s%-*s%-*s",
 +			printf("%.2ls%-*s%-*s",
  			    wds.names[i],
  			    mw, year[j].lines[i],
  			    mw, year[j + 1].lines[i]);
 @@ -518,6 +522,7 @@
  	struct monthlines year[12];
  	struct weekdays wds;
  	char	s[80], t[80];
 +	wchar_t	ws[80], wt[80];
  	int     i, j;
  	int     mpl;
  	int     mw;
 @@ -532,17 +537,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));
 +		printf("%-*ls  ", mw, wcenter(ws, year[j].name, mw));
  		if (mpl == 2)
 -			printf("%s\n", center(s, year[j + 1].name, mw));
 +			printf("%ls\n", wcenter(ws, 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));
 +			printf("%-*ls  %ls\n", mw,
 +			    wcenter(ws, year[j + 1].name, mw),
 +			    wcenter(wt, year[j + 2].name, mw));
  
  		if (mpl == 2)
 -			printf(" %s %s %s %s %s %s %s "
 -			       " %s %s %s %s %s %s %.2s\n",
 +			printf(" %ls %ls %ls %ls %ls %ls %ls "
 +			       " %ls %ls %ls %ls %ls %ls %.2ls\n",
  				wds.names[6], wds.names[0], wds.names[1],
  				wds.names[2], wds.names[3], wds.names[4],
  				wds.names[5],
 @@ -550,9 +555,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",
 +			printf("%ls%ls%ls%ls%ls%ls%ls "
 +				"%ls%ls%ls%ls%ls%ls%ls "
 +				"%ls%ls%ls%ls%ls%ls%.2ls\n",
  				wds.names[6], wds.names[0], wds.names[1],
  				wds.names[2], wds.names[3], wds.names[4],
  				wds.names[5],
 @@ -596,8 +601,9 @@
  	/* 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(mlines->name[0]);
  
  	/*
  	 * Set first and last to the day number of the first day of this
 @@ -688,8 +694,9 @@
  	/* 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(mlines->name[0]);
  
  	/*
  	 * Set first and last to the day number of the first day of this
 @@ -754,18 +761,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), 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);
  	}
  }
  
 @@ -858,6 +865,17 @@
  	return (s);
  }
  
 +/* Center string t in string s of length w by putting enough leading blanks */
 +wchar_t *
 +wcenter(wchar_t *s, wchar_t *t, int w)
 +{
 +	char blanks[80];
 +
 +	memset(blanks, ' ', sizeof(blanks));
 +	swprintf(s, MAX_WIDTH, L"%.*s%ls", (int)(w - wcslen(t)) / 2, blanks, t);
 +	return (s);
 +}
 +
  int
  parsemonth(const char *s, int *m, int *y)
  {

From: robert wilson <hotaru@thinkindifferent.net>
To: David Schultz <das@FreeBSD.ORG>
Cc: bug-followup@FreeBSD.ORG
Subject: Re: bin/131578: /usr/bin/cal doesn't handle multibyte characters
 correctly
Date: Sat, 28 Feb 2009 14:06:27 -0500

 David Schultz wrote:
 > Could you please try this patch?
 >   
 that seems to work, except that the the two locales that caused it to
 crash before only show one character for the last day of the week ("Κυ
 Δε Τρ Τε Πε Πα Σ" for el_GR.UTF-8 and "Ня Да Мя Лх Пү Ба Б" for
 mn_MN.UTF-8)...
State-Changed-From-To: feedback->patched 
State-Changed-By: das 
State-Changed-When: Sat Mar 14 18:56:31 UTC 2009 
State-Changed-Why:  
Patched in HEAD, r189804. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=131578 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/131578: commit references a PR
Date: Sat, 14 Mar 2009 18:56:02 +0000 (UTC)

 Author: das
 Date: Sat Mar 14 18:55:51 2009
 New Revision: 189804
 URL: http://svn.freebsd.org/changeset/base/189804
 
 Log:
   Multibyte character support for cal(1).
   
   PR:		131578
 
 Modified:
   head/usr.bin/ncal/ncal.1
   head/usr.bin/ncal/ncal.c
 
 Modified: head/usr.bin/ncal/ncal.1
 ==============================================================================
 --- head/usr.bin/ncal/ncal.1	Sat Mar 14 18:24:15 2009	(r189803)
 +++ head/usr.bin/ncal/ncal.1	Sat Mar 14 18:55:51 2009	(r189804)
 @@ -24,7 +24,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd October 23, 2005
 +.Dd March 14, 2009
  .Dt CAL 1
  .Os
  .Sh NAME
 @@ -142,7 +142,3 @@ command and manual were written by
  .Sh BUGS
  The assignment of Julian\(enGregorian switching dates to
  country codes is historically naive for many countries.
 -.Pp
 -The
 -.Nm
 -utility does not recognize multibyte characters.
 
 Modified: head/usr.bin/ncal/ncal.c
 ==============================================================================
 --- head/usr.bin/ncal/ncal.c	Sat Mar 14 18:24:15 2009	(r189803)
 +++ head/usr.bin/ncal/ncal.c	Sat Mar 14 18:55:51 2009	(r189804)
 @@ -40,6 +40,8 @@ static const char rcsid[] =
  #include <sysexits.h>
  #include <time.h>
  #include <unistd.h>
 +#include <wchar.h>
 +#include <wctype.h>
  
  /* Width of one month with backward compatibility */
  #define MONTH_WIDTH_B_J 27
 @@ -53,13 +55,13 @@ static const char rcsid[] =
  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 +161,7 @@ int     nswitch;		/* user defined switch
  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 +421,9 @@ printmonth(int y, int m, int jd_flag)
  
  	mkmonth(y, m - 1, jd_flag, &month);
  	mkweekdays(&wds);
 -	printf("    %s %d\n", month.name, y);
 +	printf("    %ls %d\n", month.name, y);
  	for (i = 0; i != 7; i++)
 -		printf("%.2s%s\n", wds.names[i], month.lines[i]);
 +		printf("%.2ls%s\n", wds.names[i], month.lines[i]);
  	if (flag_weeks)
  		printf("  %s\n", month.weeks);
  }
 @@ -430,7 +433,7 @@ printmonthb(int y, int m, int jd_flag)
  {
  	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,16 +442,17 @@ printmonthb(int y, int m, int jd_flag)
  
  	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"%ls %d", month.name, y);
 +	wprintf(L"%ls\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" %ls %ls %ls %ls %ls %ls %.2ls\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],
 -			wds.names[1], wds.names[2], wds.names[3],
 +		wprintf(L"%ls%ls%ls%ls%ls%ls%.2ls\n", wds.names[6],
 +			wds.names[0], wds.names[1], wds.names[2], wds.names[3],
  			wds.names[4], wds.names[5]);
  
  	for (i = 0; i != 6; i++)
 @@ -475,17 +479,17 @@ printyear(int y, int jd_flag)
  	printf("%s\n", center(t, s, mpl * mw));
  
  	for (j = 0; j != 12; j += mpl) {
 -		printf("    %-*s%-*s",
 +		printf("    %-*ls%-*ls",
  		    mw, year[j].name,
  		    mw, year[j + 1].name);
  		if (mpl == 3)
 -			printf("%s\n", year[j + 2].name);
 +			printf("%ls\n", year[j + 2].name);
  		else
 -			printf("%-*s%s\n",
 +			printf("%-*ls%ls\n",
  		    	    mw, year[j + 2].name,
  		    	    year[j + 3].name);
  		for (i = 0; i != 7; i++) {
 -			printf("%.2s%-*s%-*s",
 +			printf("%.2ls%-*s%-*s",
  			    wds.names[i],
  			    mw, year[j].lines[i],
  			    mw, year[j + 1].lines[i]);
 @@ -518,6 +522,7 @@ printyearb(int y, int jd_flag)
  	struct monthlines year[12];
  	struct weekdays wds;
  	char	s[80], t[80];
 +	wchar_t	ws[80], wt[80];
  	int     i, j;
  	int     mpl;
  	int     mw;
 @@ -532,17 +537,17 @@ printyearb(int y, int jd_flag)
  	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));
 +		printf("%-*ls  ", mw, wcenter(ws, year[j].name, mw));
  		if (mpl == 2)
 -			printf("%s\n", center(s, year[j + 1].name, mw));
 +			printf("%ls\n", wcenter(ws, 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));
 +			printf("%-*ls  %ls\n", mw,
 +			    wcenter(ws, year[j + 1].name, mw),
 +			    wcenter(wt, 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" %ls %ls %ls %ls %ls %ls %ls "
 +				" %ls %ls %ls %ls %ls %ls %.2ls\n",
  				wds.names[6], wds.names[0], wds.names[1],
  				wds.names[2], wds.names[3], wds.names[4],
  				wds.names[5],
 @@ -550,9 +555,9 @@ printyearb(int y, int jd_flag)
  				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"%ls%ls%ls%ls%ls%ls%ls "
 +				"%ls%ls%ls%ls%ls%ls%ls "
 +				"%ls%ls%ls%ls%ls%ls%.2ls\n",
  				wds.names[6], wds.names[0], wds.names[1],
  				wds.names[2], wds.names[3], wds.names[4],
  				wds.names[5],
 @@ -596,8 +601,9 @@ mkmonth(int y, int m, int jd_flag, struc
  	/* 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(mlines->name[0]);
  
  	/*
  	 * Set first and last to the day number of the first day of this
 @@ -688,8 +694,9 @@ mkmonthb(int y, int m, int jd_flag, stru
  	/* 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(mlines->name[0]);
  
  	/*
  	 * Set first and last to the day number of the first day of this
 @@ -754,18 +761,18 @@ mkweekdays(struct weekdays *wds)
  {
  	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), 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);
  	}
  }
  
 @@ -858,6 +865,17 @@ center(char *s, char *t, int w)
  	return (s);
  }
  
 +/* Center string t in string s of length w by putting enough leading blanks */
 +wchar_t *
 +wcenter(wchar_t *s, wchar_t *t, int w)
 +{
 +	char blanks[80];
 +
 +	memset(blanks, ' ', sizeof(blanks));
 +	swprintf(s, MAX_WIDTH, L"%.*s%ls", (int)(w - wcslen(t)) / 2, blanks, t);
 +	return (s);
 +}
 +
  int
  parsemonth(const char *s, int *m, int *y)
  {
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: das 
State-Changed-When: Sun Mar 22 05:45:17 UTC 2009 
State-Changed-Why:  
merged to releng7 

http://www.freebsd.org/cgi/query-pr.cgi?pr=131578 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/131578: commit references a PR
Date: Sun, 22 Mar 2009 05:45:11 +0000 (UTC)

 Author: das
 Date: Sun Mar 22 05:44:56 2009
 New Revision: 190240
 URL: http://svn.freebsd.org/changeset/base/190240
 
 Log:
   MFC r189804:
     Multibyte character support for cal(1).
   
     PR:		131578
 
 Modified:
   stable/7/usr.bin/ncal/   (props changed)
   stable/7/usr.bin/ncal/ncal.1
   stable/7/usr.bin/ncal/ncal.c
 
 Modified: stable/7/usr.bin/ncal/ncal.1
 ==============================================================================
 --- stable/7/usr.bin/ncal/ncal.1	Sun Mar 22 04:32:05 2009	(r190239)
 +++ stable/7/usr.bin/ncal/ncal.1	Sun Mar 22 05:44:56 2009	(r190240)
 @@ -24,7 +24,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd October 23, 2005
 +.Dd March 14, 2009
  .Dt CAL 1
  .Os
  .Sh NAME
 @@ -134,7 +134,3 @@ command and manual were written by
  .Sh BUGS
  The assignment of Julian\(emGregorian switching dates to
  country codes is historically naive for many countries.
 -.Pp
 -The
 -.Nm
 -utility does not recognize multibyte characters.
 
 Modified: stable/7/usr.bin/ncal/ncal.c
 ==============================================================================
 --- stable/7/usr.bin/ncal/ncal.c	Sun Mar 22 04:32:05 2009	(r190239)
 +++ stable/7/usr.bin/ncal/ncal.c	Sun Mar 22 05:44:56 2009	(r190240)
 @@ -40,6 +40,8 @@ static const char rcsid[] =
  #include <sysexits.h>
  #include <time.h>
  #include <unistd.h>
 +#include <wchar.h>
 +#include <wctype.h>
  
  /* Width of one month with backward compatibility */
  #define MONTH_WIDTH_B_J 27
 @@ -53,13 +55,13 @@ static const char rcsid[] =
  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 +161,7 @@ int     nswitch;		/* user defined switch
  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 +421,9 @@ printmonth(int y, int m, int jd_flag)
  
  	mkmonth(y, m - 1, jd_flag, &month);
  	mkweekdays(&wds);
 -	printf("    %s %d\n", month.name, y);
 +	printf("    %ls %d\n", month.name, y);
  	for (i = 0; i != 7; i++)
 -		printf("%.2s%s\n", wds.names[i], month.lines[i]);
 +		printf("%.2ls%s\n", wds.names[i], month.lines[i]);
  	if (flag_weeks)
  		printf("  %s\n", month.weeks);
  }
 @@ -430,7 +433,7 @@ printmonthb(int y, int m, int jd_flag)
  {
  	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,16 +442,17 @@ printmonthb(int y, int m, int jd_flag)
  
  	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"%ls %d", month.name, y);
 +	wprintf(L"%ls\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" %ls %ls %ls %ls %ls %ls %.2ls\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],
 -			wds.names[1], wds.names[2], wds.names[3],
 +		wprintf(L"%ls%ls%ls%ls%ls%ls%.2ls\n", wds.names[6],
 +			wds.names[0], wds.names[1], wds.names[2], wds.names[3],
  			wds.names[4], wds.names[5]);
  
  	for (i = 0; i != 6; i++)
 @@ -475,17 +479,17 @@ printyear(int y, int jd_flag)
  	printf("%s\n", center(t, s, mpl * mw));
  
  	for (j = 0; j != 12; j += mpl) {
 -		printf("    %-*s%-*s",
 +		printf("    %-*ls%-*ls",
  		    mw, year[j].name,
  		    mw, year[j + 1].name);
  		if (mpl == 3)
 -			printf("%s\n", year[j + 2].name);
 +			printf("%ls\n", year[j + 2].name);
  		else
 -			printf("%-*s%s\n",
 +			printf("%-*ls%ls\n",
  		    	    mw, year[j + 2].name,
  		    	    year[j + 3].name);
  		for (i = 0; i != 7; i++) {
 -			printf("%.2s%-*s%-*s",
 +			printf("%.2ls%-*s%-*s",
  			    wds.names[i],
  			    mw, year[j].lines[i],
  			    mw, year[j + 1].lines[i]);
 @@ -518,6 +522,7 @@ printyearb(int y, int jd_flag)
  	struct monthlines year[12];
  	struct weekdays wds;
  	char	s[80], t[80];
 +	wchar_t	ws[80], wt[80];
  	int     i, j;
  	int     mpl;
  	int     mw;
 @@ -532,17 +537,17 @@ printyearb(int y, int jd_flag)
  	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));
 +		printf("%-*ls  ", mw, wcenter(ws, year[j].name, mw));
  		if (mpl == 2)
 -			printf("%s\n", center(s, year[j + 1].name, mw));
 +			printf("%ls\n", wcenter(ws, 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));
 +			printf("%-*ls  %ls\n", mw,
 +			    wcenter(ws, year[j + 1].name, mw),
 +			    wcenter(wt, 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" %ls %ls %ls %ls %ls %ls %ls "
 +				" %ls %ls %ls %ls %ls %ls %.2ls\n",
  				wds.names[6], wds.names[0], wds.names[1],
  				wds.names[2], wds.names[3], wds.names[4],
  				wds.names[5],
 @@ -550,9 +555,9 @@ printyearb(int y, int jd_flag)
  				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"%ls%ls%ls%ls%ls%ls%ls "
 +				"%ls%ls%ls%ls%ls%ls%ls "
 +				"%ls%ls%ls%ls%ls%ls%.2ls\n",
  				wds.names[6], wds.names[0], wds.names[1],
  				wds.names[2], wds.names[3], wds.names[4],
  				wds.names[5],
 @@ -596,8 +601,9 @@ mkmonth(int y, int m, int jd_flag, struc
  	/* 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(mlines->name[0]);
  
  	/*
  	 * Set first and last to the day number of the first day of this
 @@ -688,8 +694,9 @@ mkmonthb(int y, int m, int jd_flag, stru
  	/* 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(mlines->name[0]);
  
  	/*
  	 * Set first and last to the day number of the first day of this
 @@ -754,18 +761,18 @@ mkweekdays(struct weekdays *wds)
  {
  	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), 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);
  	}
  }
  
 @@ -858,6 +865,17 @@ center(char *s, char *t, int w)
  	return (s);
  }
  
 +/* Center string t in string s of length w by putting enough leading blanks */
 +wchar_t *
 +wcenter(wchar_t *s, wchar_t *t, int w)
 +{
 +	char blanks[80];
 +
 +	memset(blanks, ' ', sizeof(blanks));
 +	swprintf(s, MAX_WIDTH, L"%.*s%ls", (int)(w - wcslen(t)) / 2, blanks, t);
 +	return (s);
 +}
 +
  int
  parsemonth(const char *s)
  {
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
