git: 8c108b341cd8 - main - ncal: add -M to start week on Monday in cal mode

From: Warner Losh <imp_at_FreeBSD.org>
Date: Sun, 07 Jul 2024 11:56:40 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=8c108b341cd82d0ed9fcd573764bc94682e84125

commit 8c108b341cd82d0ed9fcd573764bc94682e84125
Author:     Valentine Astakhov <justsomelessons@gmail.com>
AuthorDate: 2024-06-17 17:58:02 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-07-07 11:55:36 +0000

    ncal: add -M to start week on Monday in cal mode
    
    MFC after: 2 weeks
    Reviewed by: imp, Alexander Ziaee,
    Pull Request: https://github.com/freebsd/freebsd-src/pull/1294
---
 usr.bin/ncal/ncal.1 | 16 ++++++++++------
 usr.bin/ncal/ncal.c | 34 +++++++++++++++++++++++-----------
 2 files changed, 33 insertions(+), 17 deletions(-)

diff --git a/usr.bin/ncal/ncal.1 b/usr.bin/ncal/ncal.1
index a0b6889dca31..8ece31b79cc1 100644
--- a/usr.bin/ncal/ncal.1
+++ b/usr.bin/ncal/ncal.1
@@ -1,3 +1,6 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
 .\" Copyright (c) 1997 Wolfgang Helbig
 .\" All rights reserved.
 .\"
@@ -31,7 +34,7 @@
 .Nd displays a calendar and the date of Easter
 .Sh SYNOPSIS
 .Nm
-.Op Fl 3hjy
+.Op Fl 3hjMy
 .Op Fl A Ar number
 .Op Fl B Ar number
 .Oo
@@ -39,7 +42,7 @@
 .Ar year
 .Oc
 .Nm
-.Op Fl 3hj
+.Op Fl 3hjM
 .Op Fl A Ar number
 .Op Fl B Ar number
 .Fl m Ar month
@@ -85,6 +88,10 @@ option, display date of Easter according to the Julian Calendar.
 Display date of Easter (for western churches).
 .It Fl j
 Display Julian days (days one-based, numbered from January 1).
+.It Fl M
+Display Monday as the first day of the week in
+.Nm cal
+mode.
 .It Fl m Ar month
 Display the specified
 .Ar month .
@@ -186,7 +193,7 @@ X/Open System Interfaces option of the
 specification.
 .Pp
 The flags
-.Op Fl 3hyJeopw ,
+.Op Fl 3ehJMopwy ,
 as well as the ability to specify a month name as a single argument,
 are extensions to that specification.
 .Pp
@@ -215,6 +222,3 @@ codes is historically naive for many countries.
 .Pp
 Not all options are compatible and using them in different orders
 will give varying results.
-.Pp
-It is not possible to display Monday as the first day of the week with
-.Nm cal .
diff --git a/usr.bin/ncal/ncal.c b/usr.bin/ncal/ncal.c
index 6f5e1e89bf93..2829caf8a6a0 100644
--- a/usr.bin/ncal/ncal.c
+++ b/usr.bin/ncal/ncal.c
@@ -36,6 +36,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 #include <sysexits.h>
 #include <time.h>
 #include <unistd.h>
@@ -162,6 +163,7 @@ static int flag_weeks;		/* user wants number of week */
 static int nswitch;		/* user defined switch date */
 static int nswitchb;		/* switch date for backward compatibility */
 static int highlightdate;
+static bool flag_monday;	/* user wants week starts on Monday */
 
 static char	*center(char *s, char *t, int w);
 static wchar_t *wcenter(wchar_t *s, wchar_t *t, int w);
@@ -216,6 +218,7 @@ main(int argc, char *argv[])
 
 	flag_nohighlight = 0;
 	flag_weeks = 0;
+	flag_monday = false;
 
 	/*
 	 * Use locale to determine the country code,
@@ -256,7 +259,7 @@ main(int argc, char *argv[])
 
 	before = after = -1;
 
-	while ((ch = getopt(argc, argv, "3A:B:Cd:eH:hjJm:Nops:wy")) != -1)
+	while ((ch = getopt(argc, argv, "3A:B:Cd:eH:hjJm:Nops:wyM")) != -1)
 		switch (ch) {
 		case '3':
 			flag_3months = 1;
@@ -306,6 +309,9 @@ main(int argc, char *argv[])
 		case 'j':
 			flag_julian_day = 1;
 			break;
+		case 'M':
+			flag_monday = true;
+			break;
 		case 'm':
 			if (flag_specifiedmonth)
 				errx(EX_USAGE, "Double -m specified");
@@ -509,7 +515,7 @@ usage(void)
 "       cal [general options] [-hj] [-m month] [year]\n"
 "       ncal [general options] [-hJjpwy] [-s country_code] [[month] year]\n"
 "       ncal [general options] [-hJeo] [year]\n"
-"General options: [-NC3] [-A months] [-B months]\n"
+"General options: [-NCM3] [-A months] [-B months]\n"
 "For debug the highlighting: [-H yyyy-mm-dd] [-d yyyy-mm]\n",
 	    stderr);
 	exit(EX_USAGE);
@@ -652,10 +658,13 @@ monthrangeb(int y, int m, int jd_flag, int before, int after)
 		/* Day of the week names. */
 		for (i = 0; i < count; i++) {
 			wprintf(L"%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls ",
-				wdss, wds.names[6], wdss, wds.names[0],
-				wdss, wds.names[1], wdss, wds.names[2],
-				wdss, wds.names[3], wdss, wds.names[4],
-				wdss, wds.names[5]);
+				wdss, wds.names[flag_monday ? 0 : 6],
+				wdss, wds.names[flag_monday ? 1 : 0],
+				wdss, wds.names[flag_monday ? 2 : 1],
+				wdss, wds.names[flag_monday ? 3 : 2],
+				wdss, wds.names[flag_monday ? 4 : 3],
+				wdss, wds.names[flag_monday ? 5 : 4],
+				wdss, wds.names[flag_monday ? 6 : 5]);
 		}
 		printf("\n");
 
@@ -860,7 +869,7 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines)
 	date    dt;		/* handy date */
 	int     dw;		/* width of numbers */
 	int     first;		/* first day of month */
-	int     firsts;		/* sunday of first week of month */
+	int     firstsm;	/* sunday or monday of first week of month */
 	int     i, j, k, l;	/* just indices */
 	int     jan1 = 0;	/* the first day of this year */
 	int     last;		/* the first day of next month */
@@ -911,10 +920,13 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines)
 	}
 
 	/*
-	 * Set firsts to the day number of sunday of the first week of
-	 * this month. (This might be in the last month)
+	 * Set firstsm to the day number of sunday or monday of the first week
+	 * of this month. (This might be in the last month)
 	 */
-	firsts = first - (weekday(first)+1) % 7;
+	if (flag_monday)
+		firstsm = first - weekday(first);
+	else
+		firstsm = first - (weekday(first) + 1) % 7;
 
 	/*
 	 * Fill the lines with day of month or day of year (Julian day)
@@ -923,7 +935,7 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines)
 	 */
 	for (i = 0; i != 6; i++) {
 		l = 0;
-		for (j = firsts + 7 * i, k = 0; j < last && k != dw * 7;
+		for (j = firstsm + 7 * i, k = 0; j < last && k != dw * 7;
 		    j++, k += dw) {
 			if (j >= first) {
 				if (jd_flag)