-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathrandom-image-v33.patch
99 lines (92 loc) · 2.79 KB
/
random-image-v33.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
From 7383a00cf4cb2e5011ff9060465616c97d2044ac Mon Sep 17 00:00:00 2001
From: NRK <[email protected]>
Date: Tue, 11 Feb 2025 14:15:03 +0000
Subject: [PATCH] add keybind to switch to random image
---
commands.c | 32 ++++++++++++++++++++++++++++++++
commands.h | 2 ++
config.def.h | 1 +
main.c | 1 +
4 files changed, 36 insertions(+)
diff --git a/commands.c b/commands.c
index 3257b1e..672f74a 100644
--- a/commands.c
+++ b/commands.c
@@ -477,3 +477,35 @@ bool ct_select(arg_t _)
return dirty;
}
+
+/*
+ * NOTE(NRK): could be faster with __builtin_clz(), but i've opted for portibility instead.
+ * ref: https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+ */
+static unsigned int next_power_of_2_modmask(unsigned int v)
+{
+ --v;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ return v;
+}
+
+/*
+ * rejects any baised samples with the bitmask approach described in:
+ * https://www.pcg-random.org/posts/bounded-rands.html
+ */
+bool cg_random(arg_t _)
+{
+ if (filecnt >= 2) {
+ int n;
+ unsigned int mask = next_power_of_2_modmask(filecnt);
+ do {
+ n = rand() & mask;
+ } while (n >= filecnt || n == fileidx);
+ return navigate_to(n);
+ }
+ return false;
+}
diff --git a/commands.h b/commands.h
index 4e694f0..10b5008 100644
--- a/commands.h
+++ b/commands.h
@@ -23,6 +23,7 @@ bool cg_toggle_fullscreen(arg_t);
bool cg_toggle_image_mark(arg_t);
bool cg_unmark_all(arg_t);
bool cg_zoom(arg_t);
+bool cg_random(arg_t);
/* image mode */
bool ci_alternate(arg_t);
bool ci_cursor_navigate(arg_t);
@@ -69,6 +70,7 @@ bool ct_select(arg_t);
#define g_toggle_image_mark { cg_toggle_image_mark, MODE_ALL }
#define g_unmark_all { cg_unmark_all, MODE_ALL }
#define g_zoom { cg_zoom, MODE_ALL }
+#define g_random { cg_random, MODE_ALL }
/* image mode */
#define i_alternate { ci_alternate, MODE_IMAGE }
diff --git a/config.def.h b/config.def.h
index ead1509..1d4d0f4 100644
--- a/config.def.h
+++ b/config.def.h
@@ -107,6 +107,7 @@ static const keymap_t keys[] = {
{ ControlMask, XK_x, g_prefix_external, None },
{ 0, XK_g, g_first, None },
{ 0, XK_G, g_n_or_last, None },
+ { ControlMask, XK_r, g_random, None },
{ 0, XK_r, g_reload_image, None },
{ 0, XK_D, g_remove_image, None },
{ ControlMask, XK_h, g_scroll_screen, DIR_LEFT },
diff --git a/main.c b/main.c
index 6ca2f11..9dba4c2 100644
--- a/main.c
+++ b/main.c
@@ -901,6 +901,7 @@ int main(int argc, char *argv[])
setup_signal(SIGCHLD, SIG_DFL, SA_RESTART | SA_NOCLDSTOP | SA_NOCLDWAIT);
setup_signal(SIGPIPE, SIG_IGN, 0);
+ srand(time(NULL));
setlocale(LC_COLLATE, "");
parse_options(argc, argv);
--
2.46.2