From 39ab9676914bd0d8105d0f96bbd7611a53077438 Mon Sep 17 00:00:00 2001
From: Miles Alan <m@milesalan.com>
Date: Sat, 4 Jul 2020 11:19:04 -0500
Subject: [PATCH] Add -g option to display entries in the given number of grid
 columns

This option can be used in conjunction with -l to format dmenu's options in
arbitrary size grids. For example, to create a 4 column by 6 line grid, you
could use: dmenu -g 4 -l 6
---
 config.def.h |  3 ++-
 dmenu.1      |  7 ++++++-
 dmenu.c      | 22 ++++++++++++++++------
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/config.def.h b/config.def.h
index 1edb647..96cf3c9 100644
--- a/config.def.h
+++ b/config.def.h
@@ -13,8 +13,9 @@ static const char *colors[SchemeLast][2] = {
 	[SchemeSel] = { "#eeeeee", "#005577" },
 	[SchemeOut] = { "#000000", "#00ffff" },
 };
-/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
+/* -l and -g options; controls number of lines and columns in grid if > 0 */
 static unsigned int lines      = 0;
+static unsigned int columns    = 0;
 
 /*
  * Characters not considered part of a word while deleting words
diff --git a/dmenu.1 b/dmenu.1
index 323f93c..d0a734a 100644
--- a/dmenu.1
+++ b/dmenu.1
@@ -4,6 +4,8 @@ dmenu \- dynamic menu
 .SH SYNOPSIS
 .B dmenu
 .RB [ \-bfiv ]
+.RB [ \-g
+.IR columns ]
 .RB [ \-l
 .IR lines ]
 .RB [ \-m
@@ -47,8 +49,11 @@ is faster, but will lock up X until stdin reaches end\-of\-file.
 .B \-i
 dmenu matches menu items case insensitively.
 .TP
+.BI \-g " columns"
+dmenu lists items in a grid with the given number of columns.
+.TP
 .BI \-l " lines"
-dmenu lists items vertically, with the given number of lines.
+dmenu lists items in a grid with the given number of lines.
 .TP
 .BI \-m " monitor"
 dmenu is displayed on the monitor number supplied. Monitor numbers are starting
diff --git a/dmenu.c b/dmenu.c
index 6b8f51b..d79b6bb 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -77,7 +77,7 @@ calcoffsets(void)
 	int i, n;
 
 	if (lines > 0)
-		n = lines * bh;
+		n = lines * columns * bh;
 	else
 		n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">"));
 	/* calculate which items will begin the next page and previous page */
@@ -152,9 +152,15 @@ drawmenu(void)
 	}
 
 	if (lines > 0) {
-		/* draw vertical list */
-		for (item = curr; item != next; item = item->right)
-			drawitem(item, x, y += bh, mw - x);
+		/* draw grid */
+		int i = 0;
+		for (item = curr; item != next; item = item->right, i++)
+			drawitem(
+				item,
+				x + ((i / lines) *  ((mw - x) / columns)),
+				y + (((i % lines) + 1) * bh),
+				(mw - x) / columns
+			);
 	} else if (matches) {
 		/* draw horizontal list */
 		x += inputw;
@@ -708,9 +714,13 @@ main(int argc, char *argv[])
 		} else if (i + 1 == argc)
 			usage();
 		/* these options take one argument */
-		else if (!strcmp(argv[i], "-l"))   /* number of lines in vertical list */
+		else if (!strcmp(argv[i], "-g")) {   /* number of columns in grid */
+			columns = atoi(argv[++i]);
+			if (lines == 0) lines = 1;
+		} else if (!strcmp(argv[i], "-l")) { /* number of lines in grid */
 			lines = atoi(argv[++i]);
-		else if (!strcmp(argv[i], "-m"))
+			if (columns == 0) columns = 1;
+		} else if (!strcmp(argv[i], "-m"))
 			mon = atoi(argv[++i]);
 		else if (!strcmp(argv[i], "-p"))   /* adds prompt to left of input field */
 			prompt = argv[++i];
-- 
2.23.1

