2023-04-02 01:49:58 +02:00
|
|
|
/* spmenu - fancy dynamic menu
|
2023-03-16 10:09:51 +01:00
|
|
|
* See LICENSE file for copyright and license details.
|
|
|
|
*/
|
2023-01-20 23:17:30 +01:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <locale.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
2023-06-02 18:37:51 +02:00
|
|
|
#include <signal.h>
|
|
|
|
#include <fcntl.h>
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-05-22 01:20:54 +02:00
|
|
|
// set version
|
|
|
|
#ifndef VERSION
|
|
|
|
#define VERSION "unknown"
|
|
|
|
#endif
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// check if we should enable right to left language support
|
2023-03-08 21:12:37 +01:00
|
|
|
#ifndef RTL
|
2023-01-22 11:22:33 +01:00
|
|
|
#define USERTL 0
|
2023-02-28 15:51:32 +01:00
|
|
|
#else
|
|
|
|
#define USERTL 1
|
2023-01-22 11:22:33 +01:00
|
|
|
#endif
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// check if we should enable image support
|
2023-03-08 21:12:37 +01:00
|
|
|
#ifndef IMAGE
|
2023-02-26 16:38:26 +01:00
|
|
|
#define USEIMAGE 0
|
|
|
|
#else
|
|
|
|
#define USEIMAGE 1
|
|
|
|
#endif
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// check if we should enable multimonitor support using libXinerama
|
2023-03-28 21:46:23 +02:00
|
|
|
#ifndef XINERAMA
|
2023-02-28 15:51:32 +01:00
|
|
|
#define USEXINERAMA 0
|
2023-03-28 21:46:23 +02:00
|
|
|
#else
|
|
|
|
#define USEXINERAMA 1
|
2023-02-28 15:51:32 +01:00
|
|
|
#endif
|
|
|
|
|
2023-04-04 21:39:38 +02:00
|
|
|
// check if we should enable config file support using libconfig
|
|
|
|
#ifndef CONFIG
|
|
|
|
#define USECONFIG 0
|
|
|
|
#else
|
|
|
|
#define USECONFIG 1
|
|
|
|
#endif
|
|
|
|
|
2023-05-06 22:01:28 +02:00
|
|
|
// check if we should enable .Xresources support
|
|
|
|
#ifndef XRESOURCES
|
|
|
|
#define USEXRESOURCES 0
|
|
|
|
#else
|
|
|
|
#define USEXRESOURCES 1
|
|
|
|
#endif
|
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
// check if we should enable Wayland support
|
|
|
|
#ifndef WAYLAND
|
|
|
|
#define USEWAYLAND 0
|
|
|
|
#else
|
|
|
|
#define USEWAYLAND 1
|
|
|
|
#endif
|
|
|
|
|
2023-06-05 17:16:26 +02:00
|
|
|
// check if we should enable X11 support
|
|
|
|
#ifndef X11
|
|
|
|
#define USEX 0
|
|
|
|
#else
|
|
|
|
#define USEX 1
|
|
|
|
#endif
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// include fribidi used for right to left language support
|
2023-02-28 15:51:32 +01:00
|
|
|
#if USERTL
|
|
|
|
#include <fribidi.h>
|
|
|
|
#endif
|
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// include libraries used for image support
|
2023-02-26 05:13:40 +01:00
|
|
|
#if USEIMAGE
|
|
|
|
#include <errno.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <Imlib2.h>
|
|
|
|
#include <openssl/md5.h>
|
2023-03-08 21:12:37 +01:00
|
|
|
#endif
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// include macros and other defines
|
|
|
|
#include "libs/define.c"
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
// mode
|
2023-05-22 01:20:54 +02:00
|
|
|
static int curMode; // 0 is command mode
|
|
|
|
static int allowkeys; // whether or not to interpret a keypress as an insertion
|
2023-05-06 14:29:45 +02:00
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// various headers
|
2023-06-12 02:28:19 +02:00
|
|
|
#include "libs/draw/draw.h"
|
2023-06-12 03:54:40 +02:00
|
|
|
#include "libs/main.h"
|
2023-03-26 16:42:11 +02:00
|
|
|
#include "libs/draw.h"
|
2023-03-24 03:14:24 +01:00
|
|
|
#include "libs/stream.h"
|
2023-02-26 05:13:40 +01:00
|
|
|
#include "libs/schemes.h"
|
|
|
|
#include "libs/arg.h"
|
2023-05-23 22:14:24 +02:00
|
|
|
#include "libs/x11/inc.h" // include x11
|
2023-06-02 18:37:51 +02:00
|
|
|
#include "libs/wl/inc.h" // include wayland
|
2023-03-09 10:10:29 +01:00
|
|
|
#include "libs/sort.h"
|
2023-03-31 12:42:15 +02:00
|
|
|
#include "libs/history.h"
|
2023-02-25 17:44:52 +01:00
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// text
|
2023-06-12 03:39:29 +02:00
|
|
|
static char modetext[64] = "";
|
2023-03-16 10:09:51 +01:00
|
|
|
static char text[BUFSIZ] = "";
|
2023-01-20 23:17:30 +01:00
|
|
|
static char numbers[NUMBERSBUFSIZE] = "";
|
2023-03-16 10:09:51 +01:00
|
|
|
|
|
|
|
// keybinds
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEX
|
2023-01-21 22:12:58 +01:00
|
|
|
static int numlockmask = 0;
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-04-20 21:22:45 +02:00
|
|
|
static int capslockstate = 0;
|
2023-03-16 10:09:51 +01:00
|
|
|
|
2023-05-22 01:20:54 +02:00
|
|
|
static int bh, mw, mh; // height of each item, menu width, menu height
|
|
|
|
static int reallines = 0; // temporary integer which holds lines
|
|
|
|
static int inputw = 0; // input width
|
|
|
|
static int promptw; // prompt width
|
|
|
|
static int plw = 0; // powerline width
|
2023-03-16 17:25:39 +01:00
|
|
|
static int lrpad; // sum of left and right padding
|
2023-05-22 01:20:54 +02:00
|
|
|
static int vp; // vertical padding for bar
|
|
|
|
static int sp; // side padding for bar
|
2023-04-29 16:08:00 +02:00
|
|
|
static int cursorstate = 1; // cursor state
|
2023-05-07 15:33:09 +02:00
|
|
|
static int itemnumber = 0; // item number
|
2023-01-20 23:17:30 +01:00
|
|
|
static size_t cursor;
|
2023-05-07 01:41:30 +02:00
|
|
|
static struct item *items = NULL, *backup_items, *list_items;
|
2023-05-22 01:20:54 +02:00
|
|
|
static struct item *matches, *matchend; // matches, final match
|
|
|
|
static struct item *prev, *curr, *next, *sel; // previous, current, next, selected
|
|
|
|
static int hplength = 0; // high priority
|
|
|
|
static char **hpitems = NULL; // high priority
|
2023-05-16 18:54:26 +02:00
|
|
|
static int *sel_index = NULL;
|
|
|
|
static unsigned int sel_size = 0;
|
2023-06-02 19:00:09 +02:00
|
|
|
static int protocol_override = 0;
|
2023-05-22 01:20:54 +02:00
|
|
|
static int itemn = 0; // item number
|
2023-02-26 05:13:40 +01:00
|
|
|
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEX
|
2023-05-23 22:14:24 +02:00
|
|
|
static char *embed; // X11 embed
|
|
|
|
static int screen; // screen
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-05-23 22:14:24 +02:00
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// item struct
|
|
|
|
struct item {
|
2023-05-08 23:00:45 +02:00
|
|
|
char *text;
|
2023-03-24 03:48:56 +01:00
|
|
|
char *clntext;
|
2023-05-08 23:00:45 +02:00
|
|
|
#if USEIMAGE
|
2023-03-16 10:09:51 +01:00
|
|
|
char *image;
|
2023-05-08 23:00:45 +02:00
|
|
|
#endif
|
2023-03-16 10:09:51 +01:00
|
|
|
char *ex;
|
2023-05-08 23:00:45 +02:00
|
|
|
struct item *left, *right;
|
2023-03-16 10:09:51 +01:00
|
|
|
int hp;
|
2023-05-06 23:29:41 +02:00
|
|
|
int index;
|
2023-05-08 23:00:45 +02:00
|
|
|
double distance;
|
2023-03-16 10:09:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// image globals
|
2023-03-09 17:26:56 +01:00
|
|
|
#if USEIMAGE
|
2023-03-04 14:37:14 +01:00
|
|
|
static int flip = 0;
|
2023-03-09 17:26:56 +01:00
|
|
|
static int needredraw = 1;
|
|
|
|
static int longestedge = 0;
|
2023-03-03 21:18:25 +01:00
|
|
|
static int imagew = 0;
|
|
|
|
static int imageh = 0;
|
|
|
|
static int imageg = 0;
|
2023-05-14 00:10:24 +02:00
|
|
|
static int ow = 0;
|
|
|
|
static int oh = 0;
|
2023-03-16 10:09:51 +01:00
|
|
|
#endif
|
2023-05-14 00:10:24 +02:00
|
|
|
static int fullscreen = 0;
|
2023-03-03 21:18:25 +01:00
|
|
|
|
2023-03-16 14:56:41 +01:00
|
|
|
// set an integer to 1 if we have rtl enabled, this saves a lot of lines and duplicate code
|
2023-03-02 17:51:25 +01:00
|
|
|
#if USERTL
|
|
|
|
static int isrtl = 1;
|
|
|
|
#else
|
|
|
|
static int isrtl = 0;
|
|
|
|
#endif
|
|
|
|
|
2023-04-25 09:56:11 +02:00
|
|
|
static int ignoreconfkeys = 0; // can be set globally if you don't want to override keybinds with config file keys
|
|
|
|
static int ignoreglobalkeys = 0; // should be set in the config file, if 1, the Keys keys array is ignored
|
2023-04-25 16:42:15 +02:00
|
|
|
static int ignoreconfmouse = 0; // same for mouse
|
|
|
|
static int ignoreglobalmouse = 0; // same for mouse
|
2023-04-25 09:56:11 +02:00
|
|
|
|
2023-03-16 10:09:51 +01:00
|
|
|
// colors
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEX
|
2023-05-24 07:36:40 +02:00
|
|
|
static int useargb;
|
2023-01-20 23:17:30 +01:00
|
|
|
static int depth;
|
2023-05-24 07:36:40 +02:00
|
|
|
static Visual *visual;
|
2023-01-20 23:17:30 +01:00
|
|
|
static Colormap cmap;
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-01-20 23:17:30 +01:00
|
|
|
static Drw *drw;
|
|
|
|
|
2023-03-16 17:25:39 +01:00
|
|
|
// declare functions
|
2023-05-16 18:54:26 +02:00
|
|
|
static int is_selected(size_t index);
|
2023-02-28 23:03:35 +01:00
|
|
|
static void calcoffsets(void);
|
2023-03-02 11:40:52 +01:00
|
|
|
static void recalculatenumbers(void);
|
2023-03-06 21:03:06 +01:00
|
|
|
static void insert(const char *str, ssize_t n);
|
|
|
|
static void cleanup(void);
|
|
|
|
static void navigatehistfile(int dir);
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEX
|
2023-03-08 18:20:15 +01:00
|
|
|
static void pastesel(void);
|
2023-06-05 17:16:26 +02:00
|
|
|
static void grabfocus(void);
|
|
|
|
#endif
|
2023-06-02 18:37:51 +02:00
|
|
|
static void resizeclient(void);
|
|
|
|
static void get_width(void);
|
2023-06-11 16:46:36 +02:00
|
|
|
static void get_mh(void);
|
2023-06-05 17:16:26 +02:00
|
|
|
static void set_mode(void);
|
2023-06-02 18:37:51 +02:00
|
|
|
static void handle(void);
|
2023-03-13 21:21:40 +01:00
|
|
|
static void appenditem(struct item *item, struct item **list, struct item **last);
|
2023-03-08 17:20:32 +01:00
|
|
|
static int max_textw(void);
|
2023-03-16 14:56:41 +01:00
|
|
|
static size_t nextrune(int inc);
|
2023-05-23 22:14:24 +02:00
|
|
|
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;
|
2023-02-25 17:44:52 +01:00
|
|
|
|
2023-05-07 01:41:30 +02:00
|
|
|
static char **list;
|
|
|
|
static size_t listsize;
|
|
|
|
static int listcount;
|
|
|
|
static int listchanged = 0;
|
|
|
|
|
2023-06-05 17:16:26 +02:00
|
|
|
// clicks
|
|
|
|
enum {
|
|
|
|
ClickWindow,
|
|
|
|
ClickPrompt,
|
|
|
|
ClickInput,
|
|
|
|
ClickLArrow,
|
|
|
|
ClickItem,
|
|
|
|
ClickSelItem,
|
|
|
|
ClickRArrow,
|
|
|
|
ClickNumber,
|
|
|
|
ClickCaps,
|
|
|
|
ClickMode,
|
|
|
|
};
|
|
|
|
|
2023-03-16 14:56:41 +01:00
|
|
|
// user configuration
|
2023-06-09 10:23:10 +02:00
|
|
|
#include "libs/options.h"
|
|
|
|
#include "libs/keybinds.h"
|
|
|
|
#include "libs/mouse.h"
|
2023-03-06 16:23:03 +01:00
|
|
|
|
2023-06-05 17:16:26 +02:00
|
|
|
static char capstext[16];
|
2023-04-04 21:39:38 +02:00
|
|
|
static char *fonts[] = { font };
|
|
|
|
|
2023-05-23 22:14:24 +02:00
|
|
|
// color array
|
|
|
|
#include "libs/colors.h"
|
|
|
|
|
2023-04-04 17:18:16 +02:00
|
|
|
// config file
|
2023-04-04 21:39:38 +02:00
|
|
|
#if USECONFIG
|
2023-04-04 17:18:16 +02:00
|
|
|
#include "libs/conf/config.h"
|
|
|
|
#include "libs/conf/config.c"
|
2023-04-04 21:39:38 +02:00
|
|
|
#endif
|
2023-03-14 11:42:56 +01:00
|
|
|
|
2023-03-13 21:21:40 +01:00
|
|
|
// include functions
|
2023-02-26 05:13:40 +01:00
|
|
|
#include "libs/img.h"
|
|
|
|
#include "libs/img.c"
|
|
|
|
#include "libs/rtl.h"
|
|
|
|
#include "libs/rtl.c"
|
2023-03-09 10:10:29 +01:00
|
|
|
#include "libs/sort.c"
|
2023-03-02 11:40:52 +01:00
|
|
|
#include "libs/draw.c"
|
2023-03-02 12:03:26 +01:00
|
|
|
#include "libs/schemes.c"
|
2023-03-02 14:53:48 +01:00
|
|
|
#include "libs/argv.h"
|
|
|
|
#include "libs/argv.c"
|
2023-03-13 22:45:04 +01:00
|
|
|
#include "libs/match.h"
|
|
|
|
#include "libs/match.c"
|
2023-05-23 22:42:07 +02:00
|
|
|
|
|
|
|
// include x11 code
|
|
|
|
#include "libs/x11/inc.c"
|
2023-06-02 18:37:51 +02:00
|
|
|
#include "libs/wl/inc.c"
|
2023-05-23 22:42:07 +02:00
|
|
|
|
|
|
|
// include more functions
|
2023-03-31 12:42:15 +02:00
|
|
|
#include "libs/history.c"
|
2023-03-13 22:45:04 +01:00
|
|
|
#include "libs/arg.c"
|
2023-03-24 03:14:24 +01:00
|
|
|
#include "libs/stream.c"
|
2023-02-25 17:44:52 +01:00
|
|
|
|
2023-05-16 18:54:26 +02:00
|
|
|
int is_selected(size_t index) {
|
|
|
|
for (int i = 0; i < sel_size; i++) {
|
|
|
|
if (sel_index[i] == index) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void appenditem(struct item *item, struct item **list, struct item **last) {
|
2023-05-08 23:00:45 +02:00
|
|
|
if (*last)
|
|
|
|
(*last)->right = item;
|
|
|
|
else
|
|
|
|
*list = item;
|
|
|
|
|
|
|
|
item->left = *last;
|
|
|
|
item->right = NULL;
|
|
|
|
*last = item;
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void recalculatenumbers(void) {
|
2023-05-16 21:16:51 +02:00
|
|
|
unsigned int numer = 0, denom = 0, selected = 0;
|
2023-05-08 23:00:45 +02:00
|
|
|
struct item *item;
|
|
|
|
if (matchend) {
|
|
|
|
numer++;
|
2023-03-31 12:42:15 +02:00
|
|
|
|
|
|
|
// walk through items that match and add to numer
|
2023-05-08 23:00:45 +02:00
|
|
|
for (item = matchend; item && item->left; item = item->left)
|
|
|
|
numer++;
|
|
|
|
}
|
2023-03-31 12:42:15 +02:00
|
|
|
|
|
|
|
// walk through all items, matching or not and add to denom
|
2023-05-08 23:00:45 +02:00
|
|
|
for (item = items; item && item->text; item++)
|
|
|
|
denom++;
|
2023-03-31 12:42:15 +02:00
|
|
|
|
2023-05-16 21:16:51 +02:00
|
|
|
for (int i = 0; i < sel_size; i++) {
|
|
|
|
if (sel_index[i] == -1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
selected++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selected) {
|
|
|
|
snprintf(numbers, NUMBERSBUFSIZE, "%d/%d/%d", numer, denom, selected);
|
|
|
|
} else {
|
|
|
|
snprintf(numbers, NUMBERSBUFSIZE, "%d/%d", numer, denom);
|
|
|
|
}
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void calcoffsets(void) {
|
2023-05-08 23:00:45 +02:00
|
|
|
int i, n;
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
if (lines > 0)
|
|
|
|
n = lines * columns * bh;
|
|
|
|
else { // no lines, therefore the size of items must be decreased to fit the menu elements
|
2023-03-02 17:51:25 +01:00
|
|
|
int numberWidth = 0;
|
|
|
|
int modeWidth = 0;
|
|
|
|
int larrowWidth = 0;
|
|
|
|
int rarrowWidth = 0;
|
2023-04-21 09:49:38 +02:00
|
|
|
int capsWidth = 0;
|
2023-03-02 17:51:25 +01:00
|
|
|
|
2023-03-02 18:25:28 +01:00
|
|
|
if (!hidematchcount) numberWidth = pango_numbers ? TEXTWM(numbers) : TEXTW(numbers);
|
|
|
|
if (!hidemode) modeWidth = pango_mode ? TEXTWM(modetext) : TEXTW(modetext);
|
|
|
|
if (!hidelarrow) larrowWidth = pango_leftarrow ? TEXTWM(leftarrow) : TEXTW(leftarrow);
|
|
|
|
if (!hiderarrow) rarrowWidth = pango_rightarrow ? TEXTWM(rightarrow) : TEXTW(rightarrow);
|
2023-04-21 09:49:38 +02:00
|
|
|
if (!hidecaps) capsWidth = pango_caps ? TEXTWM(capstext) : TEXTW(capstext);
|
2023-03-02 17:51:25 +01:00
|
|
|
|
2023-04-21 09:49:38 +02:00
|
|
|
if (!strcmp(capstext, ""))
|
|
|
|
capsWidth = 0;
|
|
|
|
|
2023-06-18 18:05:42 +02:00
|
|
|
n = mw - (promptw + inputw + larrowWidth + rarrowWidth + modeWidth + numberWidth + capsWidth + menumarginh);
|
2023-03-02 17:51:25 +01:00
|
|
|
}
|
2023-03-16 16:54:36 +01:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
// calculate which items will begin the next page
|
|
|
|
for (i = 0, next = curr; next; next = next->right)
|
2023-06-18 21:15:32 +02:00
|
|
|
if ((i += (lines > 0) ? bh : MIN(TEXTWM(next->text) + (powerlineitems ? !lines ? 2 * plw : 0 : 0), n)) > n)
|
2023-05-08 23:00:45 +02:00
|
|
|
break;
|
2023-03-31 12:42:15 +02:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
// calculate which items will begin the previous page
|
|
|
|
for (i = 0, prev = curr; prev && prev->left; prev = prev->left)
|
2023-06-18 21:15:32 +02:00
|
|
|
if ((i += (lines > 0) ? bh : MIN(TEXTWM(prev->left->text) + (powerlineitems ? !lines ? 2 * plw : 0 : 0), n)) > n)
|
2023-05-08 23:00:45 +02:00
|
|
|
break;
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
int max_textw(void) {
|
2023-05-08 23:00:45 +02:00
|
|
|
int len = 0;
|
2023-03-31 12:42:15 +02:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
for (struct item *item = items; item && item->text; item++)
|
|
|
|
len = MAX(TEXTW(item->text), len);
|
2023-03-31 12:42:15 +02:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
return len;
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void cleanup(void) {
|
2023-05-08 23:00:45 +02:00
|
|
|
size_t i;
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
#if USEIMAGE
|
2023-03-31 12:42:15 +02:00
|
|
|
cleanupimage(); // function frees images
|
2023-05-08 23:00:45 +02:00
|
|
|
#endif
|
2023-03-02 11:46:44 +01:00
|
|
|
|
2023-03-31 12:42:15 +02:00
|
|
|
// free high priority items
|
2023-03-09 11:56:44 +01:00
|
|
|
for (i = 0; i < hplength; ++i)
|
2023-05-08 23:00:45 +02:00
|
|
|
free(hpitems[i]);
|
2023-03-09 11:56:44 +01:00
|
|
|
|
2023-03-31 12:42:15 +02:00
|
|
|
// free drawing and close the display
|
2023-05-08 23:00:45 +02:00
|
|
|
drw_free(drw);
|
2023-06-02 18:37:51 +02:00
|
|
|
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEX
|
2023-06-02 18:37:51 +02:00
|
|
|
if (!protocol) {
|
|
|
|
cleanup_x11(dpy);
|
|
|
|
}
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-06-02 18:37:51 +02:00
|
|
|
|
2023-05-16 18:54:26 +02:00
|
|
|
free(sel_index);
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
char * cistrstr(const char *h, const char *n) {
|
2023-05-08 23:00:45 +02:00
|
|
|
size_t i;
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
if (!n[0])
|
|
|
|
return (char *)h;
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
for (; *h; ++h) {
|
|
|
|
for (i = 0; n[i] && tolower((unsigned char)n[i]) ==
|
|
|
|
tolower((unsigned char)h[i]); ++i);
|
2023-03-31 12:42:15 +02:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
if (n[i] == '\0')
|
|
|
|
return (char *)h;
|
|
|
|
}
|
2023-03-31 12:42:15 +02:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
return NULL;
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
|
|
|
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEX
|
2023-05-06 14:29:45 +02:00
|
|
|
void grabfocus(void) {
|
2023-05-24 07:36:40 +02:00
|
|
|
grabfocus_x11();
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
void insert(const char *str, ssize_t n) {
|
2023-05-08 23:00:45 +02:00
|
|
|
if (strlen(text) + n > sizeof text - 1)
|
|
|
|
return;
|
2023-03-31 12:42:15 +02:00
|
|
|
|
2023-05-09 19:30:01 +02:00
|
|
|
static char l[BUFSIZ] = "";
|
|
|
|
if (requirematch) memcpy(l, text, BUFSIZ);
|
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
// 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));
|
2023-03-31 12:42:15 +02:00
|
|
|
|
|
|
|
// update cursor
|
2023-05-08 23:00:45 +02:00
|
|
|
if (n > 0 && str && n)
|
|
|
|
memcpy(&text[cursor], str, n);
|
2023-03-31 12:42:15 +02:00
|
|
|
|
|
|
|
// add to cursor position and continue matching
|
2023-05-08 23:00:45 +02:00
|
|
|
cursor += n;
|
|
|
|
match();
|
2023-05-09 19:30:01 +02:00
|
|
|
|
|
|
|
if (!matches && requirematch) {
|
|
|
|
memcpy(text, l, BUFSIZ);
|
|
|
|
cursor -= n;
|
|
|
|
match();
|
|
|
|
}
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
|
|
|
|
2023-05-06 14:29:45 +02:00
|
|
|
size_t nextrune(int inc) {
|
2023-05-08 23:00:45 +02:00
|
|
|
ssize_t n;
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
// return location of next utf8 rune in the given direction (+1 or -1)
|
|
|
|
for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc)
|
2023-03-31 12:42:15 +02:00
|
|
|
;
|
2023-05-08 23:00:45 +02:00
|
|
|
return n;
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
|
|
|
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEX
|
2023-05-06 14:29:45 +02:00
|
|
|
void pastesel(void) {
|
2023-06-02 18:37:51 +02:00
|
|
|
if (!protocol) {
|
|
|
|
pastesel_x11();
|
|
|
|
}
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
void resizeclient(void) {
|
|
|
|
#if USEWAYLAND
|
|
|
|
if (protocol) {
|
|
|
|
resizeclient_wl(&state);
|
|
|
|
} else {
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEX
|
2023-06-02 18:37:51 +02:00
|
|
|
resizeclient_x11();
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-06-02 18:37:51 +02:00
|
|
|
}
|
2023-06-05 17:16:26 +02:00
|
|
|
#elif USEX
|
2023-06-02 18:37:51 +02:00
|
|
|
resizeclient_x11();
|
|
|
|
#endif
|
|
|
|
}
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
void get_width(void) {
|
|
|
|
inputw = mw / 3;
|
|
|
|
}
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-06-11 16:46:36 +02:00
|
|
|
void get_mh(void) {
|
|
|
|
mh = (lines + 1) * bh;
|
|
|
|
mh += 2 * menumarginv;
|
2023-06-11 19:32:02 +02:00
|
|
|
|
|
|
|
if ((hideprompt && hideinput && hidemode && hidematchcount && hidecaps) && lines) {
|
|
|
|
mh -= bh;
|
|
|
|
}
|
2023-06-11 16:46:36 +02:00
|
|
|
}
|
|
|
|
|
2023-06-05 17:16:26 +02:00
|
|
|
void set_mode(void) {
|
|
|
|
if (!type) { // no typing allowed, require normal mode
|
|
|
|
mode = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set default mode, must be done before the event loop or keybindings will not work
|
|
|
|
if (mode) {
|
|
|
|
curMode = 1;
|
|
|
|
allowkeys = 1;
|
|
|
|
|
2023-06-12 03:39:29 +02:00
|
|
|
sp_strncpy(modetext, instext, sizeof(modetext));
|
2023-06-05 17:16:26 +02:00
|
|
|
} else {
|
|
|
|
curMode = 0;
|
|
|
|
allowkeys = !curMode;
|
|
|
|
|
2023-06-12 03:39:29 +02:00
|
|
|
sp_strncpy(modetext, normtext, sizeof(modetext));
|
2023-06-05 17:16:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
void handle(void) {
|
|
|
|
if (!protocol) {
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEX
|
2023-06-02 18:37:51 +02:00
|
|
|
handle_x11();
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
if (!drw_font_create(drw, fonts, LENGTH(fonts))) {
|
|
|
|
die("no fonts could be loaded.");
|
|
|
|
}
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
loadhistory(); // read history entries
|
2023-06-08 19:40:30 +02:00
|
|
|
#if USEIMAGE
|
2023-06-02 18:37:51 +02:00
|
|
|
store_image_vars();
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
// fast (-f) means we grab keyboard before reading standard input
|
|
|
|
if (fast && !isatty(0)) {
|
|
|
|
grabkeyboard_x11();
|
|
|
|
readstdin();
|
|
|
|
} else {
|
|
|
|
readstdin();
|
|
|
|
grabkeyboard_x11();
|
|
|
|
}
|
|
|
|
|
|
|
|
set_mode();
|
|
|
|
|
|
|
|
init_appearance(); // init colorschemes by reading arrays
|
|
|
|
setupdisplay_x11(); // set up display and create window
|
|
|
|
eventloop_x11(); // function is a loop which checks X11 events and calls other functions accordingly
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-06-02 18:37:51 +02:00
|
|
|
#if USEWAYLAND
|
2023-05-08 23:00:45 +02:00
|
|
|
} else {
|
2023-06-02 18:37:51 +02:00
|
|
|
loadhistory();
|
2023-06-05 17:16:26 +02:00
|
|
|
#if USEIMAGE
|
2023-06-02 18:37:51 +02:00
|
|
|
store_image_vars();
|
2023-06-17 15:38:22 +02:00
|
|
|
setimageopts();
|
2023-06-05 17:16:26 +02:00
|
|
|
#endif
|
2023-06-02 18:37:51 +02:00
|
|
|
|
2023-06-03 15:37:48 +02:00
|
|
|
// Disable some X11 only features
|
|
|
|
menupaddingv = menupaddingh = 0;
|
|
|
|
xpos = ypos = 0;
|
|
|
|
borderwidth = 0;
|
|
|
|
managed = 0;
|
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
drw = drw_create_wl(protocol);
|
|
|
|
|
|
|
|
if (!drw_font_create(drw, fonts, LENGTH(fonts))) {
|
|
|
|
die("no fonts could be loaded.");
|
|
|
|
}
|
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
readstdin();
|
2023-06-02 18:37:51 +02:00
|
|
|
set_mode();
|
|
|
|
init_appearance();
|
|
|
|
|
|
|
|
handle_wl();
|
|
|
|
#endif
|
2023-05-08 23:00:45 +02:00
|
|
|
}
|
2023-06-02 18:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
readargs(argc, argv); // start by reading arguments
|
2023-03-04 15:21:43 +01:00
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
// pledge limits what programs can do, so here we specify what spmenu should be allowed to do
|
|
|
|
#ifdef __OpenBSD__
|
|
|
|
if (pledge("stdio rpath wpath cpath", NULL) == -1)
|
|
|
|
die("pledge");
|
|
|
|
#endif
|
2023-03-04 15:21:43 +01:00
|
|
|
|
2023-06-02 18:37:51 +02:00
|
|
|
handle();
|
2023-01-20 23:17:30 +01:00
|
|
|
|
2023-05-08 23:00:45 +02:00
|
|
|
return 1; // should be unreachable
|
2023-01-20 23:17:30 +01:00
|
|
|
}
|