diff --git a/dwm/.dmenu/.gitignore b/dwm/.dmenu/.gitignore new file mode 100644 index 0000000..3ef527d --- /dev/null +++ b/dwm/.dmenu/.gitignore @@ -0,0 +1,5 @@ +*.o +config.h +patches.h +dmenu +stest diff --git a/dwm/.dmenu/Makefile b/dwm/.dmenu/Makefile index a03a95c..f4be9d1 100644 --- a/dwm/.dmenu/Makefile +++ b/dwm/.dmenu/Makefile @@ -20,7 +20,10 @@ options: config.h: cp config.def.h $@ -$(OBJ): arg.h config.h config.mk drw.h +patches.h: + cp patches.def.h $@ + +$(OBJ): arg.h config.h config.mk drw.h patches.h dmenu: dmenu.o drw.o util.o $(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS) diff --git a/dwm/.dmenu/README.md b/dwm/.dmenu/README.md new file mode 100644 index 0000000..e328022 --- /dev/null +++ b/dwm/.dmenu/README.md @@ -0,0 +1,260 @@ +Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this dmenu 5.2 (e42c036, +2022-10-26) project has a different take on patching. It uses preprocessor directives to decide +whether or not to include a patch during build time. Essentially this means that this build, for +better or worse, contains both the patched _and_ the original code. The aim being that you can +select which patches to include and the build will contain that code and nothing more. + +For example to include the `alpha` patch then you would only need to flip this setting from 0 +to 1 in [patches.h](https://github.com/bakkeby/dmenu-flexipatch/blob/master/patches.def.h): +```c +#define ALPHA_PATCH 1 +``` + +Once you have found out what works for you and what doesn't then you should be in a better position +to choose patches should you want to start patching from scratch. + +Alternatively if you have found the patches you want, but don't want the rest of the flexipatch +entanglement on your plate then you may want to have a look at +[flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer); a custom pre-processor +tool that removes all the unused flexipatch code leaving you with a build that contains the patches +you selected. + +Refer to [https://tools.suckless.org/dmenu/](https://tools.suckless.org/dmenu/) for details on +dmenu, how to install it and how it works. + +Browsing patches? There is a [map of patches](https://coggle.it/diagram/YjT2DD6jBM9dayf3) diagram which tries to organise patches into categories. + +--- + +### Changelog: + +2022-09-05 - Removed the json patch due to maintenance and compatibility reasons, added the + separator patch + +2022-09-04 - Added the fzfexpect patch + +2022-06-21 - Adding barpadding patch and relative input width patch + +2022-03-02 - Bump to 5.1 + +2021-05-23 - Adding support for `ctrl+v` to paste and adding emoji-highlight patch + +2021-05-17 - Added the restrict return, no sort, gridnav and plain-prompt (listfullwidth) patches + +2021-05-15 - Added the tsv and printindex patches + +2020-08-08 - Added the json, symbols, managed, morecolor, multi-selection and preselect patches + +2020-08-05 - Added the grid, highlight, highpriority, dynamic options and numbers patches + +2020-06-13 - Added the pango patch + +2020-06-10 - Added the case-insensitive patch + +2020-05-29 - Added the alpha patch (derived from Baitinq's [build](https://github.com/Baitinq/dmenu)) + and the color emoji patch + +2020-04-05 - Added fuzzyhighlight patch + +2020-02-09 - Added revised border patch (adding command line parameter for setting border width) + +2019-12-29 - Added xresources patch + +2019-10-16 - Introduced [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer) + +2019-09-18 - Added border, center, fuzzymatch, incremental, initialtext, instant, line-height, + mouse-support, navhistory, non-blocking-stdin, password, pipeout, printinputtext, + rejectnomatch, scroll, vertfull, wmtype and xyw patches + +### Patches included: + + - [alpha](https://github.com/bakkeby/patches/blob/master/dmenu/dmenu-alpha-5.0_20210725_523aa08.diff) + - adds transparency for the dmenu window + + - [barpadding](https://github.com/bakkeby/patches/wiki/barpadding) + - adds padding for dmenu in similar fashion to the [barpadding](https://dwm.suckless.org/patches/barpadding/) + patch for dwm + + - [border](http://tools.suckless.org/dmenu/patches/border/) + - adds a border around the dmenu window + + - [case-insensitive](http://tools.suckless.org/dmenu/patches/case-insensitive/) + - makes dmenu case-insensitive by default, replacing the case-insensitive `-i` option with a + case sensitive `-s` option + + - [center](https://tools.suckless.org/dmenu/patches/center/) + - this patch centers dmenu in the middle of the screen + + - color_emoji + - enables color emoji in dmenu by removing a workaround for a BadLength error in the Xft + library when color glyphs are used + - enabling this will crash dmenu on encountering such glyphs unless you also have an updated + Xft library that can handle them + + - [dynamic_options](https://tools.suckless.org/dmenu/patches/dynamicoptions/) + - adds a flag (`-dy`) which makes dmenu run the command given to it whenever input is changed + with the current input as the last argument and update the option list according to the + output of that command + + - [emoji-highlight](https://tools.suckless.org/dmenu/patches/emoji-highlight/) + - this patch will allow for emojis on the left side with a colored background when selected + + - [fuzzyhighlight](https://tools.suckless.org/dmenu/patches/fuzzyhighlight/) + - intended to be combined with the fuzzymatch patch, this makes it so that fuzzy matches are + highlighted + + - [fuzzymatch](https://tools.suckless.org/dmenu/patches/fuzzymatch/) + - adds support for fuzzy-matching to dmenu, allowing users to type non-consecutive portions + of the string to be matched + + - [fzfexpect](https://github.com/DAFF0D11/dafmenu/blob/master/patches/dmenu-fzfexpect-5.1.diff) + - adds fzf expect functionality in dmenu + + - [grid](https://tools.suckless.org/dmenu/patches/grid/) + - allows dmenu's entries to be rendered in a grid by adding a new `-g` flag to specify the + number of grid columns + - the `-g` and `-l` options can be used together to create a G columns * L lines grid + + - [gridnav](https://tools.suckless.org/dmenu/patches/gridnav/) + - adds the ability to move left and right through a grid (when using the grid patch) + + - [highlight](https://tools.suckless.org/dmenu/patches/highlight/) + - this patch highlights the individual characters of matched text for each dmenu list entry + + - [highpriority](https://tools.suckless.org/dmenu/patches/highpriority/) + - this patch will automatically sort the search result so that high priority items are shown + first + + - [incremental](https://tools.suckless.org/dmenu/patches/incremental/) + - this patch causes dmenu to print out the current text each time a key is pressed + + - [initialtext](https://tools.suckless.org/dmenu/patches/initialtext/) + - adds an option to provide preselected text + + - [instant](https://tools.suckless.org/dmenu/patches/instant/) + - adds a flag that will cause dmenu to select an item immediately if there is only one + matching option left + + - [~json~](https://tools.suckless.org/dmenu/patches/json/) + - ~adds basic support for json files~ + + - [line-height](http://tools.suckless.org/dmenu/patches/line-height/) + - adds a `-h` option which sets the minimum height of a dmenu line + - this helps integrate dmenu with other UI elements that require a particular vertical size + + - [managed](https://tools.suckless.org/dmenu/patches/managed/) + - adds a `-wm` flag which sets override_redirect to false; thus letting your window manager + manage the dmenu window + - this may be helpful in contexts where you don't want to exclusively bind dmenu or want to + treat dmenu more as a "window" rather than as an overlay + + - [morecolor](https://tools.suckless.org/dmenu/patches/morecolor/) + - adds an additional color scheme for highlighting entries adjacent to the current selection + + - [mouse-support](https://tools.suckless.org/dmenu/patches/mouse-support/) + - adds basic mouse support for dmenu + + - [multi-selection](https://tools.suckless.org/dmenu/patches/multi-selection/) + - without this patch when you press `Ctrl+Enter` dmenu just outputs current item and it is + not possible to undo that + - with this patch dmenu will output all selected items only on exit + - it is also possible to deselect any selected item + + - [navhistory](https://tools.suckless.org/dmenu/patches/navhistory/) + - provides dmenu the ability for history navigation similar to that of bash + + - [no-sort](https://tools.suckless.org/dmenu/patches/no-sort/) + - adds the `-S` option to disable sorting menu items after matching + - useful, for example, when menu items are sorted by their frequency of use (using an + external cache) and the most frequently selected items should always appear first regardless + of how they were exact, prefix, or substring matches + + - [non-blocking-stdin](https://tools.suckless.org/dmenu/patches/non_blocking_stdin/) + - this is a patch to have dmenu read stdin in a non blocking way, making it wait for input + both from stdin and from X + - this means that you can continue feeding dmenu while you type + - the patch is meant to be used along with the incremental patch in order to use stdout to + feed stdin + + - [numbers](https://tools.suckless.org/dmenu/patches/numbers/) + - adds text which displays the number of matched and total items in the top right corner of + dmenu + + - [pango](https://github.com/StillANixRookie/dmenu-pango/) + - adds simple markup for dmenu using pango markup + + - [password](https://tools.suckless.org/dmenu/patches/password/) + - with this patch dmenu will not directly display the keyboard input, but instead replace it + with dots + - all data from stdin will be ignored + + - [pipeout](https://tools.suckless.org/dmenu/patches/pipeout/) + - this patch allows the selected text to be piped back out with dmenu + - this can be useful if you want to display the output of a command on the screen + + - [plain-prompt](https://tools.suckless.org/dmenu/patches/listfullwidth/) + - simple change that avoids colors for the prompt by making it use the same style as the + rest of the input field + + - [prefix-completion](https://tools.suckless.org/dmenu/patches/prefix-completion/) + - changes the behaviour of matched items and the Tab key to allow tab completion + + - [preselect](https://tools.suckless.org/dmenu/patches/preselect/) + - adds an option `-ps` to preselect an item by providing the index that should be pre-selected + + - [printindex](https://tools.suckless.org/dmenu/patches/printindex/) + - allows dmenu to print out the 0-based index of matched text instead of the matched text + itself + - this can be useful in cases where you would like to select entries from one array of text + but index into another, or when you are selecting from an ordered list of non-unique items + + - [printinputtext](https://tools.suckless.org/dmenu/patches/printinputtext/) + - this patch adds a flag `-t` which makes Return key ignore selection and print the input + text to stdout + - the flag basically swaps the functions of Return and Shift+Return hotkeys + + - [rejectnomatch](https://tools.suckless.org/dmenu/patches/reject-no-match/) + - adds a new flag to dmenu with which text input will be rejected if it would result in no + matching item + + - relative_input_width + - prior to commit [e1e1de7](https://git.suckless.org/dmenu/commit/e1e1de7b3b8399cba90ddca9613f837b2dbef7b9.html) + the input width was calculated based on the input options + - this feature was removed in favour of hardcoding the input width to always take up 1/3rd of + the available space + - this patch adds that feature back in with some bespoke performance optimisations at the cost + of accuracy and correctness + + - [restrict-return](https://tools.suckless.org/dmenu/patches/restrict-return/) + - adds a `-1` option which disables Shift-Return and Ctrl-Return + - this guarantees that dmenu will only output one item, and that item was read from stdin + + - [scroll](https://tools.suckless.org/dmenu/patches/scroll/) + - this patch adds support for text scrolling + - it doesn't append `...` for long input anymore as it can handle long text + + - [separator](https://tools.suckless.org/dmenu/patches/separator/) + - adds `-d` and `-D` flags which separates the input into two halves; one half to be + displayed in dmenu and the other to be printed to stdout + + - [symbols](https://tools.suckless.org/dmenu/patches/symbols/) + - allows the symbols, which are printed in dmenu to indicate that either the input is too + long or there are too many options to be shown in dmenu in one line, to be defined + + - [tsv](https://tools.suckless.org/dmenu/patches/tsv/) + - makes dmenu split input lines at first tab character and only display first part, but it + will perform matching on and output full lines as usual + - can be useful if you want to separate data and representation + + - [vertfull](https://tools.suckless.org/dmenu/patches/vertfull/) + - prevents dmenu from indenting items at the same level as the prompt length + + - [wmtype](https://github.com/Baitinq/dmenu/blob/master/patches/dmenu-wm_type.diff) + - adds extended window manager hints such as \_NET_WM_WINDOW_TYPE and \_NET_WM_WINDOW_TYPE_DOCK + + - [xresources](https://tools.suckless.org/dmenu/patches/xresources/) + - allows dmenu to read font and colors from Xresources + - note that with this patch the Xresources settings takes precedence over command line arguments + + - [xyw](https://tools.suckless.org/dmenu/patches/xyw/) + - adds options for specifying dmenu window position and width diff --git a/dwm/.dmenu/config.def.h b/dwm/.dmenu/config.def.h index 1edb647..84e984c 100644 --- a/dwm/.dmenu/config.def.h +++ b/dwm/.dmenu/config.def.h @@ -1,23 +1,150 @@ /* See LICENSE file for copyright and license details. */ /* Default settings; can be overriden by command line. */ -static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +#if ALPHA_PATCH +static int opacity = 1; /* -o option; if 0, then alpha is disabled */ +#endif // ALPHA_PATCH +#if FUZZYMATCH_PATCH +static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */ +#endif // FUZZYMATCH_PATCH +#if INCREMENTAL_PATCH +static int incremental = 0; /* -r option; if 1, outputs text each time a key is pressed */ +#endif // INCREMENTAL_PATCH +#if INSTANT_PATCH +static int instant = 0; /* -n option; if 1, selects matching item without the need to press enter */ +#endif // INSTANT_PATCH +#if CENTER_PATCH +static int center = 1; /* -c option; if 0, dmenu won't be centered on the screen */ +static int min_width = 500; /* minimum width when centered */ +#endif // CENTER_PATCH +#if BARPADDING_PATCH +static const int vertpad = 10; /* vertical padding of bar */ +static const int sidepad = 10; /* horizontal padding of bar */ +#endif // BARPADDING_PATCH +#if RESTRICT_RETURN_PATCH +static int restrict_return = 0; /* -1 option; if 1, disables shift-return and ctrl-return */ +#endif // RESTRICT_RETURN_PATCH /* -fn option overrides fonts[0]; default X11 font or font set */ -static const char *fonts[] = { +#if PANGO_PATCH +static char font[] = "monospace 10"; +#else +#if XRESOURCES_PATCH +static char *fonts[] = +#else +static const char *fonts[] = +#endif // XRESOURCES_PATCH +{ "monospace:size=10" }; +#endif // PANGO_PATCH +#if MANAGED_PATCH +static char *prompt = NULL; /* -p option; prompt to the left of input field */ +#else static const char *prompt = NULL; /* -p option; prompt to the left of input field */ -static const char *colors[SchemeLast][2] = { - /* fg bg */ +#endif // MANAGED_PATCH +#if DYNAMIC_OPTIONS_PATCH +static const char *dynamic = NULL; /* -dy option; dynamic command to run on input change */ +#endif // DYNAMIC_OPTIONS_PATCH +#if SYMBOLS_PATCH +static const char *symbol_1 = "<"; +static const char *symbol_2 = ">"; +#endif // SYMBOLS_PATCH + +#if ALPHA_PATCH +static const unsigned int baralpha = 0xd0; +static const unsigned int borderalpha = OPAQUE; +static const unsigned int alphas[][3] = { + /* fg bg border */ + [SchemeNorm] = { OPAQUE, baralpha, borderalpha }, + [SchemeSel] = { OPAQUE, baralpha, borderalpha }, + #if BORDER_PATCH + [SchemeBorder] = { OPAQUE, OPAQUE, OPAQUE }, + #endif // BORDER_PATCH + #if MORECOLOR_PATCH + [SchemeMid] = { OPAQUE, baralpha, borderalpha }, + #endif // MORECOLOR_PATCH + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + [SchemeSelHighlight] = { OPAQUE, baralpha, borderalpha }, + [SchemeNormHighlight] = { OPAQUE, baralpha, borderalpha }, + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + #if HIGHPRIORITY_PATCH + [SchemeHp] = { OPAQUE, baralpha, borderalpha }, + #endif // HIGHPRIORITY_PATCH + #if EMOJI_HIGHLIGHT_PATCH + [SchemeHover] = { OPAQUE, baralpha, borderalpha }, + [SchemeGreen] = { OPAQUE, baralpha, borderalpha }, + [SchemeRed] = { OPAQUE, baralpha, borderalpha }, + [SchemeYellow] = { OPAQUE, baralpha, borderalpha }, + [SchemeBlue] = { OPAQUE, baralpha, borderalpha }, + [SchemePurple] = { OPAQUE, baralpha, borderalpha }, + #endif // EMOJI_HIGHLIGHT_PATCH +}; +#endif // ALPHA_PATCH + +static +#if !XRESOURCES_PATCH +const +#endif // XRESOURCES_PATCH +char *colors[][2] = { + /* fg bg */ [SchemeNorm] = { "#bbbbbb", "#222222" }, - [SchemeSel] = { "#eeeeee", "#005577" }, - [SchemeOut] = { "#000000", "#00ffff" }, + [SchemeSel] = { "#eeeeee", "#005577" }, + [SchemeOut] = { "#000000", "#00ffff" }, + #if BORDER_PATCH + [SchemeBorder] = { "#000000", "#005577" }, + #endif // BORDER_PATCH + #if MORECOLOR_PATCH + [SchemeMid] = { "#eeeeee", "#770000" }, + #endif // MORECOLOR_PATCH + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + [SchemeSelHighlight] = { "#ffc978", "#005577" }, + [SchemeNormHighlight] = { "#ffc978", "#222222" }, + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + #if HIGHPRIORITY_PATCH + [SchemeHp] = { "#bbbbbb", "#333333" }, + #endif // HIGHPRIORITY_PATCH + #if EMOJI_HIGHLIGHT_PATCH + [SchemeHover] = { "#ffffff", "#353D4B" }, + [SchemeGreen] = { "#ffffff", "#52E067" }, + [SchemeRed] = { "#ffffff", "#e05252" }, + [SchemeYellow] = { "#ffffff", "#e0c452" }, + [SchemeBlue] = { "#ffffff", "#5280e0" }, + [SchemePurple] = { "#ffffff", "#9952e0" }, + #endif // EMOJI_HIGHLIGHT_PATCH }; /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ static unsigned int lines = 0; +#if GRID_PATCH +/* -g option; if nonzero, dmenu uses a grid comprised of columns and lines */ +static unsigned int columns = 0; +#endif // GRID_PATCH +#if LINE_HEIGHT_PATCH +static unsigned int lineheight = 0; /* -h option; minimum height of a menu line */ +static unsigned int min_lineheight = 8; +#endif // LINE_HEIGHT_PATCH +#if NAVHISTORY_PATCH +static unsigned int maxhist = 15; +static int histnodup = 1; /* if 0, record repeated histories */ +#endif // NAVHISTORY_PATCH /* * Characters not considered part of a word while deleting words * for example: " /?\"&[]" */ +#if PIPEOUT_PATCH +static const char startpipe[] = "#"; +#endif // PIPEOUT_PATCH static const char worddelimiters[] = " "; + +#if BORDER_PATCH +/* Size of the window border */ +static unsigned int border_width = 0; +#endif // BORDER_PATCH + +#if PREFIXCOMPLETION_PATCH +/* + * Use prefix matching by default; can be inverted with the -x flag. + */ +static int use_prefix = 1; +#endif // PREFIXCOMPLETION_PATCH \ No newline at end of file diff --git a/dwm/.dmenu/config.mk b/dwm/.dmenu/config.mk index 566348b..29b96ca 100644 --- a/dwm/.dmenu/config.mk +++ b/dwm/.dmenu/config.mk @@ -19,12 +19,22 @@ FREETYPEINC = /usr/include/freetype2 #FREETYPEINC = $(X11INC)/freetype2 #MANPREFIX = ${PREFIX}/man +# uncomment on RHEL for strcasecmp +#EXTRAFLAGS=-D_GNU_SOURCE + +# Uncomment this for the alpha patch / ALPHA_PATCH +XRENDER = -lXrender + +# Uncomment for the pango patch / PANGO_PATCH +#PANGOINC = `pkg-config --cflags xft pango pangoxft` +#PANGOLIB = `pkg-config --libs xft pango pangoxft` + # includes and libs -INCS = -I$(X11INC) -I$(FREETYPEINC) -LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) +INCS = -I$(X11INC) -I$(FREETYPEINC) ${PANGOINC} +LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm $(XRENDER) ${PANGOLIB} # flags -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) $(EXTRAFLAGS) CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) LDFLAGS = $(LIBS) diff --git a/dwm/.dmenu/dmenu.c b/dwm/.dmenu/dmenu.c index 27b7a30..d7aa2df 100644 --- a/dwm/.dmenu/dmenu.c +++ b/dwm/.dmenu/dmenu.c @@ -16,47 +16,177 @@ #endif #include +#include "patches.h" +/* Patch incompatibility overrides */ +#if MULTI_SELECTION_PATCH +#undef NON_BLOCKING_STDIN_PATCH +#undef PIPEOUT_PATCH +#undef PRINTINPUTTEXT_PATCH +#endif // MULTI_SELECTION_PATCH + #include "drw.h" #include "util.h" +#if GRIDNAV_PATCH +#include +#endif // GRIDNAV_PATCH /* macros */ #define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) #define LENGTH(X) (sizeof X / sizeof X[0]) +#if PANGO_PATCH +#define TEXTW(X) (drw_font_getwidth(drw, (X), False) + lrpad) +#define TEXTWM(X) (drw_font_getwidth(drw, (X), True) + lrpad) +#else #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) +#endif // PANGO_PATCH +#if ALPHA_PATCH +#define OPAQUE 0xffU +#define OPACITY "_NET_WM_WINDOW_OPACITY" +#endif // ALPHA_PATCH /* enums */ -enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ +enum { + SchemeNorm, + SchemeSel, + SchemeOut, + #if BORDER_PATCH + SchemeBorder, + #endif // BORDER_PATCH + #if MORECOLOR_PATCH + SchemeMid, + #endif // MORECOLOR_PATCH + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + SchemeNormHighlight, + SchemeSelHighlight, + #endif // HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + #if HIGHPRIORITY_PATCH + SchemeHp, + #endif // HIGHPRIORITY_PATCH + #if EMOJI_HIGHLIGHT_PATCH + SchemeHover, + SchemeGreen, + SchemeYellow, + SchemeBlue, + SchemePurple, + SchemeRed, + #endif // EMOJI_HIGHLIGHT_PATCH + SchemeLast, +}; /* color schemes */ struct item { char *text; + #if SEPARATOR_PATCH + char *text_output; + #elif TSV_PATCH + char *stext; + #endif // SEPARATOR_PATCH | TSV_PATCH struct item *left, *right; + #if NON_BLOCKING_STDIN_PATCH + struct item *next; + #endif // NON_BLOCKING_STDIN_PATCH + #if MULTI_SELECTION_PATCH + int id; /* for multiselect */ + #else int out; + #endif // MULTI_SELECTION_PATCH + #if HIGHPRIORITY_PATCH + int hp; + #endif // HIGHPRIORITY_PATCH + #if FUZZYMATCH_PATCH + double distance; + #endif // FUZZYMATCH_PATCH + #if PRINTINDEX_PATCH + int index; + #endif // PRINTINDEX_PATCH }; static char text[BUFSIZ] = ""; +#if PIPEOUT_PATCH +static char pipeout[8] = " | dmenu"; +#endif // PIPEOUT_PATCH static char *embed; +#if SEPARATOR_PATCH +static char separator; +static int separator_greedy; +static int separator_reverse; +#endif // SEPARATOR_PATCH static int bh, mw, mh; +#if XYW_PATCH +static int dmx = 0, dmy = 0; /* put dmenu at these x and y offsets */ +static unsigned int dmw = 0; /* make dmenu this wide */ +#endif // XYW_PATCH static int inputw = 0, promptw; +#if PASSWORD_PATCH +static int passwd = 0; +#endif // PASSWORD_PATCH static int lrpad; /* sum of left and right padding */ +#if BARPADDING_PATCH +static int vp; /* vertical padding for bar */ +static int sp; /* side padding for bar */ +#endif // BARPADDING_PATCH +#if REJECTNOMATCH_PATCH +static int reject_no_match = 0; +#endif // REJECTNOMATCH_PATCH static size_t cursor; static struct item *items = NULL; static struct item *matches, *matchend; static struct item *prev, *curr, *next, *sel; static int mon = -1, screen; +#if PRINTINDEX_PATCH +static int print_index = 0; +#endif // PRINTINDEX_PATCH +#if MANAGED_PATCH +static int managed = 0; +#endif // MANAGED_PATCH +#if MULTI_SELECTION_PATCH +static int *selid = NULL; +static unsigned int selidsize = 0; +#endif // MULTI_SELECTION_PATCH +#if NO_SORT_PATCH +static unsigned int sortmatches = 1; +#endif // NO_SORT_PATCH +#if PRINTINPUTTEXT_PATCH +static int use_text_input = 0; +#endif // PRINTINPUTTEXT_PATCH +#if PRESELECT_PATCH +static unsigned int preselected = 0; +#endif // PRESELECT_PATCH +#if EMOJI_HIGHLIGHT_PATCH +static int commented = 0; +static int animated = 0; +#endif // EMOJI_HIGHLIGHT_PATCH static Atom clip, utf8; +#if WMTYPE_PATCH +static Atom type, dock; +#endif // WMTYPE_PATCH static Display *dpy; static Window root, parentwin, win; static XIC xic; +#if ALPHA_PATCH +static int useargb = 0; +static Visual *visual; +static int depth; +static Colormap cmap; +#endif // ALPHA_PATCH + static Drw *drw; static Clr *scheme[SchemeLast]; +#include "patch/include.h" + #include "config.h" +#if CASEINSENSITIVE_PATCH +static char * cistrstr(const char *s, const char *sub); +static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp; +static char *(*fstrstr)(const char *, const char *) = cistrstr; +#else static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; static char *(*fstrstr)(const char *, const char *) = strstr; +#endif // CASEINSENSITIVE_PATCH static unsigned int textw_clamp(const char *str, unsigned int n) @@ -65,6 +195,30 @@ textw_clamp(const char *str, unsigned int n) return MIN(w, n); } +static void appenditem(struct item *item, struct item **list, struct item **last); +static void calcoffsets(void); +static void cleanup(void); +static char * cistrstr(const char *s, const char *sub); +static int drawitem(struct item *item, int x, int y, int w); +static void drawmenu(void); +static void grabfocus(void); +static void grabkeyboard(void); +static void match(void); +static void insert(const char *str, ssize_t n); +static size_t nextrune(int inc); +static void movewordedge(int dir); +static void keypress(XKeyEvent *ev); +static void paste(void); +#if ALPHA_PATCH +static void xinitvisual(void); +#endif // ALPHA_PATCH +static void readstdin(void); +static void run(void); +static void setup(void); +static void usage(void); + +#include "patch/include.c" + static void appenditem(struct item *item, struct item **list, struct item **last) { @@ -81,12 +235,27 @@ appenditem(struct item *item, struct item **list, struct item **last) static void calcoffsets(void) { - int i, n; + int i, n, rpad = 0; - if (lines > 0) + if (lines > 0) { + #if GRID_PATCH + if (columns) + n = lines * columns * bh; + else + n = lines * bh; + #else n = lines * bh; - else - n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); + #endif // GRID_PATCH + } else { + #if NUMBERS_PATCH + rpad = TEXTW(numbers); + #endif // NUMBERS_PATCH + #if SYMBOLS_PATCH + n = mw - (promptw + inputw + TEXTW(symbol_1) + TEXTW(symbol_2) + rpad); + #else + n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">") + rpad); + #endif // SYMBOLS_PATCH + } /* calculate which items will begin the next page and previous page */ for (i = 0, next = curr; next; next = next->right) if ((i += (lines > 0) ? bh : textw_clamp(next->text, n)) > n) @@ -107,89 +276,423 @@ cleanup(void) for (i = 0; items && items[i].text; ++i) free(items[i].text); free(items); + #if HIGHPRIORITY_PATCH + for (i = 0; i < hplength; ++i) + free(hpitems[i]); + free(hpitems); + #endif // HIGHPRIORITY_PATCH drw_free(drw); XSync(dpy, False); XCloseDisplay(dpy); + #if MULTI_SELECTION_PATCH + free(selid); + #endif // MULTI_SELECTION_PATCH } static char * -cistrstr(const char *h, const char *n) +cistrstr(const char *s, const char *sub) { - size_t i; + size_t len; - if (!n[0]) - return (char *)h; - - for (; *h; ++h) { - for (i = 0; n[i] && tolower((unsigned char)n[i]) == - tolower((unsigned char)h[i]); ++i) - ; - if (n[i] == '\0') - return (char *)h; - } + for (len = strlen(sub); *s; s++) + if (!strncasecmp(s, sub, len)) + return (char *)s; return NULL; } static int drawitem(struct item *item, int x, int y, int w) { + int r; + #if TSV_PATCH && !SEPARATOR_PATCH + char *text = item->stext; + #else + char *text = item->text; + #endif // TSV_PATCH + + #if EMOJI_HIGHLIGHT_PATCH + int iscomment = 0; + if (text[0] == '>') { + if (text[1] == '>') { + iscomment = 3; + switch (text[2]) { + case 'r': + drw_setscheme(drw, scheme[SchemeRed]); + break; + case 'g': + drw_setscheme(drw, scheme[SchemeGreen]); + break; + case 'y': + drw_setscheme(drw, scheme[SchemeYellow]); + break; + case 'b': + drw_setscheme(drw, scheme[SchemeBlue]); + break; + case 'p': + drw_setscheme(drw, scheme[SchemePurple]); + break; + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + case 'h': + drw_setscheme(drw, scheme[SchemeNormHighlight]); + break; + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + case 's': + drw_setscheme(drw, scheme[SchemeSel]); + break; + default: + iscomment = 1; + drw_setscheme(drw, scheme[SchemeNorm]); + break; + } + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + iscomment = 1; + } + } else if (text[0] == ':') { + iscomment = 2; + if (item == sel) { + switch (text[1]) { + case 'r': + drw_setscheme(drw, scheme[SchemeRed]); + break; + case 'g': + drw_setscheme(drw, scheme[SchemeGreen]); + break; + case 'y': + drw_setscheme(drw, scheme[SchemeYellow]); + break; + case 'b': + drw_setscheme(drw, scheme[SchemeBlue]); + break; + case 'p': + drw_setscheme(drw, scheme[SchemePurple]); + break; + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + case 'h': + drw_setscheme(drw, scheme[SchemeNormHighlight]); + break; + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + case 's': + drw_setscheme(drw, scheme[SchemeSel]); + break; + default: + drw_setscheme(drw, scheme[SchemeSel]); + iscomment = 0; + break; + } + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + } + } + #endif // EMOJI_HIGHLIGHT_PATCH + + #if EMOJI_HIGHLIGHT_PATCH + int temppadding = 0; + if (iscomment == 2) { + if (text[2] == ' ') { + #if PANGO_PATCH + temppadding = drw->font->h * 3; + #else + temppadding = drw->fonts->h * 3; + #endif // PANGO_PATCH + animated = 1; + char dest[1000]; + strcpy(dest, text); + dest[6] = '\0'; + drw_text(drw, x, y + , temppadding + #if LINE_HEIGHT_PATCH + , MAX(lineheight, bh) + #else + , bh + #endif // LINE_HEIGHT_PATCH + , temppadding / 2.6 + , dest + 3 + , 0 + #if PANGO_PATCH + , True + #endif // PANGO_PATCH + ); + iscomment = 6; + drw_setscheme(drw, sel == item ? scheme[SchemeHover] : scheme[SchemeNorm]); + } + } + + char *output; + if (commented) { + static char onestr[2]; + onestr[0] = text[0]; + onestr[1] = '\0'; + output = onestr; + } else { + output = text; + } + #endif // EMOJI_HIGHLIGHT_PATCH + if (item == sel) drw_setscheme(drw, scheme[SchemeSel]); + #if HIGHPRIORITY_PATCH + else if (item->hp) + drw_setscheme(drw, scheme[SchemeHp]); + #endif // HIGHPRIORITY_PATCH + #if MORECOLOR_PATCH + else if (item->left == sel || item->right == sel) + drw_setscheme(drw, scheme[SchemeMid]); + #endif // MORECOLOR_PATCH + #if MULTI_SELECTION_PATCH + else if (issel(item->id)) + #else else if (item->out) + #endif // MULTI_SELECTION_PATCH drw_setscheme(drw, scheme[SchemeOut]); else drw_setscheme(drw, scheme[SchemeNorm]); - return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); + r = drw_text(drw + #if EMOJI_HIGHLIGHT_PATCH + , x + ((iscomment == 6) ? temppadding : 0) + #else + , x + #endif // EMOJI_HIGHLIGHT_PATCH + , y + , w + , bh + #if EMOJI_HIGHLIGHT_PATCH + , commented ? (bh - TEXTW(output) - lrpad) / 2 : lrpad / 2 + #else + , lrpad / 2 + #endif // EMOJI_HIGHLIGHT_PATCH + #if EMOJI_HIGHLIGHT_PATCH + , output + iscomment + #else + , text + #endif // EMOJI_HIGHLIGHT_PATCH + , 0 + #if PANGO_PATCH + , True + #endif // PANGO_PATCH + ); + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + #if EMOJI_HIGHLIGHT_PATCH + drawhighlights(item, output + iscomment, x + ((iscomment == 6) ? temppadding : 0), y, w); + #else + drawhighlights(item, x, y, w); + #endif // EMOJI_HIGHLIGHT_PATCH + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + return r; } static void drawmenu(void) { + #if SCROLL_PATCH + static int curpos, oldcurlen; + int curlen, rcurlen; + #else unsigned int curpos; + #endif // SCROLL_PATCH struct item *item; - int x = 0, y = 0, w; + int x = 0, y = 0, w, rpad = 0, itw = 0, stw = 0; + #if LINE_HEIGHT_PATCH && PANGO_PATCH + int fh = drw->font->h; + #elif LINE_HEIGHT_PATCH + int fh = drw->fonts->h; + #endif // LINE_HEIGHT_PATCH + #if PASSWORD_PATCH + char *censort; + #endif // PASSWORD_PATCH drw_setscheme(drw, scheme[SchemeNorm]); drw_rect(drw, 0, 0, mw, mh, 1, 1); if (prompt && *prompt) { + #if !PLAIN_PROMPT_PATCH drw_setscheme(drw, scheme[SchemeSel]); - x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0); + #endif // PLAIN_PROMPT_PATCH + x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0 + #if PANGO_PATCH + , True + #endif // PANGO_PATCH + ); } /* draw input field */ w = (lines > 0 || !matches) ? mw - x : inputw; + + #if SCROLL_PATCH + w -= lrpad / 2; + x += lrpad / 2; + rcurlen = TEXTW(text + cursor) - lrpad; + curlen = TEXTW(text) - lrpad - rcurlen; + curpos += curlen - oldcurlen; + curpos = MIN(w, MAX(0, curpos)); + curpos = MAX(curpos, w - rcurlen); + curpos = MIN(curpos, curlen); + oldcurlen = curlen; + drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); + #if PASSWORD_PATCH + if (passwd) { + censort = ecalloc(1, sizeof(text)); + memset(censort, '.', strlen(text)); + drw_text_align(drw, x, 0, curpos, bh, censort, cursor, AlignR); + drw_text_align(drw, x + curpos, 0, w - curpos, bh, censort + cursor, strlen(censort) - cursor, AlignL); + free(censort); + } else { + drw_text_align(drw, x, 0, curpos, bh, text, cursor, AlignR); + drw_text_align(drw, x + curpos, 0, w - curpos, bh, text + cursor, strlen(text) - cursor, AlignL); + } + #else + drw_text_align(drw, x, 0, curpos, bh, text, cursor, AlignR); + drw_text_align(drw, x + curpos, 0, w - curpos, bh, text + cursor, strlen(text) - cursor, AlignL); + #endif // PASSWORD_PATCH + #if LINE_HEIGHT_PATCH + drw_rect(drw, x + curpos - 1, 2 + (bh-fh)/2, 2, fh - 4, 1, 0); + #else + drw_rect(drw, x + curpos - 1, 2, 2, bh - 4, 1, 0); + #endif // LINE_HEIGHT_PATCH + #else // !SCROLL_PATCH + drw_setscheme(drw, scheme[SchemeNorm]); + #if PASSWORD_PATCH + if (passwd) { + censort = ecalloc(1, sizeof(text)); + memset(censort, '.', strlen(text)); + drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0 + #if PANGO_PATCH + , False + #endif // PANGO_PATCH + ); + drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0 + #if PANGO_PATCH + , False + #endif // PANGO_PATCH + ); + free(censort); + } else { + drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0 + #if PANGO_PATCH + , False + #endif // PANGO_PATCH + ); + } + #else + drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0 + #if PANGO_PATCH + , False + #endif // PANGO_PATCH + ); + #endif // PASSWORD_PATCH curpos = TEXTW(text) - TEXTW(&text[cursor]); if ((curpos += lrpad / 2 - 1) < w) { drw_setscheme(drw, scheme[SchemeNorm]); + #if LINE_HEIGHT_PATCH + drw_rect(drw, x + curpos, 2 + (bh-fh)/2, 2, fh - 4, 1, 0); + #else drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); + #endif // LINE_HEIGHT_PATCH } + #endif // SCROLL_PATCH + #if NUMBERS_PATCH + recalculatenumbers(); + rpad = TEXTW(numbers); + #if BARPADDING_PATCH + rpad += 2 * sp; + #endif // BARPADDING_PATCH + #if BORDER_PATCH + rpad += border_width; + #endif // BORDER_PATCH + #endif // NUMBERS_PATCH if (lines > 0) { + #if GRID_PATCH + /* draw grid */ + int i = 0; + for (item = curr; item != next; item = item->right, i++) + if (columns) + #if VERTFULL_PATCH + drawitem( + item, + 0 + ((i / lines) * (mw / columns)), + y + (((i % lines) + 1) * bh), + mw / columns + ); + #else + drawitem( + item, + x + ((i / lines) * ((mw - x) / columns)), + y + (((i % lines) + 1) * bh), + (mw - x) / columns + ); + #endif // VERTFULL_PATCH + else + #if VERTFULL_PATCH + drawitem(item, 0, y += bh, mw); + #else + drawitem(item, x, y += bh, mw - x); + #endif // VERTFULL_PATCH + #else /* draw vertical list */ for (item = curr; item != next; item = item->right) + #if VERTFULL_PATCH + drawitem(item, 0, y += bh, mw); + #else drawitem(item, x, y += bh, mw - x); + #endif // VERTFULL_PATCH + #endif // GRID_PATCH } else if (matches) { /* draw horizontal list */ x += inputw; w = TEXTW("<"); if (curr->left) { drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0); + drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0 + #if PANGO_PATCH + , True + #endif // PANGO_PATCH + ); } x += w; - for (item = curr; item != next; item = item->right) - x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">"))); + for (item = curr; item != next; item = item->right) { + #if SYMBOLS_PATCH + stw = TEXTW(symbol_2); + #else + stw = TEXTW(">"); + #endif // SYMBOLS_PATCH + #if TSV_PATCH && !SEPARATOR_PATCH + itw = textw_clamp(item->stext, mw - x - stw - rpad); + #else + itw = textw_clamp(item->text, mw - x - stw - rpad); + #endif // TSV_PATCH + x = drawitem(item, x, 0, itw); + } if (next) { + #if SYMBOLS_PATCH + w = TEXTW(symbol_2); + #else w = TEXTW(">"); + #endif // SYMBOLS_PATCH drw_setscheme(drw, scheme[SchemeNorm]); - drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0); + drw_text(drw, mw - w - rpad, 0, w, bh, lrpad / 2 + #if SYMBOLS_PATCH + , symbol_2 + #else + , ">" + #endif // SYMBOLS_PATCH + , 0 + #if PANGO_PATCH + , True + #endif // PANGO_PATCH + ); } } + #if NUMBERS_PATCH + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, mw - rpad, 0, TEXTW(numbers), bh, lrpad / 2, numbers, 0); + #endif // NUMBERS_PATCH drw_map(drw, win, 0, 0, mw, mh); + #if NON_BLOCKING_STDIN_PATCH + XFlush(dpy); + #endif // NON_BLOCKING_STDIN_PATCH } static void @@ -203,7 +706,9 @@ grabfocus(void) XGetInputFocus(dpy, &focuswin, &revertwin); if (focuswin == win) return; + #if !MANAGED_PATCH XSetInputFocus(dpy, win, RevertToParent, CurrentTime); + #endif // MANAGED_PATCH nanosleep(&ts, NULL); } die("cannot grab focus"); @@ -215,7 +720,11 @@ grabkeyboard(void) struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; int i; + #if MANAGED_PATCH + if (embed || managed) + #else if (embed) + #endif // MANAGED_PATCH return; /* try to grab keyboard, we may have to wait for another process to ungrab */ for (i = 0; i < 1000; i++) { @@ -230,6 +739,17 @@ grabkeyboard(void) static void match(void) { + #if DYNAMIC_OPTIONS_PATCH + if (dynamic && *dynamic) + refreshoptions(); + #endif // DYNAMIC_OPTIONS_PATCH + + #if FUZZYMATCH_PATCH + if (fuzzy) { + fuzzymatch(); + return; + } + #endif static char **tokv = NULL; static int tokn = 0; @@ -237,6 +757,12 @@ match(void) int i, tokc = 0; size_t len, textsize; struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; + #if HIGHPRIORITY_PATCH + struct item *lhpprefix, *hpprefixend; + #endif // HIGHPRIORITY_PATCH + #if NON_BLOCKING_STDIN_PATCH + int preserve = 0; + #endif // NON_BLOCKING_STDIN_PATCH strcpy(buf, text); /* separate input text into tokens to be matched individually */ @@ -245,22 +771,78 @@ match(void) die("cannot realloc %zu bytes:", tokn * sizeof *tokv); len = tokc ? strlen(tokv[0]) : 0; + #if PREFIXCOMPLETION_PATCH + if (use_prefix) { + matches = lprefix = matchend = prefixend = NULL; + textsize = strlen(text); + } else { + matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; + textsize = strlen(text) + 1; + } + #else matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; textsize = strlen(text) + 1; - for (item = items; item && item->text; item++) { + #endif // PREFIXCOMPLETION_PATCH + #if HIGHPRIORITY_PATCH + lhpprefix = hpprefixend = NULL; + #endif // HIGHPRIORITY_PATCH + #if NON_BLOCKING_STDIN_PATCH && DYNAMIC_OPTIONS_PATCH + for (item = items; item && (!(dynamic && *dynamic) || item->text); item = (dynamic && *dynamic) ? item + 1 : item->next) + #elif NON_BLOCKING_STDIN_PATCH + for (item = items; item; item = item->next) + #else + for (item = items; item && item->text; item++) + #endif + { for (i = 0; i < tokc; i++) if (!fstrstr(item->text, tokv[i])) break; + #if DYNAMIC_OPTIONS_PATCH + if (i != tokc && !(dynamic && *dynamic)) /* not all tokens match */ + continue; + #else if (i != tokc) /* not all tokens match */ continue; + #endif // DYNAMIC_OPTIONS_PATCH + #if HIGHPRIORITY_PATCH + /* exact matches go first, then prefixes with high priority, then prefixes, then substrings */ + #else /* exact matches go first, then prefixes, then substrings */ + #endif // HIGHPRIORITY_PATCH + #if NO_SORT_PATCH + if (!sortmatches) + appenditem(item, &matches, &matchend); + else + #endif // NO_SORT_PATCH if (!tokc || !fstrncmp(text, item->text, textsize)) appenditem(item, &matches, &matchend); + #if HIGHPRIORITY_PATCH + else if (item->hp && !fstrncmp(tokv[0], item->text, len)) + appenditem(item, &lhpprefix, &hpprefixend); + #endif // HIGHPRIORITY_PATCH else if (!fstrncmp(tokv[0], item->text, len)) appenditem(item, &lprefix, &prefixend); + #if PREFIXCOMPLETION_PATCH + else if (!use_prefix) + #else else + #endif // PREFIXCOMPLETION_PATCH appenditem(item, &lsubstr, &substrend); + #if NON_BLOCKING_STDIN_PATCH + if (sel == item) + preserve = 1; + #endif // NON_BLOCKING_STDIN_PATCH } + #if HIGHPRIORITY_PATCH + if (lhpprefix) { + if (matches) { + matchend->right = lhpprefix; + lhpprefix->left = matchend; + } else + matches = lhpprefix; + matchend = hpprefixend; + } + #endif // HIGHPRIORITY_PATCH if (lprefix) { if (matches) { matchend->right = lprefix; @@ -269,7 +851,12 @@ match(void) matches = lprefix; matchend = prefixend; } - if (lsubstr) { + #if PREFIXCOMPLETION_PATCH + if (!use_prefix && lsubstr) + #else + if (lsubstr) + #endif // PREFIXCOMPLETION_PATCH + { if (matches) { matchend->right = lsubstr; lsubstr->left = matchend; @@ -277,7 +864,19 @@ match(void) matches = lsubstr; matchend = substrend; } + #if NON_BLOCKING_STDIN_PATCH + if (!preserve) + #endif // NON_BLOCKING_STDIN_PATCH curr = sel = matches; + + #if INSTANT_PATCH + if (instant && matches && matches==matchend && !lsubstr) { + puts(matches->text); + cleanup(); + exit(0); + } + #endif // INSTANT_PATCH + calcoffsets(); } @@ -286,12 +885,30 @@ insert(const char *str, ssize_t n) { if (strlen(text) + n > sizeof text - 1) return; + + #if REJECTNOMATCH_PATCH + static char last[BUFSIZ] = ""; + if (reject_no_match) { + /* store last text value in case we need to revert it */ + memcpy(last, text, BUFSIZ); + } + #endif // REJECTNOMATCH_PATCH + /* move existing text out of the way, insert new text, and update cursor */ memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); if (n > 0) memcpy(&text[cursor], str, n); cursor += n; match(); + + #if REJECTNOMATCH_PATCH + if (!matches && reject_no_match) { + /* revert to last text value if theres no match */ + memcpy(text, last, BUFSIZ); + cursor -= n; + match(); + } + #endif // REJECTNOMATCH_PATCH } static size_t @@ -326,8 +943,16 @@ keypress(XKeyEvent *ev) { char buf[64]; int len; + #if PREFIXCOMPLETION_PATCH + struct item * item; + #endif // PREFIXCOMPLETION_PATCH KeySym ksym = NoSymbol; Status status; + #if GRID_PATCH && GRIDNAV_PATCH + int i; + struct item *tmpsel; + bool offscreen = false; + #endif // GRIDNAV_PATCH len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); switch (status) { @@ -342,6 +967,30 @@ keypress(XKeyEvent *ev) if (ev->state & ControlMask) { switch(ksym) { + #if FZFEXPECT_PATCH + case XK_a: expect("ctrl-a", ev); ksym = XK_Home; break; + case XK_b: expect("ctrl-b", ev); ksym = XK_Left; break; + case XK_c: expect("ctrl-c", ev); ksym = XK_Escape; break; + case XK_d: expect("ctrl-d", ev); ksym = XK_Delete; break; + case XK_e: expect("ctrl-e", ev); ksym = XK_End; break; + case XK_f: expect("ctrl-f", ev); ksym = XK_Right; break; + case XK_g: expect("ctrl-g", ev); ksym = XK_Escape; break; + case XK_h: expect("ctrl-h", ev); ksym = XK_BackSpace; break; + case XK_i: expect("ctrl-i", ev); ksym = XK_Tab; break; + case XK_j: expect("ctrl-j", ev); ksym = XK_Down; break; + case XK_J:/* fallthrough */ + case XK_l: expect("ctrl-l", ev); break; + case XK_m: expect("ctrl-m", ev); /* fallthrough */ + case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break; + case XK_n: expect("ctrl-n", ev); ksym = XK_Down; break; + case XK_p: expect("ctrl-p", ev); ksym = XK_Up; break; + case XK_o: expect("ctrl-o", ev); break; + case XK_q: expect("ctrl-q", ev); break; + case XK_r: expect("ctrl-r", ev); break; + case XK_s: expect("ctrl-s", ev); break; + case XK_t: expect("ctrl-t", ev); break; + case XK_k: expect("ctrl-k", ev); ksym = XK_Up; break; + #else case XK_a: ksym = XK_Home; break; case XK_b: ksym = XK_Left; break; case XK_c: ksym = XK_Escape; break; @@ -362,20 +1011,47 @@ keypress(XKeyEvent *ev) text[cursor] = '\0'; match(); break; + #endif // FZFEXPECT_PATCH + #if FZFEXPECT_PATCH + case XK_u: expect("ctrl-u", ev); /* delete left */ + #else case XK_u: /* delete left */ + #endif // FZFEXPECT_PATCH insert(NULL, 0 - cursor); break; + #if FZFEXPECT_PATCH + case XK_w: expect("ctrl-w", ev); /* delete word */ + #else case XK_w: /* delete word */ + #endif // FZFEXPECT_PATCH while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) insert(NULL, nextrune(-1) - cursor); while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) insert(NULL, nextrune(-1) - cursor); break; + #if FZFEXPECT_PATCH || CTRL_V_TO_PASTE_PATCH + case XK_v: + #if FZFEXPECT_PATCH + expect("ctrl-v", ev); + #endif // FZFEXPECT_PATCH + case XK_V: + XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + return; + #endif // FZFEXPECT_PATCH | CTRL_V_TO_PASTE_PATCH + #if FZFEXPECT_PATCH + case XK_y: expect("ctrl-y", ev); /* paste selection */ + #else case XK_y: /* paste selection */ + #endif // FZFEXPECT_PATCH case XK_Y: XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, utf8, utf8, win, CurrentTime); return; + #if FZFEXPECT_PATCH + case XK_x: expect("ctrl-x", ev); break; + case XK_z: expect("ctrl-z", ev); break; + #endif // FZFEXPECT_PATCH case XK_Left: case XK_KP_Left: movewordedge(-1); @@ -386,6 +1062,13 @@ keypress(XKeyEvent *ev) goto draw; case XK_Return: case XK_KP_Enter: + #if RESTRICT_RETURN_PATCH + if (restrict_return) + break; + #endif // RESTRICT_RETURN_PATCH + #if MULTI_SELECTION_PATCH + selsel(); + #endif // MULTI_SELECTION_PATCH break; case XK_bracketleft: cleanup(); @@ -407,6 +1090,16 @@ keypress(XKeyEvent *ev) case XK_j: ksym = XK_Next; break; case XK_k: ksym = XK_Prior; break; case XK_l: ksym = XK_Down; break; + #if NAVHISTORY_PATCH + case XK_p: + navhistory(-1); + buf[0]=0; + break; + case XK_n: + navhistory(1); + buf[0]=0; + break; + #endif // NAVHISTORY_PATCH default: return; } @@ -460,6 +1153,26 @@ insert: break; case XK_Left: case XK_KP_Left: + #if GRID_PATCH && GRIDNAV_PATCH + if (columns > 1) { + if (!sel) + return; + tmpsel = sel; + for (i = 0; i < lines; i++) { + if (!tmpsel->left || tmpsel->left->right != tmpsel) + return; + if (tmpsel == curr) + offscreen = true; + tmpsel = tmpsel->left; + } + sel = tmpsel; + if (offscreen) { + curr = prev; + calcoffsets(); + } + break; + } + #endif // GRIDNAV_PATCH if (cursor > 0 && (!sel || !sel->left || lines > 0)) { cursor = nextrune(-1); break; @@ -490,16 +1203,104 @@ insert: break; case XK_Return: case XK_KP_Enter: + #if RESTRICT_RETURN_PATCH + if (restrict_return && (!sel || ev->state & (ShiftMask | ControlMask))) + break; + #endif // RESTRICT_RETURN_PATCH + #if !MULTI_SELECTION_PATCH + #if PIPEOUT_PATCH + #if PRINTINPUTTEXT_PATCH + if (sel && ( + (use_text_input && (ev->state & ShiftMask)) || + (!use_text_input && !(ev->state & ShiftMask)) + )) + #else + if (sel && !(ev->state & ShiftMask)) + #endif // PRINTINPUTTEXT_PATCH + { + if (sel->text[0] == startpipe[0]) { + strncpy(sel->text + strlen(sel->text),pipeout,8); + puts(sel->text+1); + } + #if PRINTINDEX_PATCH + if (print_index) + printf("%d\n", sel->index); + else + #endif // PRINTINDEX_PATCH + puts(sel->text); + } else { + if (text[0] == startpipe[0]) { + strncpy(text + strlen(text),pipeout,8); + puts(text+1); + } + puts(text); + } + #elif PRINTINPUTTEXT_PATCH + if (use_text_input) + puts((sel && (ev->state & ShiftMask)) ? sel->text : text); + #if PRINTINDEX_PATCH + else if (print_index) + printf("%d\n", (sel && !(ev->state & ShiftMask)) ? sel->index : -1); + #endif // PRINTINDEX_PATCH + else + #if SEPARATOR_PATCH + puts((sel && !(ev->state & ShiftMask)) ? sel->text_output : text); + #else + puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); + #endif // SEPARATOR_PATCH + #elif PRINTINDEX_PATCH + if (print_index) + printf("%d\n", (sel && !(ev->state & ShiftMask)) ? sel->index : -1); + else + #if SEPARATOR_PATCH + puts((sel && !(ev->state & ShiftMask)) ? sel->text_output : text); + #else + puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); + #endif // SEPARATOR_PATCH + #elif SEPARATOR_PATCH + puts((sel && !(ev->state & ShiftMask)) ? sel->text_output : text); + #else puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); + #endif // PIPEOUT_PATCH | PRINTINPUTTEXT_PATCH | PRINTINDEX_PATCH + #endif // MULTI_SELECTION_PATCH if (!(ev->state & ControlMask)) { + #if NAVHISTORY_PATCH + savehistory((sel && !(ev->state & ShiftMask)) + ? sel->text : text); + #endif // NAVHISTORY_PATCH + #if MULTI_SELECTION_PATCH + printsel(ev->state); + #endif // MULTI_SELECTION_PATCH cleanup(); exit(0); } + #if !MULTI_SELECTION_PATCH if (sel) sel->out = 1; + #endif // MULTI_SELECTION_PATCH break; case XK_Right: case XK_KP_Right: + #if GRID_PATCH && GRIDNAV_PATCH + if (columns > 1) { + if (!sel) + return; + tmpsel = sel; + for (i = 0; i < lines; i++) { + if (!tmpsel->right || tmpsel->right->left != tmpsel) + return; + tmpsel = tmpsel->right; + if (tmpsel == next) + offscreen = true; + } + sel = tmpsel; + if (offscreen) { + curr = next; + calcoffsets(); + } + break; + } + #endif // GRIDNAV_PATCH if (text[cursor] != '\0') { cursor = nextrune(+1); break; @@ -515,16 +1316,43 @@ insert: } break; case XK_Tab: + #if PREFIXCOMPLETION_PATCH + if (!matches) + break; /* cannot complete no matches */ + #if FUZZYMATCH_PATCH + /* only do tab completion if all matches start with prefix */ + for (item = matches; item && item->text; item = item->right) + if (item->text[0] != text[0]) + goto draw; + #endif // FUZZYMATCH_PATCH + strncpy(text, matches->text, sizeof text - 1); + text[sizeof text - 1] = '\0'; + len = cursor = strlen(text); /* length of longest common prefix */ + for (item = matches; item && item->text; item = item->right) { + cursor = 0; + while (cursor < len && text[cursor] == item->text[cursor]) + cursor++; + len = cursor; + } + memset(text + len, '\0', strlen(text) - len); + #else if (!sel) return; cursor = strnlen(sel->text, sizeof text - 1); memcpy(text, sel->text, cursor); text[cursor] = '\0'; match(); + #endif // PREFIXCOMPLETION_PATCH break; } draw: + #if INCREMENTAL_PATCH + if (incremental) { + puts(text); + fflush(stdout); + } + #endif // INCREMENTAL_PATCH drawmenu(); } @@ -546,41 +1374,150 @@ paste(void) drawmenu(); } +#if ALPHA_PATCH +static void +xinitvisual() +{ + XVisualInfo *infos; + XRenderPictFormat *fmt; + int nitems; + int i; + + XVisualInfo tpl = { + .screen = screen, + .depth = 32, + .class = TrueColor + }; + long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; + + infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); + visual = NULL; + for(i = 0; i < nitems; i ++) { + fmt = XRenderFindVisualFormat(dpy, infos[i].visual); + if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { + visual = infos[i].visual; + depth = infos[i].depth; + cmap = XCreateColormap(dpy, root, visual, AllocNone); + useargb = 1; + break; + } + } + + XFree(infos); + + if (!visual || !opacity) { + visual = DefaultVisual(dpy, screen); + depth = DefaultDepth(dpy, screen); + cmap = DefaultColormap(dpy, screen); + } +} +#endif // ALPHA_PATCH + +#if !NON_BLOCKING_STDIN_PATCH static void readstdin(void) { char *line = NULL; - size_t i, junk, itemsiz = 0; + #if SEPARATOR_PATCH + char *p; + #elif TSV_PATCH + char *buf, *p; + #endif // SEPARATOR_PATCH | TSV_PATCH + + size_t size = 0; + size_t i, junk; ssize_t len; + #if PASSWORD_PATCH + if (passwd) { + inputw = lines = 0; + return; + } + #endif // PASSWORD_PATCH + /* read each line from stdin and add it to the item list */ - for (i = 0; (len = getline(&line, &junk, stdin)) != -1; i++) { - if (i + 1 >= itemsiz) { - itemsiz += 256; - if (!(items = realloc(items, itemsiz * sizeof(*items)))) - die("cannot realloc %zu bytes:", itemsiz * sizeof(*items)); - } + for (i = 0; (len = getline(&line, &junk, stdin)) != -1; i++, line = NULL) { + if (i + 1 >= size / sizeof *items) + if (!(items = realloc(items, (size += BUFSIZ)))) + die("cannot realloc %zu bytes:", size); if (line[len - 1] == '\n') line[len - 1] = '\0'; + items[i].text = line; + #if SEPARATOR_PATCH + if (separator && (p = separator_greedy ? + strrchr(items[i].text, separator) : strchr(items[i].text, separator))) { + *p = '\0'; + items[i].text_output = ++p; + } else { + items[i].text_output = items[i].text; + } + if (separator_reverse) { + p = items[i].text; + items[i].text = items[i].text_output; + items[i].text_output = p; + } + #elif TSV_PATCH + if (!(buf = strdup(line))) + die("cannot strdup %u bytes:", strlen(line) + 1); + if ((p = strchr(buf, '\t'))) + *p = '\0'; + items[i].stext = buf; + #endif // SEPARATOR_PATCH | TSV_PATCH + #if MULTI_SELECTION_PATCH + items[i].id = i; /* for multiselect */ + #if PRINTINDEX_PATCH + items[i].index = i; + #endif // PRINTINDEX_PATCH + #elif PRINTINDEX_PATCH + items[i].index = i; + #else items[i].out = 0; - line = NULL; /* next call of getline() allocates a new line */ + #endif // MULTI_SELECTION_PATCH | PRINTINDEX_PATCH + + #if HIGHPRIORITY_PATCH + items[i].hp = arrayhas(hpitems, hplength, items[i].text); + #endif // HIGHPRIORITY_PATCH } - free(line); if (items) items[i].text = NULL; lines = MIN(lines, i); } +#endif // NON_BLOCKING_STDIN_PATCH static void +#if NON_BLOCKING_STDIN_PATCH +readevent(void) +#else run(void) +#endif // NON_BLOCKING_STDIN_PATCH { XEvent ev; + #if PRESELECT_PATCH + int i; + #endif // PRESELECT_PATCH while (!XNextEvent(dpy, &ev)) { + #if PRESELECT_PATCH + if (preselected) { + for (i = 0; i < preselected; i++) { + if (sel && sel->right && (sel = sel->right) == next) { + curr = next; + calcoffsets(); + } + } + drawmenu(); + preselected = 0; + } + #endif // PRESELECT_PATCH if (XFilterEvent(&ev, win)) continue; switch(ev.type) { + #if MOUSE_SUPPORT_PATCH + case ButtonPress: + buttonpress(&ev); + break; + #endif // MOUSE_SUPPORT_PATCH case DestroyNotify: if (ev.xdestroywindow.window != win) break; @@ -615,6 +1552,11 @@ setup(void) { int x, y, i, j; unsigned int du; + #if RELATIVE_INPUT_WIDTH_PATCH + unsigned int tmp, minstrlen = 0, curstrlen = 0; + int numwidthchecks = 100; + struct item *item; + #endif // RELATIVE_INPUT_WIDTH_PATCH XSetWindowAttributes swa; XIM xim; Window w, dw, *dws; @@ -626,16 +1568,45 @@ setup(void) int a, di, n, area = 0; #endif /* init appearance */ + #if XRESOURCES_PATCH for (j = 0; j < SchemeLast; j++) + #if ALPHA_PATCH + scheme[j] = drw_scm_create(drw, (const char**)colors[j], alphas[j], 2); + #else + scheme[j] = drw_scm_create(drw, (const char**)colors[j], 2); + #endif // ALPHA_PATCH + #else + for (j = 0; j < SchemeLast; j++) + #if ALPHA_PATCH + scheme[j] = drw_scm_create(drw, colors[j], alphas[j], 2); + #else scheme[j] = drw_scm_create(drw, colors[j], 2); + #endif // ALPHA_PATCH + #endif // XRESOURCES_PATCH clip = XInternAtom(dpy, "CLIPBOARD", False); utf8 = XInternAtom(dpy, "UTF8_STRING", False); + #if WMTYPE_PATCH + type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False); + #endif // WMTYPE_PATCH /* calculate menu geometry */ + #if PANGO_PATCH + bh = drw->font->h + 2; + #else bh = drw->fonts->h + 2; + #endif // PANGO_PATCH + #if LINE_HEIGHT_PATCH + bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */ + #endif // LINE_HEIGHT_PATCH lines = MAX(lines, 0); mh = (lines + 1) * bh; + #if CENTER_PATCH && PANGO_PATCH + promptw = (prompt && *prompt) ? TEXTWM(prompt) - lrpad / 4 : 0; + #elif CENTER_PATCH + promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; + #endif // CENTER_PATCH #ifdef XINERAMA i = 0; if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { @@ -662,9 +1633,31 @@ setup(void) if (INTERSECT(x, y, 1, 1, info[i]) != 0) break; + #if CENTER_PATCH + if (center) { + mw = MIN(MAX(max_textw() + promptw, min_width), info[i].width); + x = info[i].x_org + ((info[i].width - mw) / 2); + y = info[i].y_org + ((info[i].height - mh) / 2); + } else { + #if XYW_PATCH + x = info[i].x_org + dmx; + y = info[i].y_org + (topbar ? dmy : info[i].height - mh - dmy); + mw = (dmw>0 ? dmw : info[i].width); + #else + x = info[i].x_org; + y = info[i].y_org + (topbar ? 0 : info[i].height - mh); + mw = info[i].width; + #endif // XYW_PATCH + } + #elif XYW_PATCH + x = info[i].x_org + dmx; + y = info[i].y_org + (topbar ? dmy : info[i].height - mh - dmy); + mw = (dmw>0 ? dmw : info[i].width); + #else x = info[i].x_org; y = info[i].y_org + (topbar ? 0 : info[i].height - mh); mw = info[i].width; + #endif // CENTER_PATCH / XYW_PATCH XFree(info); } else #endif @@ -672,22 +1665,102 @@ setup(void) if (!XGetWindowAttributes(dpy, parentwin, &wa)) die("could not get embedding window attributes: 0x%lx", parentwin); + #if CENTER_PATCH + if (center) { + mw = MIN(MAX(max_textw() + promptw, min_width), wa.width); + x = (wa.width - mw) / 2; + y = (wa.height - mh) / 2; + } else { + #if XYW_PATCH + x = dmx; + y = topbar ? dmy : wa.height - mh - dmy; + mw = (dmw>0 ? dmw : wa.width); + #else + x = 0; + y = topbar ? 0 : wa.height - mh; + mw = wa.width; + #endif // XYW_PATCH + } + #elif XYW_PATCH + x = dmx; + y = topbar ? dmy : wa.height - mh - dmy; + mw = (dmw>0 ? dmw : wa.width); + #else x = 0; y = topbar ? 0 : wa.height - mh; mw = wa.width; + #endif // CENTER_PATCH / XYW_PATCH } + #if !CENTER_PATCH + #if PANGO_PATCH + promptw = (prompt && *prompt) ? TEXTWM(prompt) - lrpad / 4 : 0; + #else promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - inputw = mw / 3; /* input width: ~33% of monitor width */ + #endif // PANGO_PATCH + #endif // CENTER_PATCH + #if RELATIVE_INPUT_WIDTH_PATCH + for (item = items; !lines && item && item->text; ++item) { + curstrlen = strlen(item->text); + if (numwidthchecks || minstrlen < curstrlen) { + numwidthchecks = MAX(numwidthchecks - 1, 0); + minstrlen = MAX(minstrlen, curstrlen); + if ((tmp = textw_clamp(item->text, mw/3)) > inputw) { + inputw = tmp; + if (tmp == mw/3) + break; + } + } + } + #else + inputw = mw / 3; /* input width: ~33.33% of monitor width */ + #endif // RELATIVE_INPUT_WIDTH_PATCH match(); /* create menu window */ + #if MANAGED_PATCH + swa.override_redirect = managed ? False : True; + #else swa.override_redirect = True; + #endif // MANAGED_PATCH + #if ALPHA_PATCH + swa.background_pixel = 0; + swa.colormap = cmap; + #else swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; - win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); + #endif // ALPHA_PATCH + swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask + #if MOUSE_SUPPORT_PATCH + | ButtonPressMask + #endif // MOUSE_SUPPORT_PATCH + ; + win = XCreateWindow( + dpy, parentwin, + #if BARPADDING_PATCH && BORDER_PATCH + x + sp, y + vp - (topbar ? 0 : border_width * 2), mw - 2 * sp - border_width * 2, mh, border_width, + #elif BARPADDING_PATCH + x + sp, y + vp, mw - 2 * sp, mh, 0, + #elif BORDER_PATCH + x, y - (topbar ? 0 : border_width * 2), mw - border_width * 2, mh, border_width, + #else + x, y, mw, mh, 0, + #endif // BORDER_PATCH | BARPADDING_PATCH + #if ALPHA_PATCH + depth, InputOutput, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &swa + #else + CopyFromParent, CopyFromParent, CopyFromParent, + CWOverrideRedirect | CWBackPixel | CWEventMask, &swa + #endif // ALPHA_PATCH + ); + #if BORDER_PATCH + if (border_width) + XSetWindowBorder(dpy, win, scheme[SchemeBorder][ColBg].pixel); + #endif // BORDER_PATCH XSetClassHint(dpy, win, &ch); + #if WMTYPE_PATCH + XChangeProperty(dpy, win, type, XA_ATOM, 32, PropModeReplace, + (unsigned char *) &dock, 1); + #endif // WMTYPE_PATCH /* input methods */ @@ -697,6 +1770,17 @@ setup(void) xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win, XNFocusWindow, win, NULL); + #if MANAGED_PATCH + if (managed) { + XTextProperty prop; + char *windowtitle = prompt != NULL ? prompt : "dmenu"; + Xutf8TextListToTextProperty(dpy, &windowtitle, 1, XUTF8StringStyle, &prop); + XSetWMName(dpy, win, &prop); + XSetTextProperty(dpy, win, &prop, XInternAtom(dpy, "_NET_WM_NAME", False)); + XFree(prop.value); + } + #endif // MANAGED_PATCH + XMapRaised(dpy, win); if (embed) { XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask); @@ -714,52 +1798,109 @@ setup(void) static void usage(void) { - die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]"); + die("usage: dmenu [-bv" + #if CENTER_PATCH + "c" + #endif + #if !NON_BLOCKING_STDIN_PATCH + "f" + #endif // NON_BLOCKING_STDIN_PATCH + #if INCREMENTAL_PATCH + "r" + #endif // INCREMENTAL_PATCH + #if CASEINSENSITIVE_PATCH + "s" + #else + "i" + #endif // CASEINSENSITIVE_PATCH + #if INSTANT_PATCH + "n" + #endif // INSTANT_PATCH + #if PRINTINPUTTEXT_PATCH + "t" + #endif // PRINTINPUTTEXT_PATCH + #if PREFIXCOMPLETION_PATCH + "x" + #endif // PREFIXCOMPLETION_PATCH + #if FUZZYMATCH_PATCH + "F" + #endif // FUZZYMATCH_PATCH + #if PASSWORD_PATCH + "P" + #endif // PASSWORD_PATCH + #if NO_SORT_PATCH + "S" + #endif // NO_SORT_PATCH + #if REJECTNOMATCH_PATCH + "R" // (changed from r to R due to conflict with INCREMENTAL_PATCH) + #endif // REJECTNOMATCH_PATCH + #if RESTRICT_RETURN_PATCH + "1" + #endif // RESTRICT_RETURN_PATCH + "] " + #if MANAGED_PATCH + "[-wm] " + #endif // MANAGED_PATCH + #if GRID_PATCH + "[-g columns] " + #endif // GRID_PATCH + "[-l lines] [-p prompt] [-fn font] [-m monitor]" + "\n [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]" + #if DYNAMIC_OPTIONS_PATCH || FZFEXPECT_PATCH || ALPHA_PATCH || BORDER_PATCH || HIGHPRIORITY_PATCH + "\n " + #endif + #if DYNAMIC_OPTIONS_PATCH + " [-dy command]" + #endif // DYNAMIC_OPTIONS_PATCH + #if FZFEXPECT_PATCH + " [-ex expectkey]" + #endif // FZFEXPECT_PATCH + #if ALPHA_PATCH + " [-o opacity]" + #endif // ALPHA_PATCH + #if BORDER_PATCH + " [-bw width]" + #endif // BORDER_PATCH + #if HIGHPRIORITY_PATCH + " [-hb color] [-hf color] [-hp items]" + #endif // HIGHPRIORITY_PATCH + #if INITIALTEXT_PATCH || LINE_HEIGHT_PATCH || PRESELECT_PATCH || NAVHISTORY_PATCH || XYW_PATCH + "\n " + #endif + #if INITIALTEXT_PATCH + " [-it text]" + #endif // INITIALTEXT_PATCH + #if LINE_HEIGHT_PATCH + " [-h height]" + #endif // LINE_HEIGHT_PATCH + #if PRESELECT_PATCH + " [-ps index]" + #endif // PRESELECT_PATCH + #if NAVHISTORY_PATCH + " [-H histfile]" + #endif // NAVHISTORY_PATCH + #if XYW_PATCH + " [-X xoffset] [-Y yoffset] [-W width]" // (arguments made upper case due to conflicts) + #endif // XYW_PATCH + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + "\n [-nhb color] [-nhf color] [-shb color] [-shf color]" // highlight colors + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + #if SEPARATOR_PATCH + "\n [-d separator] [-D separator]" + #endif // SEPARATOR_PATCH + "\n"); } int main(int argc, char *argv[]) { XWindowAttributes wa; - int i, fast = 0; - - for (i = 1; i < argc; i++) - /* these options take no arguments */ - if (!strcmp(argv[i], "-v")) { /* prints version information */ - puts("dmenu-"VERSION); - exit(0); - } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ - topbar = 0; - else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ - fast = 1; - else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ - fstrncmp = strncasecmp; - fstrstr = cistrstr; - } else if (i + 1 == argc) - usage(); - /* these options take one argument */ - else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ - lines = atoi(argv[++i]); - 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]; - else if (!strcmp(argv[i], "-fn")) /* font or font set */ - fonts[0] = argv[++i]; - else if (!strcmp(argv[i], "-nb")) /* normal background color */ - colors[SchemeNorm][ColBg] = argv[++i]; - else if (!strcmp(argv[i], "-nf")) /* normal foreground color */ - colors[SchemeNorm][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-sb")) /* selected background color */ - colors[SchemeSel][ColBg] = argv[++i]; - else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ - colors[SchemeSel][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-w")) /* embedding window id */ - embed = argv[++i]; - else - usage(); + int i; + #if !NON_BLOCKING_STDIN_PATCH + int fast = 0; + #endif // NON_BLOCKING_STDIN_PATCH + #if XRESOURCES_PATCH if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) fputs("warning: no locale support\n", stderr); if (!(dpy = XOpenDisplay(NULL))) @@ -771,23 +1912,274 @@ main(int argc, char *argv[]) if (!XGetWindowAttributes(dpy, parentwin, &wa)) die("could not get embedding window attributes: 0x%lx", parentwin); + + #if ALPHA_PATCH + xinitvisual(); + drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); + #else drw = drw_create(dpy, screen, root, wa.width, wa.height); + #endif // ALPHA_PATCH + readxresources(); + #endif // XRESOURCES_PATCH + + for (i = 1; i < argc; i++) + /* these options take no arguments */ + if (!strcmp(argv[i], "-v")) { /* prints version information */ + puts("dmenu-"VERSION); + exit(0); + } else if (!strcmp(argv[i], "-b")) { /* appears at the bottom of the screen */ + topbar = 0; + #if CENTER_PATCH + } else if (!strcmp(argv[i], "-c")) { /* toggles centering of dmenu window on screen */ + center = !center; + #endif // CENTER_PATCH + #if !NON_BLOCKING_STDIN_PATCH + } else if (!strcmp(argv[i], "-f")) { /* grabs keyboard before reading stdin */ + fast = 1; + #endif // NON_BLOCKING_STDIN_PATCH + #if INCREMENTAL_PATCH + } else if (!strcmp(argv[i], "-r")) { /* incremental */ + incremental = !incremental; + #endif // INCREMENTAL_PATCH + #if CASEINSENSITIVE_PATCH + } else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */ + fstrncmp = strncmp; + fstrstr = strstr; + #else + } else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ + fstrncmp = strncasecmp; + fstrstr = cistrstr; + #endif // CASEINSENSITIVE_PATCH + #if MANAGED_PATCH + } else if (!strcmp(argv[i], "-wm")) { /* display as managed wm window */ + managed = 1; + #endif // MANAGED_PATCH + #if INSTANT_PATCH + } else if (!strcmp(argv[i], "-n")) { /* instant select only match */ + instant = !instant; + #endif // INSTANT_PATCH + #if PRINTINPUTTEXT_PATCH + } else if (!strcmp(argv[i], "-t")) { /* favors text input over selection */ + use_text_input = 1; + #endif // PRINTINPUTTEXT_PATCH + #if PREFIXCOMPLETION_PATCH + } else if (!strcmp(argv[i], "-x")) { /* invert use_prefix */ + use_prefix = !use_prefix; + #endif // PREFIXCOMPLETION_PATCH + #if FUZZYMATCH_PATCH + } else if (!strcmp(argv[i], "-F")) { /* disable/enable fuzzy matching, depends on default */ + fuzzy = !fuzzy; + #endif // FUZZYMATCH_PATCH + #if PASSWORD_PATCH + } else if (!strcmp(argv[i], "-P")) { /* is the input a password */ + passwd = 1; + #endif // PASSWORD_PATCH + #if FZFEXPECT_PATCH + } else if (!strcmp(argv[i], "-ex")) { /* expect key */ + expected = argv[++i]; + #endif // FZFEXPECT_PATCH + #if REJECTNOMATCH_PATCH + } else if (!strcmp(argv[i], "-R")) { /* reject input which results in no match */ + reject_no_match = 1; + #endif // REJECTNOMATCH_PATCH + #if NO_SORT_PATCH + } else if (!strcmp(argv[i], "-S")) { /* do not sort matches */ + sortmatches = 0; + #endif // NO_SORT_PATCH + #if PRINTINDEX_PATCH + } else if (!strcmp(argv[i], "-ix")) { /* adds ability to return index in list */ + print_index = 1; + #endif // PRINTINDEX_PATCH + #if RESTRICT_RETURN_PATCH + } else if (!strcmp(argv[i], "-1")) { + restrict_return = 1; + #endif // RESTRICT_RETURN_PATCH + } else if (i + 1 == argc) + usage(); + /* these options take one argument */ + #if NAVHISTORY_PATCH + else if (!strcmp(argv[i], "-H")) + histfile = argv[++i]; + #endif // NAVHISTORY_PATCH + #if GRID_PATCH + else if (!strcmp(argv[i], "-g")) { /* number of columns in grid */ + columns = atoi(argv[++i]); + if (columns && lines == 0) + lines = 1; + } + #endif // GRID_PATCH + else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ + lines = atoi(argv[++i]); + #if XYW_PATCH + else if (!strcmp(argv[i], "-X")) /* window x offset */ + dmx = atoi(argv[++i]); + else if (!strcmp(argv[i], "-Y")) /* window y offset (from bottom up if -b) */ + dmy = atoi(argv[++i]); + else if (!strcmp(argv[i], "-W")) /* make dmenu this wide */ + dmw = atoi(argv[++i]); + #endif // XYW_PATCH + else if (!strcmp(argv[i], "-m")) + mon = atoi(argv[++i]); + #if ALPHA_PATCH + else if (!strcmp(argv[i], "-o")) /* opacity, pass -o 0 to disable alpha */ + opacity = atoi(argv[++i]); + #endif // ALPHA_PATCH + else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ + prompt = argv[++i]; + else if (!strcmp(argv[i], "-fn")) /* font or font set */ + #if PANGO_PATCH + strcpy(font, argv[++i]); + #else + fonts[0] = argv[++i]; + #endif // PANGO_PATCH + #if LINE_HEIGHT_PATCH + else if(!strcmp(argv[i], "-h")) { /* minimum height of one menu line */ + lineheight = atoi(argv[++i]); + lineheight = MAX(lineheight, min_lineheight); /* reasonable default in case of value too small/negative */ + } + #endif // LINE_HEIGHT_PATCH + else if (!strcmp(argv[i], "-nb")) /* normal background color */ + colors[SchemeNorm][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-nf")) /* normal foreground color */ + colors[SchemeNorm][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-sb")) /* selected background color */ + colors[SchemeSel][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ + colors[SchemeSel][ColFg] = argv[++i]; + #if HIGHPRIORITY_PATCH + else if (!strcmp(argv[i], "-hb")) /* high priority background color */ + colors[SchemeHp][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-hf")) /* low priority background color */ + colors[SchemeHp][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-hp")) + hpitems = tokenize(argv[++i], ",", &hplength); + #endif // HIGHPRIORITY_PATCH + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + else if (!strcmp(argv[i], "-nhb")) /* normal hi background color */ + colors[SchemeNormHighlight][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-nhf")) /* normal hi foreground color */ + colors[SchemeNormHighlight][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-shb")) /* selected hi background color */ + colors[SchemeSelHighlight][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-shf")) /* selected hi foreground color */ + colors[SchemeSelHighlight][ColFg] = argv[++i]; + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + else if (!strcmp(argv[i], "-w")) /* embedding window id */ + embed = argv[++i]; + #if SEPARATOR_PATCH + else if (!strcmp(argv[i], "-d") || /* field separator */ + (separator_greedy = !strcmp(argv[i], "-D"))) { + separator = argv[++i][0]; + separator_reverse = argv[i][1] == '|'; + } + #endif // SEPARATOR_PATCH + #if PRESELECT_PATCH + else if (!strcmp(argv[i], "-ps")) /* preselected item */ + preselected = atoi(argv[++i]); + #endif // PRESELECT_PATCH + #if DYNAMIC_OPTIONS_PATCH + else if (!strcmp(argv[i], "-dy")) /* dynamic command to run */ + dynamic = argv[++i]; + #endif // DYNAMIC_OPTIONS_PATCH + #if BORDER_PATCH + else if (!strcmp(argv[i], "-bw")) /* border width around dmenu */ + border_width = atoi(argv[++i]); + #endif // BORDER_PATCH + #if INITIALTEXT_PATCH + else if (!strcmp(argv[i], "-it")) { /* adds initial text */ + const char * text = argv[++i]; + insert(text, strlen(text)); + } + #endif // INITIALTEXT_PATCH + else + usage(); + + #if XRESOURCES_PATCH + #if PANGO_PATCH + if (!drw_font_create(drw, font)) + die("no fonts could be loaded."); + #else + if (!drw_fontset_create(drw, (const char**)fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + #endif // PANGO_PATCH + #else // !XRESOURCES_PATCH + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("cannot open display"); + screen = DefaultScreen(dpy); + root = RootWindow(dpy, screen); + if (!embed || !(parentwin = strtol(embed, NULL, 0))) + parentwin = root; + if (!XGetWindowAttributes(dpy, parentwin, &wa)) + die("could not get embedding window attributes: 0x%lx", + parentwin); + + #if ALPHA_PATCH + xinitvisual(); + drw = drw_create(dpy, screen, root, wa.width, wa.height, visual, depth, cmap); + #else + drw = drw_create(dpy, screen, root, wa.width, wa.height); + #endif // ALPHA_PATCH + + #if PANGO_PATCH + if (!drw_font_create(drw, font)) + die("no fonts could be loaded."); + #else if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) die("no fonts could be loaded."); + #endif // PANGO_PATCH + #endif // XRESOURCES_PATCH + + #if PANGO_PATCH + lrpad = drw->font->h; + #else lrpad = drw->fonts->h; + #endif // PANGO_PATCH + + #if BARPADDING_PATCH + sp = sidepad; + vp = (topbar ? vertpad : - vertpad); + #endif // BARPADDING_PATCH + + #if LINE_HEIGHT_PATCH + if (lineheight == -1) + #if PANGO_PATCH + lineheight = drw->font->h * 2.5; + #else + lineheight = drw->fonts->h * 2.5; + #endif // PANGO_PATCH + #endif // LINE_HEIGHT_PATCH #ifdef __OpenBSD__ if (pledge("stdio rpath", NULL) == -1) die("pledge"); #endif + #if NAVHISTORY_PATCH + loadhistory(); + #endif // NAVHISTORY_PATCH + #if NON_BLOCKING_STDIN_PATCH + grabkeyboard(); + #else if (fast && !isatty(0)) { grabkeyboard(); + #if DYNAMIC_OPTIONS_PATCH + if (!(dynamic && *dynamic)) + readstdin(); + #else readstdin(); + #endif // DYNAMIC_OPTIONS_PATCH } else { + #if DYNAMIC_OPTIONS_PATCH + if (!(dynamic && *dynamic)) + readstdin(); + #else readstdin(); + #endif // DYNAMIC_OPTIONS_PATCH grabkeyboard(); } + #endif // NON_BLOCKING_STDIN_PATCH setup(); run(); diff --git a/dwm/.dmenu/dmenu_run b/dwm/.dmenu/dmenu_run index 834ede5..cc05de4 100755 --- a/dwm/.dmenu/dmenu_run +++ b/dwm/.dmenu/dmenu_run @@ -1,2 +1,6 @@ #!/bin/sh -dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} & +export _JAVA_AWT_WM_NONREPARENTING=1 +exec $(dmenu_path | dmenu "$@") + +# Uncomment for the NAVHISTORY patch (and remove the exec above) +#dmenu_path | dmenu -H "${XDG_CACHE_HOME:-$HOME/.cache/}/dmenu_run.hist" "$@" | ${SHELL:-"/bin/sh"} & \ No newline at end of file diff --git a/dwm/.dmenu/drw.c b/dwm/.dmenu/drw.c index a58a2b4..62096d1 100644 --- a/dwm/.dmenu/drw.c +++ b/dwm/.dmenu/drw.c @@ -5,9 +5,11 @@ #include #include +#include "patches.h" #include "drw.h" #include "util.h" +#if !PANGO_PATCH #define UTF_INVALID 0xFFFD #define UTF_SIZ 4 @@ -59,9 +61,14 @@ utf8decode(const char *c, long *u, size_t clen) return len; } +#endif // PANGO_PATCH Drw * +#if ALPHA_PATCH +drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) +#else drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) +#endif // ALPHA_PATCH { Drw *drw = ecalloc(1, sizeof(Drw)); @@ -70,8 +77,16 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h drw->root = root; drw->w = w; drw->h = h; + #if ALPHA_PATCH + drw->visual = visual; + drw->depth = depth; + drw->cmap = cmap; + drw->drawable = XCreatePixmap(dpy, root, w, h, depth); + drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); + #else drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); drw->gc = XCreateGC(dpy, root, 0, NULL); + #endif // ALPHA_PATCH XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); return drw; @@ -87,7 +102,11 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) drw->h = h; if (drw->drawable) XFreePixmap(drw->dpy, drw->drawable); + #if ALPHA_PATCH + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); + #else drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); + #endif // ALPHA_PATCH } void @@ -95,10 +114,49 @@ drw_free(Drw *drw) { XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc); + #if PANGO_PATCH + drw_font_free(drw->font); + #else drw_fontset_free(drw->fonts); + #endif // PANGO_PATCH free(drw); } +#if PANGO_PATCH +/* This function is an implementation detail. Library users should use + * drw_font_create instead. + */ +static Fnt * +xfont_create(Drw *drw, const char *fontname) +{ + Fnt *font; + PangoFontMap *fontmap; + PangoContext *context; + PangoFontDescription *desc; + PangoFontMetrics *metrics; + + if (!fontname) { + die("no font specified."); + } + + font = ecalloc(1, sizeof(Fnt)); + font->dpy = drw->dpy; + + fontmap = pango_xft_get_font_map(drw->dpy, drw->screen); + context = pango_font_map_create_context(fontmap); + desc = pango_font_description_from_string(fontname); + font->layout = pango_layout_new(context); + pango_layout_set_font_description(font->layout, desc); + + metrics = pango_context_get_metrics(context, desc, pango_language_from_string ("en-us")); + font->h = pango_font_metrics_get_height(metrics) / PANGO_SCALE; + + pango_font_metrics_unref(metrics); + g_object_unref(context); + + return font; +} +#else /* This function is an implementation detail. Library users should use * drw_fontset_create instead. */ @@ -133,6 +191,21 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) die("no font specified."); } + #if NO_COLOR_EMOJI_PATCH + /* Do not allow using color fonts. This is a workaround for a BadLength + * error from Xft with color glyphs. Modelled on the Xterm workaround. See + * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 + * https://lists.suckless.org/dev/1701/30932.html + * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349 + * and lots more all over the internet. + */ + FcBool iscol; + if (FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { + XftFontClose(drw->dpy, xfont); + return NULL; + } + #endif // NO_COLOR_EMOJI_PATCH + font = ecalloc(1, sizeof(Fnt)); font->xfont = xfont; font->pattern = pattern; @@ -141,18 +214,38 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) return font; } +#endif // PANGO_PATCH static void xfont_free(Fnt *font) { if (!font) return; + #if PANGO_PATCH + if (font->layout) + g_object_unref(font->layout); + #else if (font->pattern) FcPatternDestroy(font->pattern); XftFontClose(font->dpy, font->xfont); + #endif // PANGO_PATCH free(font); } +#if PANGO_PATCH +Fnt* +drw_font_create(Drw* drw, const char font[]) +{ + Fnt *fnt = NULL; + + if (!drw || !font) + return NULL; + + fnt = xfont_create(drw, font); + + return (drw->font = fnt); +} +#else Fnt* drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) { @@ -170,7 +263,16 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) } return (drw->fonts = ret); } +#endif // PANGO_PATCH +#if PANGO_PATCH +void +drw_font_free(Fnt *font) +{ + if (font) + xfont_free(font); +} +#else void drw_fontset_free(Fnt *font) { @@ -179,23 +281,40 @@ drw_fontset_free(Fnt *font) xfont_free(font); } } +#endif // PANGO_PATCH void +#if ALPHA_PATCH +drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) +#else drw_clr_create(Drw *drw, Clr *dest, const char *clrname) +#endif // ALPHA_PATCH { if (!drw || !dest || !clrname) return; + #if ALPHA_PATCH + if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); + + dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); + #else if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), DefaultColormap(drw->dpy, drw->screen), clrname, dest)) die("error, cannot allocate color '%s'", clrname); + #endif // ALPHA_PATCH } /* Wrapper to create color schemes. The caller has to call free(3) on the * returned color scheme when done using it. */ Clr * +#if ALPHA_PATCH +drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount) +#else drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) +#endif // ALPHA_PATCH { size_t i; Clr *ret; @@ -205,16 +324,22 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) return NULL; for (i = 0; i < clrcount; i++) + #if ALPHA_PATCH + drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); + #else drw_clr_create(drw, &ret[i], clrnames[i]); + #endif // ALPHA_PATCH return ret; } +#if !PANGO_PATCH void drw_setfontset(Drw *drw, Fnt *set) { if (drw) drw->fonts = set; } +#endif // PANGO_PATCH void drw_setscheme(Drw *drw, Clr *scm) @@ -235,6 +360,73 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); } +#if PANGO_PATCH +int +drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup) +{ + char buf[1024]; + int ty; + unsigned int ew; + XftDraw *d = NULL; + size_t i, len; + int render = x || y || w || h; + + if (!drw || (render && !drw->scheme) || !text || !drw->font) + return 0; + + if (!render) { + w = invert ? invert : ~invert; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + #if ALPHA_PATCH + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); + #else + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + #endif // ALPHA_PATCH + x += lpad; + w -= lpad; + } + + len = strlen(text); + + if (len) { + drw_font_getexts(drw->font, text, len, &ew, NULL, markup); + /* shorten text if necessary */ + for (len = MIN(len, sizeof(buf) - 1); len && ew > w; len--) + drw_font_getexts(drw->font, text, len, &ew, NULL, markup); + + if (len) { + memcpy(buf, text, len); + buf[len] = '\0'; + if (len < strlen(text)) + for (i = len; i && i > len - 3; buf[--i] = '.') + ; /* NOP */ + + if (render) { + ty = y + (h - drw->font->h) / 2; + if (markup) + pango_layout_set_markup(drw->font->layout, buf, len); + else + pango_layout_set_text(drw->font->layout, buf, len); + pango_xft_render_layout(d, &drw->scheme[invert ? ColBg : ColFg], + drw->font->layout, x * PANGO_SCALE, ty * PANGO_SCALE); + if (markup) /* clear markup attributes */ + pango_layout_set_attributes(drw->font->layout, NULL); + } + x += ew; + w -= ew; + } + } + + if (d) + XftDrawDestroy(d); + + return x + (render ? w : 0); +} +#else int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) { @@ -253,6 +445,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp /* keep track of a couple codepoints for which we have no match. */ enum { nomatches_len = 64 }; static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches; + const char *ellipsis = "..."; static unsigned int ellipsis_width = 0; if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts) @@ -263,16 +456,20 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp } else { XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + #if ALPHA_PATCH + d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); + #else d = XftDrawCreate(drw->dpy, drw->drawable, DefaultVisual(drw->dpy, drw->screen), DefaultColormap(drw->dpy, drw->screen)); + #endif // ALPHA_PATCH x += lpad; w -= lpad; } usedfont = drw->fonts; if (!ellipsis_width && render) - ellipsis_width = drw_fontset_getwidth(drw, "..."); + ellipsis_width = drw_fontset_getwidth(drw, ellipsis); while (1) { ew = ellipsis_len = utf8strlen = 0; utf8str = text; @@ -300,12 +497,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp else utf8strlen = ellipsis_len; } else if (curfont == usedfont) { - utf8strlen += utf8charlen; - text += utf8charlen; + utf8strlen += utf8charlen; + text += utf8charlen; ew += tmpw; - } else { - nextfont = curfont; - } + } else { + nextfont = curfont; + } break; } } @@ -321,12 +518,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen); - } + } x += ew; w -= ew; } - if (render && overflow) - drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); + if (render && overflow && ellipsis_w) + drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, ellipsis, invert); if (!*text || overflow) { break; @@ -355,6 +552,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp fcpattern = FcPatternDuplicate(drw->fonts->pattern); FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + #if NO_COLOR_EMOJI_PATCH + FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); + #endif // NO_COLOR_EMOJI_PATCH FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); FcDefaultSubstitute(fcpattern); @@ -383,6 +583,7 @@ no_match: return x + (render ? w : 0); } +#endif // PANGO_PATCH void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) @@ -394,6 +595,24 @@ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) XSync(drw->dpy, False); } +#if PANGO_PATCH +unsigned int +drw_font_getwidth(Drw *drw, const char *text, Bool markup) +{ + if (!drw || !drw->font || !text) + return 0; + return drw_text(drw, 0, 0, 0, 0, 0, text, 0, markup); +} + +unsigned int +drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) +{ + unsigned int tmp = 0; + if (drw && drw->font && text && n) + tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n, True); + return MIN(n, tmp); +} +#else unsigned int drw_fontset_getwidth(Drw *drw, const char *text) { @@ -410,7 +629,29 @@ drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n) tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n); return MIN(n, tmp); } +#endif // PANGO_PATCH +#if PANGO_PATCH +void +drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup) +{ + if (!font || !text) + return; + + PangoRectangle r; + if (markup) + pango_layout_set_markup(font->layout, text, len); + else + pango_layout_set_text(font->layout, text, len); + pango_layout_get_extents(font->layout, 0, &r); + if (markup) /* clear markup attributes */ + pango_layout_set_attributes(font->layout, NULL); + if (w) + *w = r.width / PANGO_SCALE; + if (h) + *h = font->h; +} +#else void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) { @@ -425,6 +666,7 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, if (h) *h = font->h; } +#endif // PANGO_PATCH Cur * drw_cur_create(Drw *drw, int shape) @@ -448,3 +690,7 @@ drw_cur_free(Drw *drw, Cur *cursor) XFreeCursor(drw->dpy, cursor->cursor); free(cursor); } + +#if SCROLL_PATCH +#include "patch/scroll.c" +#endif diff --git a/dwm/.dmenu/drw.h b/dwm/.dmenu/drw.h index fd7631b..af4af4d 100644 --- a/dwm/.dmenu/drw.h +++ b/dwm/.dmenu/drw.h @@ -1,5 +1,10 @@ /* See LICENSE file for copyright and license details. */ +#if PANGO_PATCH +#include +#include +#endif // PANGO_PATCH + typedef struct { Cursor cursor; } Cur; @@ -7,9 +12,13 @@ typedef struct { typedef struct Fnt { Display *dpy; unsigned int h; + #if PANGO_PATCH + PangoLayout *layout; + #else XftFont *xfont; FcPattern *pattern; struct Fnt *next; + #endif // PANGO_PATCH } Fnt; enum { ColFg, ColBg }; /* Clr scheme index */ @@ -20,39 +29,75 @@ typedef struct { Display *dpy; int screen; Window root; + #if ALPHA_PATCH + Visual *visual; + unsigned int depth; + Colormap cmap; + #endif // ALPHA_PATCH Drawable drawable; GC gc; Clr *scheme; + #if PANGO_PATCH + Fnt *font; + #else Fnt *fonts; + #endif // PANGO_PATCH } Drw; /* Drawable abstraction */ +#if ALPHA_PATCH +Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap); +#else Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +#endif // ALPHA_PATCH void drw_resize(Drw *drw, unsigned int w, unsigned int h); void drw_free(Drw *drw); /* Fnt abstraction */ +#if PANGO_PATCH +Fnt *drw_font_create(Drw* drw, const char font[]); +void drw_font_free(Fnt* set); +unsigned int drw_font_getwidth(Drw *drw, const char *text, Bool markup); +unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); +void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h, Bool markup); +#else Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); void drw_fontset_free(Fnt* set); unsigned int drw_fontset_getwidth(Drw *drw, const char *text); unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); +#endif // PANGO_PATCH /* Colorscheme abstraction */ +#if ALPHA_PATCH +void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); +Clr *drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount); +#else void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); +#endif // ALPHA_PATCH /* Cursor abstraction */ Cur *drw_cur_create(Drw *drw, int shape); void drw_cur_free(Drw *drw, Cur *cursor); /* Drawing context manipulation */ +#if !PANGO_PATCH void drw_setfontset(Drw *drw, Fnt *set); +#endif // PANGO_PATCH void drw_setscheme(Drw *drw, Clr *scm); /* Drawing functions */ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); +#if PANGO_PATCH +int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert, Bool markup); +#else int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); +#endif // PANGO_PATCH /* Map functions */ void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); + +#if SCROLL_PATCH +#include "patch/scroll.h" +#endif \ No newline at end of file diff --git a/dwm/.dmenu/patch/center.c b/dwm/.dmenu/patch/center.c new file mode 100644 index 0000000..9682bfb --- /dev/null +++ b/dwm/.dmenu/patch/center.c @@ -0,0 +1,8 @@ +static int +max_textw(void) +{ + int len = 0; + for (struct item *item = items; item && item->text; item++) + len = MAX(TEXTW(item->text), len); + return len; +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/dynamicoptions.c b/dwm/.dmenu/patch/dynamicoptions.c new file mode 100644 index 0000000..0102cfb --- /dev/null +++ b/dwm/.dmenu/patch/dynamicoptions.c @@ -0,0 +1,91 @@ +static void +refreshoptions() +{ + int dynlen = strlen(dynamic); + char* cmd= malloc(dynlen + strlen(text) + 2); + if (cmd == NULL) + die("malloc:"); + sprintf(cmd, "%s %s", dynamic, text); + FILE *stream = popen(cmd, "r"); + if (!stream) + die("popen(%s):", cmd); + readstream(stream); + int pc = pclose(stream); + if (pc == -1) + die("pclose:"); + free(cmd); + curr = sel = items; +} + +static void +readstream(FILE* stream) +{ + char buf[sizeof text], *p; + size_t i, imax = 0, size = 0; + unsigned int tmpmax = 0; + + /* read each line from stdin and add it to the item list */ + for (i = 0; fgets(buf, sizeof buf, stream); i++) { + if (i + 1 >= size / sizeof *items) + if (!(items = realloc(items, (size += BUFSIZ)))) + die("cannot realloc %u bytes:", size); + if ((p = strchr(buf, '\n'))) + *p = '\0'; + if (!(items[i].text = strdup(buf))) + die("cannot strdup %u bytes:", strlen(buf) + 1); + #if SEPARATOR_PATCH + if (separator && (p = separator_greedy ? + strrchr(items[i].text, separator) : strchr(items[i].text, separator))) { + *p = '\0'; + items[i].text_output = ++p; + } else { + items[i].text_output = items[i].text; + } + if (separator_reverse) { + p = items[i].text; + items[i].text = items[i].text_output; + items[i].text_output = p; + } + #elif TSV_PATCH + if ((p = strchr(buf, '\t'))) + *p = '\0'; + if (!(items[i].stext = strdup(buf))) + die("cannot strdup %u bytes:", strlen(buf) + 1); + #endif // TSV_PATCH + #if MULTI_SELECTION_PATCH + items[i].id = i; + #else + items[i].out = 0; + #endif // MULTI_SELECTION_PATCH + #if HIGHPRIORITY_PATCH + items[i].hp = arrayhas(hpitems, hplength, items[i].text); + #endif // HIGHPRIORITY_PATCH + #if PANGO_PATCH + drw_font_getexts(drw->font, buf, strlen(buf), &tmpmax, NULL, True); + #else + drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); + #endif // PANGO_PATCH + if (tmpmax > inputw) { + inputw = tmpmax; + imax = i; + } + } + + /* If the command did not give any output at all, then do not clear the existing items */ + if (!i) + return; + + if (items) + items[i].text = NULL; + #if PANGO_PATCH + inputw = items ? TEXTWM(items[imax].text) : 0; + #else + inputw = items ? TEXTW(items[imax].text) : 0; + #endif // PANGO_PATCH + if (!dynamic || !*dynamic) + lines = MIN(lines, i); + else { + text[0] = '\0'; + cursor = 0; + } +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/dynamicoptions.h b/dwm/.dmenu/patch/dynamicoptions.h new file mode 100644 index 0000000..eba9fb0 --- /dev/null +++ b/dwm/.dmenu/patch/dynamicoptions.h @@ -0,0 +1,2 @@ +static void refreshoptions(); +static void readstream(FILE* stream); \ No newline at end of file diff --git a/dwm/.dmenu/patch/fuzzyhighlight.c b/dwm/.dmenu/patch/fuzzyhighlight.c new file mode 100644 index 0000000..a62fba7 --- /dev/null +++ b/dwm/.dmenu/patch/fuzzyhighlight.c @@ -0,0 +1,57 @@ +static void +#if EMOJI_HIGHLIGHT_PATCH +drawhighlights(struct item *item, char *output, int x, int y, int maxw) +#else +drawhighlights(struct item *item, int x, int y, int maxw) +#endif // EMOJI_HIGHLIGHT_PATCH +{ + int i, indent; + char *highlight; + char c; + + #if EMOJI_HIGHLIGHT_PATCH + char *itemtext = output; + #elif TSV_PATCH && !SEPARATOR_PATCH + char *itemtext = item->stext; + #else + char *itemtext = item->text; + #endif // TSV_PATCH + + if (!(strlen(itemtext) && strlen(text))) + return; + + drw_setscheme(drw, scheme[item == sel + ? SchemeSelHighlight + : SchemeNormHighlight]); + for (i = 0, highlight = itemtext; *highlight && text[i];) { + #if FUZZYMATCH_PATCH + if (!fstrncmp(&(*highlight), &text[i], 1)) + #else + if (*highlight == text[i]) + #endif // FUZZYMATCH_PATCH + { + /* get indentation */ + c = *highlight; + *highlight = '\0'; + indent = TEXTW(itemtext) - lrpad; + *highlight = c; + + /* highlight character */ + c = highlight[1]; + highlight[1] = '\0'; + drw_text( + drw, + x + indent + (lrpad / 2), + y, + MIN(maxw - indent - lrpad, TEXTW(highlight) - lrpad), + bh, 0, highlight, 0 + #if PANGO_PATCH + , True + #endif // PANGO_PATCH + ); + highlight[1] = c; + i++; + } + highlight++; + } +} diff --git a/dwm/.dmenu/patch/fuzzymatch.c b/dwm/.dmenu/patch/fuzzymatch.c new file mode 100644 index 0000000..ab934ba --- /dev/null +++ b/dwm/.dmenu/patch/fuzzymatch.c @@ -0,0 +1,106 @@ +#include + +int +compare_distance(const void *a, const void *b) +{ + struct item *da = *(struct item **) a; + struct item *db = *(struct item **) b; + + if (!db) + return 1; + if (!da) + return -1; + + return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1; +} + +void +fuzzymatch(void) +{ + /* bang - we have so much memory */ + struct item *it; + struct item **fuzzymatches = NULL; + char c; + int number_of_matches = 0, i, pidx, sidx, eidx; + int text_len = strlen(text), itext_len; + #if HIGHPRIORITY_PATCH + struct item *lhpprefix, *hpprefixend; + lhpprefix = hpprefixend = NULL; + #endif // HIGHPRIORITY_PATCH + matches = matchend = NULL; + + /* walk through all items */ + for (it = items; it && it->text; it++) { + if (text_len) { + itext_len = strlen(it->text); + pidx = 0; /* pointer */ + sidx = eidx = -1; /* start of match, end of match */ + /* walk through item text */ + for (i = 0; i < itext_len && (c = it->text[i]); i++) { + /* fuzzy match pattern */ + if (!fstrncmp(&text[pidx], &c, 1)) { + if (sidx == -1) + sidx = i; + pidx++; + if (pidx == text_len) { + eidx = i; + break; + } + } + } + /* build list of matches */ + if (eidx != -1) { + /* compute distance */ + /* add penalty if match starts late (log(sidx+2)) + * add penalty for long a match without many matching characters */ + it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len); + /* fprintf(stderr, "distance %s %f\n", it->text, it->distance); */ + appenditem(it, &matches, &matchend); + number_of_matches++; + } + } else { + appenditem(it, &matches, &matchend); + } + } + + if (number_of_matches) { + /* initialize array with matches */ + if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*)))) + die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item*)); + for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) { + fuzzymatches[i] = it; + } + + #if NO_SORT_PATCH + if (sortmatches) + #endif // NO_SORT_PATCH + /* sort matches according to distance */ + qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance); + /* rebuild list of matches */ + matches = matchend = NULL; + for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \ + it->text; i++, it = fuzzymatches[i]) { + #if HIGHPRIORITY_PATCH + #if NO_SORT_PATCH + if (sortmatches && it->hp) + #else + if (it->hp) + #endif // NO_SORT_PATCH + appenditem(it, &lhpprefix, &hpprefixend); + else + appenditem(it, &matches, &matchend); + #else + appenditem(it, &matches, &matchend); + #endif // HIGHPRIORITY_PATCH + } + free(fuzzymatches); + } + #if HIGHPRIORITY_PATCH + if (lhpprefix) { + hpprefixend->right = matches; + matches = lhpprefix; + } + #endif // HIGHPRIORITY_PATCH + curr = sel = matches; + calcoffsets(); +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/fzfexpect.c b/dwm/.dmenu/patch/fzfexpect.c new file mode 100644 index 0000000..1563362 --- /dev/null +++ b/dwm/.dmenu/patch/fzfexpect.c @@ -0,0 +1,39 @@ +static char *expected; +#if MULTI_SELECTION_PATCH +void +expect(char *expect, XKeyEvent *ev) +{ + if (sel && expected && strstr(expected, expect)) { + if (expected && sel && !(ev->state & ShiftMask)) + puts(expect); + for (int i = 0; i < selidsize; i++) + if (selid[i] != -1 && (!sel || sel->id != selid[i])) + puts(items[selid[i]].text); + if (sel && !(ev->state & ShiftMask)) { + puts(sel->text); + } else + puts(text); + cleanup(); + exit(1); + } else if (!sel && expected && strstr(expected, expect)) { + puts(expect); + cleanup(); + exit(1); + } +} +#else +void +expect(char *expect, XKeyEvent *ignored) +{ + if (sel && expected && strstr(expected, expect)) { + puts(expect); + puts(sel->text); + cleanup(); + exit(1); + } else if (!sel && expected && strstr(expected, expect)){ + puts(expect); + cleanup(); + exit(1); + } +} +#endif // MULTI_SELECTION_PATCH \ No newline at end of file diff --git a/dwm/.dmenu/patch/fzfexpect.h b/dwm/.dmenu/patch/fzfexpect.h new file mode 100644 index 0000000..95c1dad --- /dev/null +++ b/dwm/.dmenu/patch/fzfexpect.h @@ -0,0 +1 @@ +static void expect(char *expect, XKeyEvent *ev); diff --git a/dwm/.dmenu/patch/highlight.c b/dwm/.dmenu/patch/highlight.c new file mode 100644 index 0000000..b5947b5 --- /dev/null +++ b/dwm/.dmenu/patch/highlight.c @@ -0,0 +1,51 @@ +static void +#if EMOJI_HIGHLIGHT_PATCH +drawhighlights(struct item *item, char *output, int x, int y, int maxw) +#else +drawhighlights(struct item *item, int x, int y, int maxw) +#endif // EMOJI_HIGHLIGHT_PATCH +{ + char restorechar, tokens[sizeof text], *highlight, *token; + int indentx, highlightlen; + #if EMOJI_HIGHLIGHT_PATCH + char *itemtext = output; + #elif TSV_PATCH && !SEPARATOR_PATCH + char *itemtext = item->stext; + #else + char *itemtext = item->text; + #endif // EMOJI_HIGHLIGHT_PATCH | TSV_PATCH + + drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : SchemeNormHighlight]); + strcpy(tokens, text); + for (token = strtok(tokens, " "); token; token = strtok(NULL, " ")) { + highlight = fstrstr(itemtext, token); + while (highlight) { + // Move item str end, calc width for highlight indent, & restore + highlightlen = highlight - itemtext; + restorechar = *highlight; + itemtext[highlightlen] = '\0'; + indentx = TEXTW(itemtext); + itemtext[highlightlen] = restorechar; + + // Move highlight str end, draw highlight, & restore + restorechar = highlight[strlen(token)]; + highlight[strlen(token)] = '\0'; + if (indentx - (lrpad / 2) - 1 < maxw) + drw_text( + drw, + x + indentx - (lrpad / 2) - 1, + y, + MIN(maxw - indentx, TEXTW(highlight) - lrpad), + bh, 0, highlight, 0 + #if PANGO_PATCH + , True + #endif // PANGO_PATCH + ); + highlight[strlen(token)] = restorechar; + + if (strlen(highlight) - strlen(token) < strlen(token)) + break; + highlight = fstrstr(highlight + strlen(token), token); + } + } +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/highpriority.c b/dwm/.dmenu/patch/highpriority.c new file mode 100644 index 0000000..2b3577a --- /dev/null +++ b/dwm/.dmenu/patch/highpriority.c @@ -0,0 +1,35 @@ +static char **hpitems = NULL; +static int hplength = 0; + +static char ** +tokenize(char *source, const char *delim, int *llen) +{ + int listlength = 0, list_size = 0; + char **list = NULL, *token; + + token = strtok(source, delim); + while (token) { + if (listlength + 1 >= list_size) { + if (!(list = realloc(list, (list_size += 8) * sizeof(*list)))) + die("Unable to realloc %zu bytes\n", list_size * sizeof(*list)); + } + if (!(list[listlength] = strdup(token))) + die("Unable to strdup %zu bytes\n", strlen(token) + 1); + token = strtok(NULL, delim); + listlength++; + } + + *llen = listlength; + return list; +} + +static int +arrayhas(char **list, int length, char *item) { + for (int i = 0; i < length; i++) { + int len1 = strlen(list[i]); + int len2 = strlen(item); + if (fstrncmp(list[i], item, len1 > len2 ? len2 : len1) == 0) + return 1; + } + return 0; +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/highpriority.h b/dwm/.dmenu/patch/highpriority.h new file mode 100644 index 0000000..8fa65bf --- /dev/null +++ b/dwm/.dmenu/patch/highpriority.h @@ -0,0 +1,2 @@ +static int arrayhas(char **list, int length, char *item); + diff --git a/dwm/.dmenu/patch/include.c b/dwm/.dmenu/patch/include.c new file mode 100644 index 0000000..4240212 --- /dev/null +++ b/dwm/.dmenu/patch/include.c @@ -0,0 +1,38 @@ +#if CENTER_PATCH +#include "center.c" +#endif +#if FUZZYHIGHLIGHT_PATCH +#include "fuzzyhighlight.c" +#elif HIGHLIGHT_PATCH +#include "highlight.c" +#endif +#if FUZZYMATCH_PATCH +#include "fuzzymatch.c" +#endif +#if FZFEXPECT_PATCH +#include "fzfexpect.c" +#endif +#if HIGHPRIORITY_PATCH +#include "highpriority.c" +#endif +#if DYNAMIC_OPTIONS_PATCH +#include "dynamicoptions.c" +#endif +#if MULTI_SELECTION_PATCH +#include "multiselect.c" +#endif +#if MOUSE_SUPPORT_PATCH +#include "mousesupport.c" +#endif +#if NAVHISTORY_PATCH +#include "navhistory.c" +#endif +#if NON_BLOCKING_STDIN_PATCH +#include "nonblockingstdin.c" +#endif +#if NUMBERS_PATCH +#include "numbers.c" +#endif +#if XRESOURCES_PATCH +#include "xresources.c" +#endif \ No newline at end of file diff --git a/dwm/.dmenu/patch/include.h b/dwm/.dmenu/patch/include.h new file mode 100644 index 0000000..1e7e0cc --- /dev/null +++ b/dwm/.dmenu/patch/include.h @@ -0,0 +1,15 @@ +#if DYNAMIC_OPTIONS_PATCH +#include "dynamicoptions.h" +#endif +#if FZFEXPECT_PATCH +#include "fzfexpect.h" +#endif +#if HIGHPRIORITY_PATCH +#include "highpriority.h" +#endif +#if NON_BLOCKING_STDIN_PATCH +#include "nonblockingstdin.h" +#endif +#if NUMBERS_PATCH +#include "numbers.h" +#endif \ No newline at end of file diff --git a/dwm/.dmenu/patch/mousesupport.c b/dwm/.dmenu/patch/mousesupport.c new file mode 100644 index 0000000..d040e86 --- /dev/null +++ b/dwm/.dmenu/patch/mousesupport.c @@ -0,0 +1,159 @@ +static void +buttonpress(XEvent *e) +{ + struct item *item; + XButtonPressedEvent *ev = &e->xbutton; + int x = 0, y = 0, h = bh, w; + + if (ev->window != win) + return; + + /* right-click: exit */ + if (ev->button == Button3) + exit(1); + + if (prompt && *prompt) + x += promptw; + + /* input field */ + w = (lines > 0 || !matches) ? mw - x : inputw; + + /* left-click on input: clear input, + * NOTE: if there is no left-arrow the space for < is reserved so + * add that to the input width */ + #if SYMBOLS_PATCH + if (ev->button == Button1 && + ((lines <= 0 && ev->x >= 0 && ev->x <= x + w + + ((!prev || !curr->left) ? TEXTW(symbol_1) : 0)) || + (lines > 0 && ev->y >= y && ev->y <= y + h))) { + insert(NULL, -cursor); + drawmenu(); + return; + } + #else + if (ev->button == Button1 && + ((lines <= 0 && ev->x >= 0 && ev->x <= x + w + + ((!prev || !curr->left) ? TEXTW("<") : 0)) || + (lines > 0 && ev->y >= y && ev->y <= y + h))) { + insert(NULL, -cursor); + drawmenu(); + return; + } + #endif // SYMBOLS_PATCH + /* middle-mouse click: paste selection */ + if (ev->button == Button2) { + XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, + utf8, utf8, win, CurrentTime); + drawmenu(); + return; + } + /* scroll up */ + if (ev->button == Button4 && prev) { + sel = curr = prev; + calcoffsets(); + drawmenu(); + return; + } + /* scroll down */ + if (ev->button == Button5 && next) { + sel = curr = next; + calcoffsets(); + drawmenu(); + return; + } + if (ev->button != Button1) + return; + if (ev->state & ~ControlMask) + return; + if (lines > 0) { + /* vertical list: (ctrl)left-click on item */ + w = mw - x; + for (item = curr; item != next; item = item->right) { + y += h; + if (ev->y >= y && ev->y <= (y + h)) { + #if !MULTI_SELECTION_PATCH + puts(item->text); + #endif // MULTI_SELECTION_PATCH + if (!(ev->state & ControlMask)) { + #if MULTI_SELECTION_PATCH + sel = item; + selsel(); + printsel(ev->state); + #endif // MULTI_SELECTION_PATCH + exit(0); + } + sel = item; + if (sel) { + #if MULTI_SELECTION_PATCH + selsel(); + #else + sel->out = 1; + #endif // MULTI_SELECTION_PATCH + drawmenu(); + } + return; + } + } + } else if (matches) { + /* left-click on left arrow */ + x += inputw; + #if SYMBOLS_PATCH + w = TEXTW(symbol_1); + #else + w = TEXTW("<"); + #endif // SYMBOLS_PATCH + if (prev && curr->left) { + if (ev->x >= x && ev->x <= x + w) { + sel = curr = prev; + calcoffsets(); + drawmenu(); + return; + } + } + /* horizontal list: (ctrl)left-click on item */ + for (item = curr; item != next; item = item->right) { + x += w; + #if SYMBOLS_PATCH + w = MIN(TEXTW(item->text), mw - x - TEXTW(symbol_2)); + #else + w = MIN(TEXTW(item->text), mw - x - TEXTW(">")); + #endif // SYMBOLS_PATCH + if (ev->x >= x && ev->x <= x + w) { + #if !MULTI_SELECTION_PATCH + puts(item->text); + #endif // MULTI_SELECTION_PATCH + if (!(ev->state & ControlMask)) { + #if MULTI_SELECTION_PATCH + sel = item; + selsel(); + printsel(ev->state); + #endif // MULTI_SELECTION_PATCH + exit(0); + } + sel = item; + if (sel) { + #if MULTI_SELECTION_PATCH + selsel(); + #else + sel->out = 1; + #endif // MULTI_SELECTION_PATCH + drawmenu(); + } + return; + } + } + /* left-click on right arrow */ + #if SYMBOLS_PATCH + w = TEXTW(symbol_2); + #else + w = TEXTW(">"); + #endif // SYMBOLS_PATCH + x = mw - w; + if (next && ev->x >= x && ev->x <= x + w) { + sel = curr = next; + calcoffsets(); + drawmenu(); + return; + } + } +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/multiselect.c b/dwm/.dmenu/patch/multiselect.c new file mode 100644 index 0000000..ad78db3 --- /dev/null +++ b/dwm/.dmenu/patch/multiselect.c @@ -0,0 +1,53 @@ +static int +issel(size_t id) +{ + for (int i = 0;i < selidsize;i++) + if (selid[i] == id) + return 1; + return 0; +} + +static void +printsel(unsigned int state) +{ + for (int i = 0;i < selidsize;i++) + if (selid[i] != -1 && (!sel || sel->id != selid[i])) { + #if PRINTINDEX_PATCH + if (print_index) + printf("%d\n", selid[i]); + else + #endif // PRINTINDEX_PATCH + puts(items[selid[i]].text); + } + if (sel && !(state & ShiftMask)) { + #if PRINTINDEX_PATCH + if (print_index) + printf("%d\n", sel->index); + else + #endif // PRINTINDEX_PATCH + puts(sel->text); + } else + puts(text); + +} + +static void +selsel() +{ + if (!sel) + return; + if (issel(sel->id)) { + for (int i = 0; i < selidsize; i++) + if (selid[i] == sel->id) + selid[i] = -1; + } else { + for (int i = 0; i < selidsize; i++) + if (selid[i] == -1) { + selid[i] = sel->id; + return; + } + selidsize++; + selid = realloc(selid, (selidsize + 1) * sizeof(int)); + selid[selidsize - 1] = sel->id; + } +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/navhistory.c b/dwm/.dmenu/patch/navhistory.c new file mode 100644 index 0000000..7d10ee4 --- /dev/null +++ b/dwm/.dmenu/patch/navhistory.c @@ -0,0 +1,126 @@ +static char *histfile; +static char **history; +static size_t histsz, histpos; + +static void +loadhistory(void) +{ + FILE *fp = NULL; + static size_t cap = 0; + size_t llen; + char *line; + + if (!histfile) { + return; + } + + fp = fopen(histfile, "r"); + if (!fp) { + return; + } + + for (;;) { + line = NULL; + llen = 0; + if (-1 == getline(&line, &llen, fp)) { + if (ferror(fp)) { + die("failed to read history"); + } + free(line); + break; + } + + if (cap == histsz) { + cap += 64 * sizeof(char*); + history = realloc(history, cap); + if (!history) { + die("failed to realloc memory"); + } + } + strtok(line, "\n"); + history[histsz] = line; + histsz++; + } + histpos = histsz; + + if (fclose(fp)) { + die("failed to close file %s", histfile); + } +} + +static void +navhistory(int dir) +{ + static char def[BUFSIZ]; + char *p = NULL; + size_t len = 0; + + if (!history || histpos + 1 == 0) + return; + + if (histsz == histpos) { + strncpy(def, text, sizeof(def)); + } + + switch(dir) { + case 1: + if (histpos < histsz - 1) { + p = history[++histpos]; + } else if (histpos == histsz - 1) { + p = def; + histpos++; + } + break; + case -1: + if (histpos > 0) { + p = history[--histpos]; + } + break; + } + if (p == NULL) { + return; + } + + len = MIN(strlen(p), BUFSIZ - 1); + strncpy(text, p, len); + text[len] = '\0'; + cursor = len; + match(); +} + +static void +savehistory(char *input) +{ + unsigned int i; + FILE *fp; + + if (!histfile || + 0 == maxhist || + 0 == strlen(input)) { + goto out; + } + + fp = fopen(histfile, "w"); + if (!fp) { + die("failed to open %s", histfile); + } + for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) { + if (0 >= fprintf(fp, "%s\n", history[i])) { + die("failed to write to %s", histfile); + } + } + if (histsz == 0 || !histnodup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) { /* TODO */ + if (0 >= fputs(input, fp)) { + die("failed to write to %s", histfile); + } + } + if (fclose(fp)) { + die("failed to close file %s", histfile); + } + +out: + for (i = 0; i < histsz; i++) { + free(history[i]); + } + free(history); +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/nonblockingstdin.c b/dwm/.dmenu/patch/nonblockingstdin.c new file mode 100644 index 0000000..eb7013f --- /dev/null +++ b/dwm/.dmenu/patch/nonblockingstdin.c @@ -0,0 +1,68 @@ +#include +#include +#include + +static void +readstdin(void) +{ + static size_t max = 0; + static struct item **end = &items; + + char buf[sizeof text], *p, *maxstr; + struct item *item; + + #if PASSWORD_PATCH + if (passwd) { + inputw = lines = 0; + return; + } + #endif // PASSWORD_PATCH + + /* read each line from stdin and add it to the item list */ + while (fgets(buf, sizeof buf, stdin)) { + if (!(item = malloc(sizeof *item))) + die("cannot malloc %u bytes:", sizeof *item); + if ((p = strchr(buf, '\n'))) + *p = '\0'; + if (!(item->text = strdup(buf))) + die("cannot strdup %u bytes:", strlen(buf)+1); + if (strlen(item->text) > max) { + max = strlen(maxstr = item->text); + #if PANGO_PATCH + inputw = maxstr ? TEXTWM(maxstr) : 0; + #else + inputw = maxstr ? TEXTW(maxstr) : 0; + #endif // PANGO_PATCH + } + *end = item; + end = &item->next; + item->next = NULL; + item->out = 0; + } + match(); + drawmenu(); +} + +static void +run(void) +{ + fd_set fds; + int flags, xfd = XConnectionNumber(dpy); + + if ((flags = fcntl(0, F_GETFL)) == -1) + die("cannot get stdin control flags:"); + if (fcntl(0, F_SETFL, flags | O_NONBLOCK) == -1) + die("cannot set stdin control flags:"); + for (;;) { + FD_ZERO(&fds); + FD_SET(xfd, &fds); + if (!feof(stdin)) + FD_SET(0, &fds); + if (select(xfd + 1, &fds, NULL, NULL, NULL) == -1) + die("cannot multiplex input:"); + if (FD_ISSET(xfd, &fds)) + readevent(); + if (FD_ISSET(0, &fds)) + readstdin(); + } +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/nonblockingstdin.h b/dwm/.dmenu/patch/nonblockingstdin.h new file mode 100644 index 0000000..a0c4dfe --- /dev/null +++ b/dwm/.dmenu/patch/nonblockingstdin.h @@ -0,0 +1 @@ +static void readevent(); \ No newline at end of file diff --git a/dwm/.dmenu/patch/numbers.c b/dwm/.dmenu/patch/numbers.c new file mode 100644 index 0000000..9f9557a --- /dev/null +++ b/dwm/.dmenu/patch/numbers.c @@ -0,0 +1,16 @@ +static char numbers[NUMBERSBUFSIZE] = ""; + +static void +recalculatenumbers() +{ + unsigned int numer = 0, denom = 0; + struct item *item; + if (matchend) { + numer++; + for (item = matchend; item && item->left; item = item->left) + numer++; + } + for (item = items; item && item->text; item++) + denom++; + snprintf(numbers, NUMBERSBUFSIZE, "%d/%d", numer, denom); +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/numbers.h b/dwm/.dmenu/patch/numbers.h new file mode 100644 index 0000000..34d3dbc --- /dev/null +++ b/dwm/.dmenu/patch/numbers.h @@ -0,0 +1,4 @@ +#define NUMBERSMAXDIGITS 100 +#define NUMBERSBUFSIZE (NUMBERSMAXDIGITS * 2) + 1 + +static void recalculatenumbers(); \ No newline at end of file diff --git a/dwm/.dmenu/patch/scroll.c b/dwm/.dmenu/patch/scroll.c new file mode 100644 index 0000000..9021edf --- /dev/null +++ b/dwm/.dmenu/patch/scroll.c @@ -0,0 +1,168 @@ +int +utf8nextchar(const char *str, int len, int i, int inc) +{ + int n; + + for (n = i + inc; n + inc >= 0 && n + inc <= len + && (str[n] & 0xc0) == 0x80; n += inc) + ; + return n; +} + +int +drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align) +{ + int ty; + unsigned int ew; + XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + size_t len; + int utf8strlen, utf8charlen, render = x || y || w || h; + long utf8codepoint = 0; + const char *utf8str; + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; + XftResult result; + int charexists = 0; + int i, n; + + if (!drw || (render && !drw->scheme) || !text || !drw->fonts || textlen <= 0 + || (align != AlignL && align != AlignR)) + return 0; + + if (!render) { + w = ~w; + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); + d = XftDrawCreate(drw->dpy, drw->drawable, + DefaultVisual(drw->dpy, drw->screen), + DefaultColormap(drw->dpy, drw->screen)); + } + + usedfont = drw->fonts; + i = align == AlignL ? 0 : textlen; + x = align == AlignL ? x : x + w; + while (1) { + utf8strlen = 0; + nextfont = NULL; + /* if (align == AlignL) */ + utf8str = text + i; + + while ((align == AlignL && i < textlen) || (align == AlignR && i > 0)) { + if (align == AlignL) { + utf8charlen = utf8decode(text + i, &utf8codepoint, MIN(textlen - i, UTF_SIZ)); + if (!utf8charlen) { + textlen = i; + break; + } + } else { + n = utf8nextchar(text, textlen, i, -1); + utf8charlen = utf8decode(text + n, &utf8codepoint, MIN(textlen - n, UTF_SIZ)); + if (!utf8charlen) { + textlen -= i; + text += i; + i = 0; + break; + } + } + for (curfont = drw->fonts; curfont; curfont = curfont->next) { + charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); + if (charexists) { + if (curfont == usedfont) { + utf8strlen += utf8charlen; + i += align == AlignL ? utf8charlen : -utf8charlen; + } else { + nextfont = curfont; + } + break; + } + } + + if (!charexists || nextfont) + break; + else + charexists = 0; + } + + if (align == AlignR) + utf8str = text + i; + + if (utf8strlen) { + drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); + /* shorten text if necessary */ + if (align == AlignL) { + for (len = utf8strlen; len && ew > w; ) { + len = utf8nextchar(utf8str, len, len, -1); + drw_font_getexts(usedfont, utf8str, len, &ew, NULL); + } + } else { + for (len = utf8strlen; len && ew > w; ) { + n = utf8nextchar(utf8str, len, 0, +1); + utf8str += n; + len -= n; + drw_font_getexts(usedfont, utf8str, len, &ew, NULL); + } + } + + if (len) { + if (render) { + ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; + XftDrawStringUtf8(d, &drw->scheme[ColFg], + usedfont->xfont, align == AlignL ? x : x - ew, ty, (XftChar8 *)utf8str, len); + } + x += align == AlignL ? ew : -ew; + w -= ew; + } + if (len < utf8strlen) + break; + } + + if ((align == AlignR && i <= 0) || (align == AlignL && i >= textlen)) { + break; + } else if (nextfont) { + charexists = 0; + usedfont = nextfont; + } else { + /* Regardless of whether or not a fallback font is found, the + * character must be drawn. */ + charexists = 1; + + fccharset = FcCharSetCreate(); + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts->pattern) { + /* Refer to the comment in xfont_create for more information. */ + die("the first font in the cache must be loaded from a font string."); + } + + fcpattern = FcPatternDuplicate(drw->fonts->pattern); + FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); + FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); + match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { + usedfont = xfont_create(drw, NULL, match); + if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; + } else { + xfont_free(usedfont); + usedfont = drw->fonts; + } + } + } + } + if (d) + XftDrawDestroy(d); + + return x; +} \ No newline at end of file diff --git a/dwm/.dmenu/patch/scroll.h b/dwm/.dmenu/patch/scroll.h new file mode 100644 index 0000000..927df9a --- /dev/null +++ b/dwm/.dmenu/patch/scroll.h @@ -0,0 +1,3 @@ +enum { AlignL, AlignR }; + +int drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align); \ No newline at end of file diff --git a/dwm/.dmenu/patch/xresources.c b/dwm/.dmenu/patch/xresources.c new file mode 100644 index 0000000..cdb1631 --- /dev/null +++ b/dwm/.dmenu/patch/xresources.c @@ -0,0 +1,90 @@ +#include + +void +readxresources(void) +{ + XrmInitialize(); + + char* xrm; + if ((xrm = XResourceManagerString(drw->dpy))) { + char *type; + XrmDatabase xdb = XrmGetStringDatabase(xrm); + XrmValue xval; + + if (XrmGetResource(xdb, "dmenu.font", "*", &type, &xval)) + #if PANGO_PATCH + strcpy(font, xval.addr); + #else + fonts[0] = strdup(xval.addr); + #endif // PANGO_PATCH + #if !PANGO_PATCH + else + fonts[0] = strdup(fonts[0]); + #endif // PANGO_PATCH + if (XrmGetResource(xdb, "dmenu.background", "*", &type, &xval)) + colors[SchemeNorm][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.foreground", "*", &type, &xval)) + colors[SchemeNorm][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.selbackground", "*", &type, &xval)) + colors[SchemeSel][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.selforeground", "*", &type, &xval)) + colors[SchemeSel][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.outbackground", "*", &type, &xval)) + colors[SchemeOut][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.outforeground", "*", &type, &xval)) + colors[SchemeOut][ColFg] = strdup(xval.addr); + #if MORECOLOR_PATCH + if (XrmGetResource(xdb, "dmenu.midbackground", "*", &type, &xval)) + colors[SchemeMid][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.midforeground", "*", &type, &xval)) + colors[SchemeMid][ColFg] = strdup(xval.addr); + #endif // MORECOLOR_PATCH + #if BORDER_PATCH + if (XrmGetResource(xdb, "dmenu.bordercolor", "*", &type, &xval)) + colors[SchemeBorder][ColBg] = strdup(xval.addr); + #endif // BORDER_PATCH + #if HIGHLIGHT_PATCH || FUZZYHIGHLIGHT_PATCH + if (XrmGetResource(xdb, "dmenu.selhlbackground", "*", &type, &xval)) + colors[SchemeSelHighlight][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.selhlforeground", "*", &type, &xval)) + colors[SchemeSelHighlight][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.hlbackground", "*", &type, &xval)) + colors[SchemeNormHighlight][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.hlforeground", "*", &type, &xval)) + colors[SchemeNormHighlight][ColFg] = strdup(xval.addr); + #endif // HIGHLIGHT_PATCH | FUZZYHIGHLIGHT_PATCH + #if HIGHPRIORITY_PATCH + if (XrmGetResource(xdb, "dmenu.hpbackground", "*", &type, &xval)) + colors[SchemeHp][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.hpforeground", "*", &type, &xval)) + colors[SchemeHp][ColFg] = strdup(xval.addr); + #endif // HIGHPRIORITY_PATCH + #if EMOJI_HIGHLIGHT_PATCH + if (XrmGetResource(xdb, "dmenu.hoverbackground", "*", &type, &xval)) + colors[SchemeHover][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.hoverforeground", "*", &type, &xval)) + colors[SchemeHover][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.greenbackground", "*", &type, &xval)) + colors[SchemeGreen][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.greenforeground", "*", &type, &xval)) + colors[SchemeGreen][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.yellowbackground", "*", &type, &xval)) + colors[SchemeYellow][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.yellowforeground", "*", &type, &xval)) + colors[SchemeYellow][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.bluebackground", "*", &type, &xval)) + colors[SchemeBlue][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.blueforeground", "*", &type, &xval)) + colors[SchemeBlue][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.purplebackground", "*", &type, &xval)) + colors[SchemePurple][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.purpleforeground", "*", &type, &xval)) + colors[SchemePurple][ColFg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.redbackground", "*", &type, &xval)) + colors[SchemeRed][ColBg] = strdup(xval.addr); + if (XrmGetResource(xdb, "dmenu.redforeground", "*", &type, &xval)) + colors[SchemeRed][ColFg] = strdup(xval.addr); + #endif // EMOJI_HIGHLIGHT_PATCH + XrmDestroyDatabase(xdb); + } +} \ No newline at end of file diff --git a/dwm/.dmenu/patches.def.h b/dwm/.dmenu/patches.def.h new file mode 100644 index 0000000..e45c715 --- /dev/null +++ b/dwm/.dmenu/patches.def.h @@ -0,0 +1,349 @@ +/* Patches */ + +/* The alpha patch adds transparency for the dmenu window. + * You need to uncomment the corresponding line in config.mk to use the -lXrender library + * when including this patch. + * https://github.com/bakkeby/patches/blob/master/dmenu/dmenu-alpha-5.0_20210725_523aa08.diff + */ +#define ALPHA_PATCH 0 + +/* This adds padding for dmenu in similar fashion to the similarly named patch for dwm. The idea + * is to have dmenu appear on top of the bar when using said patch in dwm. + * https://github.com/bakkeby/patches/wiki/barpadding + */ +#define BARPADDING_PATCH 0 + +/* This patch adds a border around the dmenu window. It is intended to be used with the center + * or xyw patches, to make the menu stand out from similarly coloured windows. + * http://tools.suckless.org/dmenu/patches/border/ + */ +#define BORDER_PATCH 0 + +/* This patch makes dmenu case-insensitive by default, replacing the + * case-insensitive -i option with a case sensitive -s option. + * http://tools.suckless.org/dmenu/patches/case-insensitive/ + */ +#define CASEINSENSITIVE_PATCH 0 + +/* This patch centers dmenu in the middle of the screen. + * https://tools.suckless.org/dmenu/patches/center/ + */ +#define CENTER_PATCH 0 + +/* Minor patch to enable the use of Ctrl+v (XA_PRIMARY) and Ctrl+Shift+v (CLIPBOARD) to paste. + * By default dmenu only supports Ctrl+y and Ctrl+Shift+y to paste. + */ +#define CTRL_V_TO_PASTE_PATCH 0 + +/* This patch adds a flag (-dy) which makes dmenu run the command given to it whenever input + * is changed with the current input as the last argument and update the option list according + * to the output of that command. + * https://tools.suckless.org/dmenu/patches/dynamicoptions/ + */ +#define DYNAMIC_OPTIONS_PATCH 0 + +/* This patch will allow for emojis on the left side with a colored background when selected. + * To test this try running: + * $ echo -e ":b here\n:p there\n:r and here" | ./dmenu -p "Search..." -W 400 -l 20 -i -h -1 + * NB: the original patch came embedded with the the xyw patch, the morecolors patch and the + * line height patch and as such is intended to be combined with these. + * https://tools.suckless.org/dmenu/patches/emoji-highlight/ + */ +#define EMOJI_HIGHLIGHT_PATCH 0 + +/* This patch make it so that fuzzy matches gets highlighted and is therefore meant + * to be used together with the fuzzymatch patch. + * https://tools.suckless.org/dmenu/patches/fuzzyhighlight/ + */ +#define FUZZYHIGHLIGHT_PATCH 0 + +/* This patch adds support for fuzzy-matching to dmenu, allowing users to type non-consecutive + * portions of the string to be matched. + * https://tools.suckless.org/dmenu/patches/fuzzymatch/ + */ +#define FUZZYMATCH_PATCH 0 + +/* Adds fzf-like functionality for dmenu. + * Refer to https://github.com/DAFF0D11/dafmenu/ for documentation and example use cases. + * https://github.com/DAFF0D11/dafmenu/blob/master/patches/dmenu-fzfexpect-5.1.diff + */ +#define FZFEXPECT_PATCH 0 + +/* Allows dmenu's entries to be rendered in a grid by adding a new -g flag to specify + * the number of grid columns. The -g and -l options can be used together to create a + * G columns * L lines grid. + * https://tools.suckless.org/dmenu/patches/grid/ + */ +#define GRID_PATCH 0 + +/* This patch adds the ability to move left and right through a grid. + * This patch depends on the grid patch. + * https://tools.suckless.org/dmenu/patches/gridnav/ + */ +#define GRIDNAV_PATCH 0 + +/* This patch highlights the individual characters of matched text for each dmenu list entry. + * The fuzzy highlight patch takes precedence over this patch. + * https://tools.suckless.org/dmenu/patches/highlight/ + */ +#define HIGHLIGHT_PATCH 0 + +/* This will automatically sort the search result so that high priority items are shown first. + * https://tools.suckless.org/dmenu/patches/highpriority/ + */ +#define HIGHPRIORITY_PATCH 0 + +/* This patch causes dmenu to print out the current text each time a key is pressed. + * https://tools.suckless.org/dmenu/patches/incremental/ + */ +#define INCREMENTAL_PATCH 0 + +/* This patch adds an option to provide preselected text. + * https://tools.suckless.org/dmenu/patches/initialtext/ + */ +#define INITIALTEXT_PATCH 0 + +/* This patch adds a flag which will cause dmenu to select an item immediately if there + * is only one matching option left. + * https://tools.suckless.org/dmenu/patches/instant/ + */ +#define INSTANT_PATCH 0 + +/* This patch adds a '-h' option which sets the minimum height of a dmenu line. This helps + * integrate dmenu with other UI elements that require a particular vertical size. + * http://tools.suckless.org/dmenu/patches/line-height/ + */ +#define LINE_HEIGHT_PATCH 0 + +/* This patch adds a -wm flag which sets override_redirect to false; thus letting your window + * manager manage the dmenu window. + * + * This may be helpful in contexts where you don't want to exclusively bind dmenu or want to + * treat dmenu more as a "window" rather than as an overlay. + * https://tools.suckless.org/dmenu/patches/managed/ + */ +#define MANAGED_PATCH 0 + +/* This patch adds an additional color scheme for highlighting entries adjacent to the current + * selection. + * https://tools.suckless.org/dmenu/patches/morecolor/ + */ +#define MORECOLOR_PATCH 0 + +/* This patch adds basic mouse support for dmenu. + * https://tools.suckless.org/dmenu/patches/mouse-support/ + */ +#define MOUSE_SUPPORT_PATCH 0 + +/* Without this patch when you press Ctrl+Enter dmenu just outputs current item and it is not + * possible to undo that. + * With this patch dmenu will output all selected items only on exit. It is also possible to + * deselect any selected item. + * Also refer to the dmenu_run replacement on the below URL that supports multiple selections. + * + * This patch is not compatible with, and takes precedence over, the json, printinputtext, + * pipeout and non-blocking stdin patches. + * + * https://tools.suckless.org/dmenu/patches/multi-selection/ + */ +#define MULTI_SELECTION_PATCH 0 + +/* This patch provides dmenu the ability for history navigation similar to that of bash. + * + * If you take this patch then it is recommended that you also uncomment the line in the + * dmenu_run script which replaces the exec command. + * + * https://tools.suckless.org/dmenu/patches/navhistory/ + */ +#define NAVHISTORY_PATCH 0 + +/* This patch adds back in the workaround for a BadLength error in the Xft library when color + * glyphs are used. This is for systems that do not have an updated version of the Xft library + * (or generally prefer monochrome fonts). + */ +#define NO_COLOR_EMOJI_PATCH 0 + +/* Adds the -S option to disable sorting menu items after matching. Useful, for example, when menu + * items are sorted by their frequency of use (using an external cache) and the most frequently + * selected items should always appear first regardless of how they were exact, prefix, or + * substring matches. + * https://tools.suckless.org/dmenu/patches/no-sort/ + */ +#define NO_SORT_PATCH 0 + +/* This is a patch to have dmenu read stdin in a non blocking way, making it wait for input both + * from stdin and from X. This means that you can continue feeding dmenu while you type. + * This patch is meant to be used along with the incremental patch, so that you can use stdout + * to feed stdin. + * + * This patch is not compatible with the json and multi-selection patches, both of which takes + * precedence over this patch. + * + * https://tools.suckless.org/dmenu/patches/non_blocking_stdin/ + */ +#define NON_BLOCKING_STDIN_PATCH 0 + +/* Adds text which displays the number of matched and total items in the top right corner of dmenu. + * https://tools.suckless.org/dmenu/patches/numbers/ + */ +#define NUMBERS_PATCH 0 + +/* This patch adds simple markup for dmenu using pango markup. + * This depends on the pango library v1.44 or greater. + * You need to uncomment the corresponding lines in config.mk to use the pango libraries + * when including this patch. + * + * Note that the pango patch is incompatible with the scroll patch and will result in + * compilation errors if both are enabled. + * + * Note that the pango patch does not protect against the BadLength error from Xft + * when color glyphs are used, which means that dmenu will crash if color emoji is used. + * + * If you need color emoji then you may want to install this patched library from the AUR: + * https://aur.archlinux.org/packages/libxft-bgra/ + * + * A long term fix for the libXft library is pending approval of this pull request: + * https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1 + * + * Also see: + * https://developer.gnome.org/pygtk/stable/pango-markup-language.html + * https://github.com/StillANixRookie/dmenu-pango + */ +#define PANGO_PATCH 0 + +/* With this patch dmenu will not directly display the keyboard input, but instead replace + * it with dots. All data from stdin will be ignored. + * https://tools.suckless.org/dmenu/patches/password/ + */ +#define PASSWORD_PATCH 0 + +/* This patch allows the selected text to be piped back out with dmenu. This can be useful if you + * want to display the output of a command on the screen. + * Only text starting with the character '#' is piped out by default. + * + * This patch is not compatible with the json and multi-select patches, both of which takes + * precedence over this one. + * + * https://tools.suckless.org/dmenu/patches/pipeout/ + */ +#define PIPEOUT_PATCH 0 + +/* Lifted from the listfullwidth patch this simple change just avoids colors for the prompt (with + * the -p option or in config.h) by making it use the same style as the rest of the input field. + * The rest of the listfullwidth patch is covered by the vertfull patch. + * https://tools.suckless.org/dmenu/patches/listfullwidth/ + */ +#define PLAIN_PROMPT_PATCH 0 + +/* This patch changes the behaviour of matched items and the Tab key to allow tab completion. + * https://tools.suckless.org/dmenu/patches/prefix-completion/ + */ +#define PREFIXCOMPLETION_PATCH 0 + +/* This patch adds an option -ps to specify an item by providing the index that should be + * pre-selected. + * https://tools.suckless.org/dmenu/patches/preselect/ + */ +#define PRESELECT_PATCH 0 + +/* This patch allows dmenu to print out the 0-based index of matched text instead of the matched + * text itself. This can be useful in cases where you would like to select entries from one array + * of text but index into another, or when you are selecting from an ordered list of non-unique + * items. + * https://tools.suckless.org/dmenu/patches/printindex/ + */ +#define PRINTINDEX_PATCH 0 + +/* This patch adds a flag (-t) which makes Return key to ignore selection and print the input + * text to stdout. The flag basically swaps the functions of Return and Shift+Return hotkeys. + * + * This patch is not compatible with the multi-select and json patches, both of which takes + * precedence over this one. + * + * https://tools.suckless.org/dmenu/patches/printinputtext/ + */ +#define PRINTINPUTTEXT_PATCH 0 + +/* This patch adds a new flag to dmenu with which text input will be rejected if it would + * result in no matching item. + * https://tools.suckless.org/dmenu/patches/reject-no-match/ + */ +#define REJECTNOMATCH_PATCH 0 + +/* The input width used to be relative to the input options prior to commit e1e1de7: + * https://git.suckless.org/dmenu/commit/e1e1de7b3b8399cba90ddca9613f837b2dbef7b9.html + * + * This had a performance hit when using large data sets and was removed in favour of having the + * input width take up 1/3rd of the available space. + * + * This option adds that feature back in with some performance optimisations at the cost of + * accuracy and correctness. + */ +#define RELATIVE_INPUT_WIDTH_PATCH 0 + +/* This patch adds a '-1' option which disables Shift-Return and Ctrl-Return. + * This guarantees that dmenu will only output one item, and that item was read from stdin. + * The original patch used '-r'. This was changed to '-1' to avoid conflict with the incremental + * patch. + * https://tools.suckless.org/dmenu/patches/restrict-return/ + */ +#define RESTRICT_RETURN_PATCH 0 + +/* This patch adds support for text scrolling and no longer appends '...' for long input as + * it can handle long text. + * https://tools.suckless.org/dmenu/patches/scroll/ + */ +#define SCROLL_PATCH 0 + +/* This patch adds -d and -D flags which separates the input into two halves; one half to be + * displayed in dmenu and the other to be printed to stdout. This patch takes precedence over + * the TSV patch. + * https://tools.suckless.org/dmenu/patches/separator/ + */ +#define SEPARATOR_PATCH 0 + +/* This patch allows the symbols, which are printed in dmenu to indicate that either the input + * is too long or there are too many options to be shown in dmenu in one line, to be defined. + * https://tools.suckless.org/dmenu/patches/symbols/ + */ +#define SYMBOLS_PATCH 0 + +/* With this patch dmenu will split input lines at first tab character and only display first + * part, but it will perform matching on and output full lines as usual. + * + * This can be useful if you want to separate data and representation, for example, a music + * player wrapper can display only a track title to user, but still supply full filename to + * the underlying script. + * https://tools.suckless.org/dmenu/patches/tsv/ + */ +#define TSV_PATCH 0 + +/* This patch prevents dmenu from indenting items at the same level as the prompt length. + * https://tools.suckless.org/dmenu/patches/vertfull/ + */ +#define VERTFULL_PATCH 0 + +/* Adds extended window manager hints such as _NET_WM_WINDOW_TYPE and _NET_WM_WINDOW_TYPE_DOCK. + * https://github.com/Baitinq/dmenu/blob/master/patches/dmenu-wm_type.diff + */ +#define WMTYPE_PATCH 0 + +/* This patch adds the ability to configure dmenu via Xresources. At startup, dmenu will read and + * apply the resources named below: + * dmenu.font : font or font set + * dmenu.background : normal background color + * dmenu.foreground : normal foreground color + * dmenu.selbackground : selected background color + * dmenu.selforeground : selected foreground color + * + * See patch/xresources.c for more color settings. + * + * https://tools.suckless.org/dmenu/patches/xresources/ + */ +#define XRESOURCES_PATCH 0 + +/* This patch adds options for specifying dmenu window position and width. + * The center patch takes precedence over the XYW patch if enabled. + * https://tools.suckless.org/dmenu/patches/xyw/ + */ +#define XYW_PATCH 0 diff --git a/dwm/.dmenu/util.h b/dwm/.dmenu/util.h index f633b51..531ab25 100644 --- a/dwm/.dmenu/util.h +++ b/dwm/.dmenu/util.h @@ -1,7 +1,11 @@ /* See LICENSE file for copyright and license details. */ +#ifndef MAX #define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif +#ifndef MIN #define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) void die(const char *fmt, ...); diff --git a/dwm/.dwm/config.def.h b/dwm/.dwm/config.def.h index d8741eb..ed94082 100644 --- a/dwm/.dwm/config.def.h +++ b/dwm/.dwm/config.def.h @@ -7,7 +7,7 @@ static const int corner_radius = 10; #else static const unsigned int borderpx = 1; /* border pixel of windows */ #endif // ROUNDED_CORNERS_PATCH -static const unsigned int snap = 32; /* snap pixel */ +static const unsigned int snap = 28; /* snap pixel */ #if SWALLOW_PATCH static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ #endif // SWALLOW_PATCH @@ -50,7 +50,7 @@ static const int showtab = showtab_auto; /* Default tab b static const int toptab = False; /* False means bottom tab bar */ #endif // TAB_PATCH #if BAR_HEIGHT_PATCH -static const int bar_height = 0; /* 0 means derive from font, >= 1 explicit height */ +static const int bar_height = 32; /* 0 means derive from font, >= 1 explicit height */ #endif // BAR_HEIGHT_PATCH #if BAR_PADDING_PATCH static const int vertpad = 10; /* vertical padding of bar */ @@ -154,11 +154,11 @@ static void (*bartabmonfns[])(Monitor *) = { NULL /* , customlayoutfn */ }; #endif // MONOCLE_LAYOUT #endif // BAR_TABGROUPS_PATCH #if BAR_PANGO_PATCH -static const char font[] = "monospace 10"; +static const char font[] = "monospace 11"; #else -static const char *fonts[] = { "monospace:size=10" }; +static const char *fonts[] = { "SauceCodePro Nerd Font Mono:size=11:antialias=true", "monospace:size=11:antialias=true" }; #endif // BAR_PANGO_PATCH -static const char dmenufont[] = "monospace:size=10"; +static const char dmenufont[] = "SauceCodePro Nerd Font Mono:size=11:antialias=true"; static char c000000[] = "#000000"; // placeholder value @@ -763,31 +763,31 @@ static const char *xkb_layouts[] = { #endif // XKB_PATCH /* key definitions */ -#define MODKEY Mod1Mask +#define MODKEY Mod4Mask #if COMBO_PATCH && SWAPTAGS_PATCH && TAGOTHERMONITOR_PATCH #define TAGKEYS(KEY,TAG) \ { MODKEY, KEY, comboview, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ { MODKEY|ShiftMask, KEY, combotag, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask|ShiftMask, KEY, swaptags, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask, KEY, tagnextmon, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, + { MODKEY|Mod1Mask|ShiftMask, KEY, swaptags, {.ui = 1 << TAG} }, \ + { MODKEY|Mod1Mask, KEY, tagnextmon, {.ui = 1 << TAG} }, \ + { MODKEY|Mod1Mask|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, #elif COMBO_PATCH && SWAPTAGS_PATCH #define TAGKEYS(KEY,TAG) \ { MODKEY, KEY, comboview, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ { MODKEY|ShiftMask, KEY, combotag, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask|ShiftMask, KEY, swaptags, {.ui = 1 << TAG} }, + { MODKEY|Mod1Mask|ShiftMask, KEY, swaptags, {.ui = 1 << TAG} }, #elif COMBO_PATCH && TAGOTHERMONITOR_PATCH #define TAGKEYS(KEY,TAG) \ { MODKEY, KEY, comboview, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ { MODKEY|ShiftMask, KEY, combotag, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask, KEY, tagnextmon, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, + { MODKEY|Mod1Mask, KEY, tagnextmon, {.ui = 1 << TAG} }, \ + { MODKEY|Mod1Mask|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, #elif COMBO_PATCH #define TAGKEYS(KEY,TAG) \ { MODKEY, KEY, comboview, {.ui = 1 << TAG} }, \ @@ -800,24 +800,24 @@ static const char *xkb_layouts[] = { { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask|ShiftMask, KEY, swaptags, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask, KEY, tagnextmon, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, + { MODKEY|Mod1Mask|ShiftMask, KEY, swaptags, {.ui = 1 << TAG} }, \ + { MODKEY|Mod1Mask, KEY, tagnextmon, {.ui = 1 << TAG} }, \ + { MODKEY|Mod1Mask|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, #elif SWAPTAGS_PATCH #define TAGKEYS(KEY,TAG) \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask|ShiftMask, KEY, swaptags, {.ui = 1 << TAG} }, + { MODKEY|Mod1Mask|ShiftMask, KEY, swaptags, {.ui = 1 << TAG} }, #elif TAGOTHERMONITOR_PATCH #define TAGKEYS(KEY,TAG) \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask, KEY, tagnextmon, {.ui = 1 << TAG} }, \ - { MODKEY|Mod4Mask|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, + { MODKEY|Mod1Mask, KEY, tagnextmon, {.ui = 1 << TAG} }, \ + { MODKEY|Mod1Mask|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, #else #define TAGKEYS(KEY,TAG) \ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ @@ -863,7 +863,7 @@ static const char *dmenucmd[] = { #endif // BAR_DMENUMATCHTOP_PATCH NULL }; -static const char *termcmd[] = { "st", NULL }; +static const char *termcmd[] = { "alacritty", NULL }; #if BAR_STATUSCMD_PATCH #if BAR_DWMBLOCKS_PATCH @@ -928,14 +928,14 @@ static const Key keys[] = { { MODKEY, XK_v, switchcol, {0} }, #endif // SWITCHCOL_PATCH #if ROTATESTACK_PATCH - { MODKEY|Mod4Mask, XK_j, rotatestack, {.i = +1 } }, - { MODKEY|Mod4Mask, XK_k, rotatestack, {.i = -1 } }, + { MODKEY|Mod1Mask, XK_j, rotatestack, {.i = +1 } }, + { MODKEY|Mod1Mask, XK_k, rotatestack, {.i = -1 } }, #endif // ROTATESTACK_PATCH #if INPLACEROTATE_PATCH - { MODKEY|Mod4Mask, XK_j, inplacerotate, {.i = +2 } }, // same as rotatestack - { MODKEY|Mod4Mask, XK_k, inplacerotate, {.i = -2 } }, // same as reotatestack - { MODKEY|Mod4Mask|ShiftMask, XK_j, inplacerotate, {.i = +1} }, - { MODKEY|Mod4Mask|ShiftMask, XK_k, inplacerotate, {.i = -1} }, + { MODKEY|Mod1Mask, XK_j, inplacerotate, {.i = +2 } }, // same as rotatestack + { MODKEY|Mod1Mask, XK_k, inplacerotate, {.i = -2 } }, // same as reotatestack + { MODKEY|Mod1Mask|ShiftMask, XK_j, inplacerotate, {.i = +1} }, + { MODKEY|Mod1Mask|ShiftMask, XK_k, inplacerotate, {.i = -1} }, #endif // INPLACEROTATE_PATCH #if PUSH_PATCH || PUSH_NO_MASTER_PATCH { MODKEY|ControlMask, XK_j, pushdown, {0} }, @@ -959,14 +959,14 @@ static const Key keys[] = { { MODKEY|ControlMask|ShiftMask, XK_r, aspectresize, {.i = -24} }, #endif // ASPECTRESIZE_PATCH #if MOVERESIZE_PATCH - { MODKEY|Mod4Mask, XK_Down, moveresize, {.v = "0x 25y 0w 0h" } }, - { MODKEY|Mod4Mask, XK_Up, moveresize, {.v = "0x -25y 0w 0h" } }, - { MODKEY|Mod4Mask, XK_Right, moveresize, {.v = "25x 0y 0w 0h" } }, - { MODKEY|Mod4Mask, XK_Left, moveresize, {.v = "-25x 0y 0w 0h" } }, - { MODKEY|Mod4Mask|ShiftMask, XK_Down, moveresize, {.v = "0x 0y 0w 25h" } }, - { MODKEY|Mod4Mask|ShiftMask, XK_Up, moveresize, {.v = "0x 0y 0w -25h" } }, - { MODKEY|Mod4Mask|ShiftMask, XK_Right, moveresize, {.v = "0x 0y 25w 0h" } }, - { MODKEY|Mod4Mask|ShiftMask, XK_Left, moveresize, {.v = "0x 0y -25w 0h" } }, + { MODKEY|Mod1Mask, XK_Down, moveresize, {.v = "0x 25y 0w 0h" } }, + { MODKEY|Mod1Mask, XK_Up, moveresize, {.v = "0x -25y 0w 0h" } }, + { MODKEY|Mod1Mask, XK_Right, moveresize, {.v = "25x 0y 0w 0h" } }, + { MODKEY|Mod1Mask, XK_Left, moveresize, {.v = "-25x 0y 0w 0h" } }, + { MODKEY|Mod1Mask|ShiftMask, XK_Down, moveresize, {.v = "0x 0y 0w 25h" } }, + { MODKEY|Mod1Mask|ShiftMask, XK_Up, moveresize, {.v = "0x 0y 0w -25h" } }, + { MODKEY|Mod1Mask|ShiftMask, XK_Right, moveresize, {.v = "0x 0y 25w 0h" } }, + { MODKEY|Mod1Mask|ShiftMask, XK_Left, moveresize, {.v = "0x 0y -25w 0h" } }, #endif // MOVERESIZE_PATCH #if MOVESTACK_PATCH { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, @@ -989,22 +989,22 @@ static const Key keys[] = { #endif // INSETS_PATCH { MODKEY, XK_Return, zoom, {0} }, #if VANITYGAPS_PATCH - { MODKEY|Mod4Mask, XK_u, incrgaps, {.i = +1 } }, - { MODKEY|Mod4Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } }, - { MODKEY|Mod4Mask, XK_i, incrigaps, {.i = +1 } }, - { MODKEY|Mod4Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } }, - { MODKEY|Mod4Mask, XK_o, incrogaps, {.i = +1 } }, - { MODKEY|Mod4Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } }, - { MODKEY|Mod4Mask, XK_6, incrihgaps, {.i = +1 } }, - { MODKEY|Mod4Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } }, - { MODKEY|Mod4Mask, XK_7, incrivgaps, {.i = +1 } }, - { MODKEY|Mod4Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } }, - { MODKEY|Mod4Mask, XK_8, incrohgaps, {.i = +1 } }, - { MODKEY|Mod4Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } }, - { MODKEY|Mod4Mask, XK_9, incrovgaps, {.i = +1 } }, - { MODKEY|Mod4Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } }, - { MODKEY|Mod4Mask, XK_0, togglegaps, {0} }, - { MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} }, + { MODKEY|Mod1Mask, XK_u, incrgaps, {.i = +1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } }, + { MODKEY|Mod1Mask, XK_i, incrigaps, {.i = +1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } }, + { MODKEY|Mod1Mask, XK_o, incrogaps, {.i = +1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } }, + { MODKEY|Mod1Mask, XK_6, incrihgaps, {.i = +1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } }, + { MODKEY|Mod1Mask, XK_7, incrivgaps, {.i = +1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } }, + { MODKEY|Mod1Mask, XK_8, incrohgaps, {.i = +1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } }, + { MODKEY|Mod1Mask, XK_9, incrovgaps, {.i = +1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } }, + { MODKEY|Mod1Mask, XK_0, togglegaps, {0} }, + { MODKEY|Mod1Mask|ShiftMask, XK_0, defaultgaps, {0} }, #endif // VANITYGAPS_PATCH #if ALT_TAB_PATCH { Mod1Mask, XK_Tab, alttabstart, {0} }, @@ -1024,16 +1024,16 @@ static const Key keys[] = { { MODKEY|ShiftMask, XK_backslash, shiftview, { .i = +1 } }, #endif // SHIFTVIEW_PATCH #if SHIFTVIEW_CLIENTS_PATCH - { MODKEY|Mod4Mask, XK_Tab, shiftviewclients, { .i = -1 } }, - { MODKEY|Mod4Mask, XK_backslash, shiftviewclients, { .i = +1 } }, + { MODKEY|Mod1Mask, XK_Tab, shiftviewclients, { .i = -1 } }, + { MODKEY|Mod1Mask, XK_backslash, shiftviewclients, { .i = +1 } }, #endif // SHIFTVIEW_CLIENTS_PATCH #if SHIFTBOTH_PATCH { MODKEY|ControlMask, XK_Left, shiftboth, { .i = -1 } }, // note keybinding conflict with focusadjacenttag tagandviewtoleft { MODKEY|ControlMask, XK_Right, shiftboth, { .i = +1 } }, // note keybinding conflict with focusadjacenttag tagandviewtoright #endif // SHIFTBOTH_PATCH #if SHIFTSWAPTAGS_PATCH && SWAPTAGS_PATCH - { MODKEY|Mod4Mask|ShiftMask, XK_Left, shiftswaptags, { .i = -1 } }, - { MODKEY|Mod4Mask|ShiftMask, XK_Right, shiftswaptags, { .i = +1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_Left, shiftswaptags, { .i = -1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_Right, shiftswaptags, { .i = +1 } }, #endif // SHIFTSWAPTAGS_PATCH #if BAR_WINTITLEACTIONS_PATCH { MODKEY|ControlMask, XK_z, showhideclient, {0} }, @@ -1100,7 +1100,7 @@ static const Key keys[] = { { MODKEY|ShiftMask, XK_grave, removescratch, {.ui = 0 } }, #endif // SCRATCHPADS_PATCH | RENAMED_SCRATCHPADS_PATCH #if UNFLOATVISIBLE_PATCH - { MODKEY|Mod4Mask, XK_space, unfloatvisible, {0} }, + { MODKEY|Mod1Mask, XK_space, unfloatvisible, {0} }, { MODKEY|ShiftMask, XK_t, unfloatvisible, {.v = &layouts[0]} }, #endif // UNFLOATVISIBLE_PATCH #if TOGGLEFULLSCREEN_PATCH @@ -1159,12 +1159,12 @@ static const Key keys[] = { { MODKEY|ControlMask, XK_F9, tagall, {.v = "9"} }, #endif // TAGALL_PATCH #if TAGALLMON_PATCH - { MODKEY|Mod4Mask|ShiftMask, XK_comma, tagallmon, {.i = +1 } }, - { MODKEY|Mod4Mask|ShiftMask, XK_period, tagallmon, {.i = -1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_comma, tagallmon, {.i = +1 } }, + { MODKEY|Mod1Mask|ShiftMask, XK_period, tagallmon, {.i = -1 } }, #endif // TAGALLMON_PATCH #if TAGSWAPMON_PATCH - { MODKEY|Mod4Mask|ControlMask, XK_comma, tagswapmon, {.i = +1 } }, - { MODKEY|Mod4Mask|ControlMask, XK_period, tagswapmon, {.i = -1 } }, + { MODKEY|Mod1Mask|ControlMask, XK_comma, tagswapmon, {.i = +1 } }, + { MODKEY|Mod1Mask|ControlMask, XK_period, tagswapmon, {.i = -1 } }, #endif // TAGSWAPMON_PATCH #if BAR_ALTERNATIVE_TAGS_PATCH { MODKEY, XK_n, togglealttag, {0} }, @@ -1177,10 +1177,10 @@ static const Key keys[] = { { MODKEY|ControlMask, XK_Down, switchtag, { .ui = SWITCHTAG_DOWN | SWITCHTAG_VIEW } }, { MODKEY|ControlMask, XK_Right, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_VIEW } }, { MODKEY|ControlMask, XK_Left, switchtag, { .ui = SWITCHTAG_LEFT | SWITCHTAG_VIEW } }, - { MODKEY|Mod4Mask, XK_Up, switchtag, { .ui = SWITCHTAG_UP | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, - { MODKEY|Mod4Mask, XK_Down, switchtag, { .ui = SWITCHTAG_DOWN | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, - { MODKEY|Mod4Mask, XK_Right, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, - { MODKEY|Mod4Mask, XK_Left, switchtag, { .ui = SWITCHTAG_LEFT | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, + { MODKEY|Mod1Mask, XK_Up, switchtag, { .ui = SWITCHTAG_UP | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, + { MODKEY|Mod1Mask, XK_Down, switchtag, { .ui = SWITCHTAG_DOWN | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, + { MODKEY|Mod1Mask, XK_Right, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, + { MODKEY|Mod1Mask, XK_Left, switchtag, { .ui = SWITCHTAG_LEFT | SWITCHTAG_TAG | SWITCHTAG_VIEW } }, #endif // BAR_TAGGRID_PATCH #if MOVEPLACE_PATCH { MODKEY, XK_KP_7, moveplace, {.ui = WIN_NW }}, /* XK_KP_Home, */ diff --git a/htop/.config/htop/htoprc b/htop/.config/htop/htoprc index 04c0a39..ebcd3b7 100644 --- a/htop/.config/htop/htoprc +++ b/htop/.config/htop/htoprc @@ -1,19 +1,17 @@ # Beware! This file is rewritten by htop when settings are changed in the interface. # The parser is also very primitive, and not human-friendly. -htop_version=3.1.2 -config_reader_min_version=2 +htop_version=3.2.2 +config_reader_min_version=3 fields=0 48 17 18 38 39 40 2 46 47 49 1 -sort_key=46 -sort_direction=1 -tree_sort_key=38 -tree_sort_direction=-1 hide_kernel_threads=1 hide_userland_threads=0 +hide_running_in_container=0 shadow_other_users=0 show_thread_names=0 show_program_path=1 highlight_base_name=1 highlight_deleted_exe=1 +shadow_distribution_path_prefix=0 highlight_megabytes=1 highlight_threads=1 highlight_changes=1 @@ -21,10 +19,8 @@ highlight_changes_delay_secs=5 find_comm_in_cmdline=1 strip_exe_from_cmdline=1 show_merged_command=1 -tree_view=1 -tree_view_always_by_pid=0 -all_branches_collapsed=1 header_margin=1 +screen_tabs=0 detailed_cpu_time=0 cpu_count_from_one=0 show_cpu_usage=1 @@ -44,3 +40,26 @@ column_meters_1=Clock LoadAverage Uptime Battery Memory column_meter_modes_1=2 2 2 2 3 column_meters_2=AllCPUs4 DiskIO column_meter_modes_2=3 3 +tree_view=1 +sort_key=46 +tree_sort_key=47 +sort_direction=1 +tree_sort_direction=-1 +tree_view_always_by_pid=0 +all_branches_collapsed=1 +screen:Main=PID USER PRIORITY NICE M_VIRT M_RESIDENT M_SHARE STATE PERCENT_CPU PERCENT_MEM TIME Command +.sort_key=PERCENT_CPU +.tree_sort_key=PERCENT_MEM +.tree_view=1 +.tree_view_always_by_pid=0 +.sort_direction=1 +.tree_sort_direction=-1 +.all_branches_collapsed=1 +screen:I/O=PID USER IO_PRIORITY IO_RATE IO_READ_RATE IO_WRITE_RATE PERCENT_SWAP_DELAY PERCENT_IO_DELAY Command +.sort_key=IO_RATE +.tree_sort_key=PID +.tree_view=0 +.tree_view_always_by_pid=0 +.sort_direction=-1 +.tree_sort_direction=1 +.all_branches_collapsed=0