Merge branch 'next'
This commit is contained in:
		
						commit
						67774c3e46
					
				
							
								
								
									
										11
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Makefile
									
									
									
									
									
								
							| @ -3,7 +3,7 @@ | ||||
| 
 | ||||
| include config.mk | ||||
| 
 | ||||
| SRC = draw.c dunst.c list.c dunst_dbus.c utils.c options.c | ||||
| SRC = draw.c dunst.c container.c dunst_dbus.c utils.c options.c | ||||
| OBJ = ${SRC:.c=.o} | ||||
| 
 | ||||
| all: doc options dunst service | ||||
| @ -24,9 +24,13 @@ config.h: | ||||
| 	@echo creating $@ from config.def.h | ||||
| 	@cp config.def.h $@ | ||||
| 
 | ||||
| dunst: draw.o dunst.o list.o dunst_dbus.o utils.o options.o | ||||
| dunst: ${OBJ} | ||||
| 	@echo CC -o $@ | ||||
| 	@${CC} ${CFLAGS} -o $@ dunst.o draw.o list.o dunst_dbus.o options.o utils.o ${LDFLAGS} | ||||
| 	@${CC} ${CFLAGS} -o $@ ${OBJ} ${LDFLAGS} | ||||
| 
 | ||||
| debug: ${OBJ} | ||||
| 	@echo CC -o $@ | ||||
| 	@${CC} ${CFLAGS} -O0 -o dunst ${OBJ} ${LDFLAGS} | ||||
| 
 | ||||
| clean: | ||||
| 	@echo cleaning | ||||
| @ -34,6 +38,7 @@ clean: | ||||
| 	@rm -f dunst | ||||
| 	@rm -f dunst.1 | ||||
| 	@rm -f org.knopwob.dunst.service | ||||
| 	@rm -f core | ||||
| 
 | ||||
| doc: dunst.1 | ||||
| dunst.1: README.pod | ||||
|  | ||||
							
								
								
									
										15
									
								
								README.pod
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								README.pod
									
									
									
									
									
								
							| @ -145,6 +145,21 @@ The progress value can be set with a hint, too. | ||||
| 
 | ||||
| =back | ||||
| 
 | ||||
| =head1 MISCELLANEOUS | ||||
| 
 | ||||
| Dunst can be paused by sending a notification with a summary of "DUNST_COMMAND_PAUSE" | ||||
| and resumed with a summary of "DUNST_COMMAND_RESUME". Alternatively you can send SIGUSR1 and SIGUSR2 to pause and unpause respectivly. For Example: | ||||
| 
 | ||||
| =item killall -SIGUSR1 dunst # pause | ||||
| 
 | ||||
| =item killall -SIGUSR2 dunst # resume | ||||
| 
 | ||||
| =back | ||||
| 
 | ||||
| When paused dunst will not display any notifications but keep all notifications in a queue. | ||||
| This can for example be wrapped around a screen locker (i3lock, slock) to prevent flickering | ||||
| of notifications through the lock and to read all missed notifications after returning to the computer. | ||||
| 
 | ||||
| =head1 CONFIGURATION | ||||
| 
 | ||||
| An example configuration file is included (usually /usr/share/dunst/dunstrc). | ||||
|  | ||||
							
								
								
									
										14
									
								
								config.def.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								config.def.h
									
									
									
									
									
								
							| @ -27,10 +27,21 @@ int line_height = 0;   /* if line height < font height, it will be raised to fon | ||||
| int separator_height = 2; /* height of the separator line between two notifications */ | ||||
| enum separator_color sep_color = AUTO; /* AUTO or FOREGROUND */ | ||||
| 
 | ||||
| /* show a notification on startup
 | ||||
|  * This is mainly for crash detection since dbus restarts dunst | ||||
|  * automatically after a crash, so crashes might get unnotices otherwise | ||||
|  * */ | ||||
| int startup_notification = False; | ||||
| 
 | ||||
| 
 | ||||
| /* monitor to display notifications on */ | ||||
| int monitor = 0; | ||||
| 
 | ||||
| /* path to dmenu */ | ||||
| char *dmenu = "/usr/bin/dmenu"; | ||||
| 
 | ||||
| char *browser = "/usr/bin/firefox"; | ||||
| 
 | ||||
| /* follow focus to different monitor and display notifications there?
 | ||||
|  * possible values: | ||||
|  * FOLLOW_NONE | ||||
| @ -54,6 +65,9 @@ keyboard_shortcut close_all_ks = {.str = "none", | ||||
| keyboard_shortcut history_ks = {.str = "none", | ||||
|                        .code = 0, .sym = NoSymbol,.is_valid = False}; /* ignore this */ | ||||
| 
 | ||||
| keyboard_shortcut context_ks = {.str = "none", | ||||
|                        .code = 0, .sym = NoSymbol,.is_valid = False}; /* ignore this */ | ||||
| 
 | ||||
| rule_t default_rules[] = { | ||||
|      /* name can be any unique string. It is used to identify the rule in dunstrc to override it there */ | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										177
									
								
								container.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								container.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,177 @@ | ||||
| #include "stdlib.h" | ||||
| #include "stdio.h" | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "container.h" | ||||
| 
 | ||||
| void n_stack_push(n_stack **s, notification *n) | ||||
| { | ||||
|         if (!n || !s) | ||||
|                 return; | ||||
| 
 | ||||
|         n_stack *new = malloc(sizeof(n_stack)); | ||||
|         new->n = n; | ||||
|         new->next = *s; | ||||
|         *s = new; | ||||
| } | ||||
| 
 | ||||
| notification *n_stack_pop(n_stack **s) | ||||
| { | ||||
|         if (!s || !*s) | ||||
|                 return NULL; | ||||
| 
 | ||||
|         n_stack *head = *s; | ||||
|         *s = (*s)->next; | ||||
| 
 | ||||
|         notification *n = head->n; | ||||
|         free(head); | ||||
| 
 | ||||
|         return n; | ||||
| } | ||||
| 
 | ||||
| void n_stack_remove(n_stack **s, notification *n) | ||||
| { | ||||
|         if (!s || !*s || !n) | ||||
|                 return; | ||||
| 
 | ||||
|         /* head is n */ | ||||
|         if ((*s)->n == n) { | ||||
|                 n_stack *tmp = *s; | ||||
|                 *s = (*s)->next; | ||||
|                 free(tmp); | ||||
|                 return; | ||||
|         } | ||||
| 
 | ||||
|         for (n_stack *iter = *s; iter->next; iter = iter->next) { | ||||
|                 if (iter->next->n == n) { | ||||
|                         n_stack *tmp = iter->next; | ||||
|                         iter->next = iter->next->next; | ||||
|                         free(tmp); | ||||
|                         return; | ||||
|                 } | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| int n_stack_len(n_stack **s) | ||||
| { | ||||
|         if (!s || !*s) | ||||
|                 return 0; | ||||
| 
 | ||||
|         n_stack *cur = *s; | ||||
|         int count = 0; | ||||
| 
 | ||||
|         while (cur) { | ||||
|                 cur = cur->next; | ||||
|                 count++; | ||||
|         } | ||||
| 
 | ||||
|         return count; | ||||
| } | ||||
| 
 | ||||
| int cmp_notification(notification *a, notification *b) | ||||
| { | ||||
|         if (a == NULL && b == NULL) | ||||
|                 return 0; | ||||
|         else if (a == NULL) | ||||
|                 return -1; | ||||
|         else if (b == NULL) | ||||
|                 return 1; | ||||
| 
 | ||||
|         if (a->urgency != b->urgency) { | ||||
|                 return a->urgency - b->urgency; | ||||
|         } else { | ||||
|                 return b->timestamp - a->timestamp; | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| void n_queue_enqueue(n_queue **q, notification *n) | ||||
| { | ||||
|         if (!n || !q) | ||||
|                 return; | ||||
| 
 | ||||
| 
 | ||||
|         n_queue *new = malloc(sizeof(n_queue)); | ||||
|         new->n = n; | ||||
|         new->next = NULL; | ||||
| 
 | ||||
|         if (!(*q)) { | ||||
|                 /* queue was empty */ | ||||
|                 *q = new; | ||||
|                 return; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         /* new head */ | ||||
|         if (cmp_notification(new->n, (*q)->n) > 0) { | ||||
|                 new->next = *q; | ||||
|                 *q = new; | ||||
|                 return; | ||||
|         } | ||||
| 
 | ||||
|         /* in between */ | ||||
|         n_queue *cur = *q; | ||||
|         while (cur->next) { | ||||
|                 if (cmp_notification(new->n, cur->next->n) > 0) { | ||||
|                         new->next = cur->next; | ||||
|                         cur->next = new; | ||||
|                         return; | ||||
|                 } | ||||
| 
 | ||||
|                 cur = cur->next; | ||||
|         } | ||||
| 
 | ||||
|         /* last */ | ||||
|         cur->next = new; | ||||
| } | ||||
| 
 | ||||
| void n_queue_remove(n_queue **q, notification *n) | ||||
| { | ||||
|         n_stack_remove(q, n); | ||||
| } | ||||
| 
 | ||||
| notification *n_queue_dequeue(n_queue **q) | ||||
| { | ||||
|         return n_stack_pop(q); | ||||
| } | ||||
| 
 | ||||
| int n_queue_len(n_queue **q) | ||||
| { | ||||
|         return n_stack_len(q); | ||||
| } | ||||
| 
 | ||||
| str_array *str_array_malloc(void) | ||||
| { | ||||
|         str_array *a = malloc(sizeof(str_array)); | ||||
|         a->count = 0; | ||||
|         a->strs = NULL; | ||||
|         return a; | ||||
| } | ||||
| 
 | ||||
| void str_array_append(str_array *a, char *str) | ||||
| { | ||||
|         if (!a) | ||||
|                 return; | ||||
|         a->count++; | ||||
|         a->strs = realloc(a->strs, a->count); | ||||
|         (a->strs)[a->count-1] = str; | ||||
| } | ||||
| 
 | ||||
| void str_array_dup_append(str_array *a, const char *str) | ||||
| { | ||||
|         if (!a) | ||||
|                 return; | ||||
|         char *dup = strdup(str); | ||||
|         str_array_append(a, dup); | ||||
| } | ||||
| 
 | ||||
| void str_array_deep_free(str_array *a) | ||||
| { | ||||
|         if (!a) | ||||
|                 return; | ||||
|         for (int i = 0; i < a->count; i++) { | ||||
|                 free((a->strs)[i]); | ||||
|         } | ||||
|         free(a); | ||||
| } | ||||
| 
 | ||||
| /* vim: set ts=8 sw=8 tw=0: */ | ||||
							
								
								
									
										84
									
								
								container.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								container.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | ||||
| #ifndef _LIST_H | ||||
| #define _LIST_H | ||||
| 
 | ||||
| #include "dunst.h" | ||||
| 
 | ||||
| typedef struct _n_stack { | ||||
|         notification *n; | ||||
|         struct _n_stack *next; | ||||
| } n_stack; | ||||
| 
 | ||||
| typedef n_stack n_queue; | ||||
| 
 | ||||
| typedef struct _str_array { | ||||
|         int count; | ||||
|         char **strs; | ||||
| } str_array; | ||||
| 
 | ||||
| str_array *str_array_malloc(void); | ||||
| void str_array_dup_append(str_array *a, const char *str); | ||||
| void str_array_append(str_array *a, char *str); | ||||
| void str_array_deep_free(str_array *a); | ||||
| 
 | ||||
| int cmp_notification(notification *a, notification *b); | ||||
| 
 | ||||
| /************
 | ||||
|  * stack | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * push notification onto stack | ||||
|  * creates a new stack if *s == NULL | ||||
|  */ | ||||
| void n_stack_push(n_stack **s, notification *n); | ||||
| 
 | ||||
| /**
 | ||||
|  * remove and return notification from stack | ||||
|  * sets *s to NULL if stack is empty | ||||
|  */ | ||||
| notification *n_stack_pop(n_stack **s); | ||||
| 
 | ||||
| /**
 | ||||
|  * remove notification from stack | ||||
|  */ | ||||
| 
 | ||||
| void n_stack_remove(n_stack **q, notification *n); | ||||
| 
 | ||||
| /**
 | ||||
|  * return length of stack | ||||
|  */ | ||||
| 
 | ||||
| int n_stack_len(n_stack **s); | ||||
| 
 | ||||
| /***************
 | ||||
|  * queue | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * enqueue notification into queue | ||||
|  * creates a new queue if *q == NULL | ||||
|  */ | ||||
| 
 | ||||
| void n_queue_enqueue(n_queue **q, notification *n); | ||||
| 
 | ||||
| /**
 | ||||
|  * dequeues the next element from the queue. | ||||
|  * returns NULL if queue is empty | ||||
|  */ | ||||
| 
 | ||||
| notification *n_queue_dequeue(n_queue **q); | ||||
| 
 | ||||
| /**
 | ||||
|  * remove notification from queue | ||||
|  */ | ||||
| 
 | ||||
| void n_queue_remove(n_queue **q, notification *n); | ||||
| 
 | ||||
| /**
 | ||||
|  * return length of queue | ||||
|  */ | ||||
| 
 | ||||
| int n_queue_len(n_queue **q); | ||||
| 
 | ||||
| #endif | ||||
| /* vim: set ts=8 sw=8 tw=0: */ | ||||
							
								
								
									
										15
									
								
								draw.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								draw.c
									
									
									
									
									
								
							| @ -34,6 +34,7 @@ DEALINGS IN THE SOFTWARE. | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdbool.h> | ||||
| #include <string.h> | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/X.h> | ||||
| @ -45,7 +46,7 @@ DEALINGS IN THE SOFTWARE. | ||||
| #define MIN(a, b)  ((a) < (b) ? (a) : (b)) | ||||
| 
 | ||||
| void | ||||
| drawrect(DC * dc, int x, int y, unsigned int w, unsigned int h, Bool fill, | ||||
| drawrect(DC * dc, int x, int y, unsigned int w, unsigned int h, bool fill, | ||||
|          unsigned long color) | ||||
| { | ||||
|         XSetForeground(dc->dpy, dc->gc, color); | ||||
| @ -71,7 +72,7 @@ void drawtext(DC * dc, const char *text, ColorSet * col) | ||||
|         if (mn < n) | ||||
|                 for (n = MAX(mn - 3, 0); n < mn; buf[n++] = '.') ; | ||||
| 
 | ||||
|         drawrect(dc, 0, 0, dc->w, dc->h, True, col->BG); | ||||
|         drawrect(dc, 0, 0, dc->w, dc->h, true, col->BG); | ||||
|         drawtextn(dc, buf, mn, col); | ||||
| } | ||||
| 
 | ||||
| @ -234,12 +235,12 @@ void initfont(DC * dc, const char *fontstr) | ||||
|         return; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| setopacity(DC *dc, Window win, unsigned long opacity) | ||||
| void setopacity(DC * dc, Window win, unsigned long opacity) | ||||
| { | ||||
| 	Atom _NET_WM_WINDOW_OPACITY = XInternAtom(dc->dpy, "_NET_WM_WINDOW_OPACITY", False); | ||||
| 	XChangeProperty(dc->dpy, win, _NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32, PropModeReplace, | ||||
| 			(unsigned char *)&opacity, 1L); | ||||
|         Atom _NET_WM_WINDOW_OPACITY = | ||||
|             XInternAtom(dc->dpy, "_NET_WM_WINDOW_OPACITY", false); | ||||
|         XChangeProperty(dc->dpy, win, _NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32, | ||||
|                         PropModeReplace, (unsigned char *)&opacity, 1L); | ||||
| } | ||||
| 
 | ||||
| void mapdc(DC * dc, Window win, unsigned int w, unsigned int h) | ||||
|  | ||||
							
								
								
									
										8
									
								
								draw.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								draw.h
									
									
									
									
									
								
							| @ -33,11 +33,13 @@ DEALINGS IN THE SOFTWARE. | ||||
| #ifndef DRAW_H | ||||
| #define DRAW_H | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| #include <X11/Xft/Xft.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|         int x, y, w, h; | ||||
|         Bool invert; | ||||
|         bool invert; | ||||
|         Display *dpy; | ||||
|         GC gc; | ||||
|         Pixmap canvas; | ||||
| @ -59,7 +61,7 @@ typedef struct { | ||||
|         unsigned long BG; | ||||
| } ColorSet; | ||||
| 
 | ||||
| void drawrect(DC * dc, int x, int y, unsigned int w, unsigned int h, Bool fill, | ||||
| void drawrect(DC * dc, int x, int y, unsigned int w, unsigned int h, bool fill, | ||||
|               unsigned long color); | ||||
| void drawtext(DC * dc, const char *text, ColorSet * col); | ||||
| void drawtextn(DC * dc, const char *text, size_t n, ColorSet * col); | ||||
| @ -70,7 +72,7 @@ unsigned long getcolor(DC * dc, const char *colstr); | ||||
| ColorSet *initcolor(DC * dc, const char *foreground, const char *background); | ||||
| DC *initdc(void); | ||||
| void initfont(DC * dc, const char *fontstr); | ||||
| void setopacity(DC *dc, Window win, unsigned long opacity); | ||||
| void setopacity(DC * dc, Window win, unsigned long opacity); | ||||
| void mapdc(DC * dc, Window win, unsigned int w, unsigned int h); | ||||
| void resizedc(DC * dc, unsigned int w, unsigned int h); | ||||
| int textnw(DC * dc, const char *text, size_t len); | ||||
|  | ||||
							
								
								
									
										34
									
								
								dunst.h
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								dunst.h
									
									
									
									
									
								
							| @ -2,6 +2,8 @@ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| #include "draw.h" | ||||
| 
 | ||||
| #define LOW 0 | ||||
| @ -12,7 +14,6 @@ | ||||
| #define ColFG 1 | ||||
| #define ColBG 0 | ||||
| 
 | ||||
| 
 | ||||
| enum alignment { left, center, right }; | ||||
| enum separator_color { FOREGROUND, AUTO }; | ||||
| enum follow_mode { FOLLOW_NONE, FOLLOW_MOUSE, FOLLOW_KEYBOARD }; | ||||
| @ -23,6 +24,7 @@ typedef struct _dimension_t { | ||||
|         unsigned int h; | ||||
|         unsigned int w; | ||||
|         int mask; | ||||
|         int negative_width; | ||||
| } dimension_t; | ||||
| 
 | ||||
| typedef struct _screen_info { | ||||
| @ -30,30 +32,26 @@ typedef struct _screen_info { | ||||
|         dimension_t dim; | ||||
| } screen_info; | ||||
| 
 | ||||
| typedef struct _draw_txt { | ||||
|         char *txt; | ||||
|         int line_count; | ||||
| } draw_txt; | ||||
| 
 | ||||
| typedef struct _notification { | ||||
|         char *appname; | ||||
|         char *summary; | ||||
|         char *body; | ||||
|         char *icon; | ||||
|         char *msg; | ||||
|         draw_txt draw_txt_buf; | ||||
|         const char *format; | ||||
|         char *dbus_client; | ||||
|         time_t start; | ||||
|         time_t timestamp; | ||||
|         int timeout; | ||||
|         int urgency; | ||||
|         int redisplayed;        /* has been displayed before? */ | ||||
|         bool redisplayed;       /* has been displayed before? */ | ||||
|         int id; | ||||
|         int dup_count; | ||||
|         ColorSet *colors; | ||||
|         char *color_strings[2]; | ||||
|         int progress;           /* percentage + 1, 0 to hide */ | ||||
|         int line_count; | ||||
|         struct { int count; char **strs; } *urls; | ||||
| } notification; | ||||
| 
 | ||||
| typedef struct _notification_buffer { | ||||
| @ -83,9 +81,27 @@ typedef struct _keyboard_shortcut { | ||||
|         KeyCode code; | ||||
|         KeySym sym; | ||||
|         KeySym mask; | ||||
|         int is_valid; | ||||
|         bool is_valid; | ||||
| } keyboard_shortcut; | ||||
| 
 | ||||
| typedef struct _r_line { | ||||
|     ColorSet *colors; | ||||
|     char *str; | ||||
|     bool continues; | ||||
| } r_line; | ||||
| 
 | ||||
| typedef struct r_line_cache { | ||||
|     int count; | ||||
|     int size; | ||||
|     r_line *lines; | ||||
| } r_line_cache; | ||||
| 
 | ||||
| typedef struct _rule_array { | ||||
|         int count; | ||||
|         rule_t *rules; | ||||
| } rule_array; | ||||
| 
 | ||||
| 
 | ||||
| extern int verbosity; | ||||
| 
 | ||||
| /* return id of notification */ | ||||
|  | ||||
							
								
								
									
										79
									
								
								dunst_dbus.c
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								dunst_dbus.c
									
									
									
									
									
								
							| @ -3,7 +3,7 @@ | ||||
| #include <dbus/dbus.h> | ||||
| 
 | ||||
| #include "dunst.h" | ||||
| #include "list.h" | ||||
| #include "container.h" | ||||
| 
 | ||||
| #include "dunst_dbus.h" | ||||
| 
 | ||||
| @ -131,37 +131,36 @@ void dbus_poll(int timeout) | ||||
|         dbus_connection_read_write(dbus_conn, timeout); | ||||
| 
 | ||||
|         dbus_msg = dbus_connection_pop_message(dbus_conn); | ||||
|         /* we don't have a new message */ | ||||
|         if (dbus_msg == NULL) { | ||||
|                 return; | ||||
|         } | ||||
| 
 | ||||
|         if (dbus_message_is_method_call | ||||
|             (dbus_msg, "org.freedesktop.DBus.Introspectable", "Introspect")) { | ||||
|                 dbus_introspect(dbus_msg); | ||||
|         } | ||||
|         while (dbus_msg) { | ||||
|                 if (dbus_message_is_method_call | ||||
|                     (dbus_msg, "org.freedesktop.DBus.Introspectable", "Introspect")) { | ||||
|                         dbus_introspect(dbus_msg); | ||||
|                 } | ||||
| 
 | ||||
|         if (dbus_message_is_method_call(dbus_msg, | ||||
|                                         "org.freedesktop.Notifications", | ||||
|                                         "Notify")) { | ||||
|                 notify(dbus_msg); | ||||
|                 if (dbus_message_is_method_call(dbus_msg, | ||||
|                                                 "org.freedesktop.Notifications", | ||||
|                                                 "Notify")) { | ||||
|                         notify(dbus_msg); | ||||
|                 } | ||||
|                 if (dbus_message_is_method_call(dbus_msg, | ||||
|                                                 "org.freedesktop.Notifications", | ||||
|                                                 "GetCapabilities")) { | ||||
|                         getCapabilities(dbus_msg); | ||||
|                 } | ||||
|                 if (dbus_message_is_method_call(dbus_msg, | ||||
|                                                 "org.freedesktop.Notifications", | ||||
|                                                 "GetServerInformation")) { | ||||
|                         getServerInformation(dbus_msg); | ||||
|                 } | ||||
|                 if (dbus_message_is_method_call(dbus_msg, | ||||
|                                                 "org.freedesktop.Notifications", | ||||
|                                                 "CloseNotification")) { | ||||
|                         closeNotification(dbus_msg); | ||||
|                 } | ||||
|                 dbus_message_unref(dbus_msg); | ||||
|                 dbus_msg = dbus_connection_pop_message(dbus_conn); | ||||
|         } | ||||
|         if (dbus_message_is_method_call(dbus_msg, | ||||
|                                         "org.freedesktop.Notifications", | ||||
|                                         "GetCapabilities")) { | ||||
|                 getCapabilities(dbus_msg); | ||||
|         } | ||||
|         if (dbus_message_is_method_call(dbus_msg, | ||||
|                                         "org.freedesktop.Notifications", | ||||
|                                         "GetServerInformation")) { | ||||
|                 getServerInformation(dbus_msg); | ||||
|         } | ||||
|         if (dbus_message_is_method_call(dbus_msg, | ||||
|                                         "org.freedesktop.Notifications", | ||||
|                                         "CloseNotification")) { | ||||
|                 closeNotification(dbus_msg); | ||||
|         } | ||||
|         dbus_message_unref(dbus_msg); | ||||
| } | ||||
| 
 | ||||
| void getCapabilities(DBusMessage * dmsg) | ||||
| @ -336,11 +335,17 @@ void notify(DBusMessage * dmsg) | ||||
|                                 continue; | ||||
|                         } | ||||
|                         dbus_message_iter_get_basic(&hint, &hint_name); | ||||
|                         _extract_hint(DBUS_TYPE_BYTE, "urgency", hint_name, &hint, &urgency); | ||||
|                         _extract_hint(DBUS_TYPE_STRING, "fgcolor", hint_name, &hint, &fgcolor); | ||||
|                         _extract_hint(DBUS_TYPE_STRING, "bgcolor", hint_name, &hint, &bgcolor); | ||||
|                         _extract_hint(DBUS_TYPE_INT32, "value", hint_name, &hint, &progress); | ||||
|                         if (!progress) _extract_hint(DBUS_TYPE_UINT32, "value", hint_name, &hint, &progress); | ||||
|                         _extract_hint(DBUS_TYPE_BYTE, "urgency", hint_name, | ||||
|                                       &hint, &urgency); | ||||
|                         _extract_hint(DBUS_TYPE_STRING, "fgcolor", hint_name, | ||||
|                                       &hint, &fgcolor); | ||||
|                         _extract_hint(DBUS_TYPE_STRING, "bgcolor", hint_name, | ||||
|                                       &hint, &bgcolor); | ||||
|                         _extract_hint(DBUS_TYPE_INT32, "value", hint_name, | ||||
|                                       &hint, &progress); | ||||
|                         if (!progress) | ||||
|                                 _extract_hint(DBUS_TYPE_UINT32, "value", | ||||
|                                               hint_name, &hint, &progress); | ||||
|                         dbus_message_iter_next(&hint); | ||||
|                 } | ||||
|                 dbus_message_iter_next(&hints); | ||||
| @ -358,7 +363,7 @@ void notify(DBusMessage * dmsg) | ||||
|         n->body = body != NULL ? strdup(body) : ""; | ||||
|         n->icon = icon != NULL ? strdup(icon) : ""; | ||||
|         n->timeout = expires; | ||||
|         n->progress = (progress < 0 || progress > 100) ? 0 : progress+1; | ||||
|         n->progress = (progress < 0 || progress > 100) ? 0 : progress + 1; | ||||
|         n->urgency = urgency; | ||||
|         n->dbus_client = strdup(dbus_message_get_sender(dmsg)); | ||||
|         for (i = 0; i < ColLast; i++) { | ||||
| @ -366,8 +371,10 @@ void notify(DBusMessage * dmsg) | ||||
|         } | ||||
|         n->color_strings[ColFG] = fgcolor == NULL ? NULL : strdup(fgcolor); | ||||
|         n->color_strings[ColBG] = bgcolor == NULL ? NULL : strdup(bgcolor); | ||||
| 
 | ||||
|         id = init_notification(n, replaces_id); | ||||
|         map_win(); | ||||
|         if (id > 0) | ||||
|                 map_win(); | ||||
| 
 | ||||
|         reply = dbus_message_new_method_return(dmsg); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										16
									
								
								dunstrc
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								dunstrc
									
									
									
									
									
								
							| @ -43,6 +43,8 @@ | ||||
|     # the window expands to the longest message displayed. | ||||
|     # A positive x is measured from the left, a negative from the | ||||
|     # right side of the screen.  Y is measured from the top and down respectevly. | ||||
|     # The width can be negative. In this case the actual width is the | ||||
|     # screen width minus the width defined in within the geometry option. | ||||
|     geometry = "0x3-30+20" | ||||
| 
 | ||||
|     # The transparency of the window. range: [0; 100] | ||||
| @ -87,6 +89,17 @@ | ||||
|     # that fits nicely to the background color. | ||||
|     separator_color = auto | ||||
| 
 | ||||
|     # print a notification on startup | ||||
|     # This is mainly for error detection, since dbus (re-)starts dunst | ||||
|     # automatically after a crash. | ||||
|     startup_notification = false | ||||
| 
 | ||||
|     # dmenu path | ||||
|     dmenu = /usr/bin/dmenu -p dunst: | ||||
| 
 | ||||
|     # browser for opening urls in context menu | ||||
|     browser = /usr/bin/firefox -new-tab | ||||
| 
 | ||||
| 
 | ||||
| [shortcuts] | ||||
|     # shortcuts are specified as [modifier+][modifier+]...key | ||||
| @ -104,6 +117,9 @@ | ||||
|     # On the US keyboard layout 'grave' is normally above TAB and left of '1'. | ||||
|     history = ctrl+grave | ||||
| 
 | ||||
|     # context menu | ||||
|     context = ctrl+shift+period | ||||
| 
 | ||||
| [urgency_low] | ||||
|     # IMPORTANT: colors have to be defined in quotation marks. | ||||
|     # Otherwise the '#' and following  would be interpreted as a comment. | ||||
|  | ||||
							
								
								
									
										266
									
								
								list.c
									
									
									
									
									
								
							
							
						
						
									
										266
									
								
								list.c
									
									
									
									
									
								
							| @ -1,266 +0,0 @@ | ||||
| #include "stdlib.h" | ||||
| #include "stdio.h" | ||||
| 
 | ||||
| #include "list.h" | ||||
| 
 | ||||
| int l_push(list * l, void *data) | ||||
| { | ||||
|         l_node *n; | ||||
|         int ret; | ||||
| 
 | ||||
|         /* invalid input */ | ||||
|         if (!l || !data) { | ||||
|                 return -1; | ||||
|         } | ||||
| 
 | ||||
|         n = l_init_node(data); | ||||
|         if (!n) { | ||||
|                 /* something went wrong */ | ||||
|                 return -2; | ||||
|         } | ||||
| 
 | ||||
|         ret = l_node_push(l, n); | ||||
| 
 | ||||
|         return ret; | ||||
| } | ||||
| 
 | ||||
| int l_node_push(list * l, l_node * n) | ||||
| { | ||||
|         l_node *end; | ||||
| 
 | ||||
|         /* invalid input */ | ||||
|         if (!l || !n) { | ||||
|                 return -1; | ||||
|         } | ||||
| 
 | ||||
|         n->next = NULL; | ||||
| 
 | ||||
|         /* empty list */ | ||||
|         if (!l->head) { | ||||
|                 l->head = n; | ||||
| 
 | ||||
|                 return 0; | ||||
|         } | ||||
| 
 | ||||
|         for (end = l->head; end->next; end = end->next) ; | ||||
| 
 | ||||
|         if (end != n) { | ||||
|                 end->next = n; | ||||
|         } | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| void *l_pop(list * l) | ||||
| { | ||||
|         l_node *penultimate; | ||||
|         void *data; | ||||
| 
 | ||||
|         /* invalid input */ | ||||
|         if (!l) { | ||||
|                 return NULL; | ||||
|         } | ||||
| 
 | ||||
|         /* empty list */ | ||||
|         if (!l->head) { | ||||
|                 return NULL; | ||||
|         } | ||||
| 
 | ||||
|         /* len(l) == 1 */ | ||||
|         if (!l->head->next) { | ||||
|                 data = l->head->data; | ||||
|                 free(l->head); | ||||
|                 l->head = NULL; | ||||
| 
 | ||||
|                 return data; | ||||
|         } | ||||
| 
 | ||||
|         for (penultimate = l->head; | ||||
|              penultimate->next->next; penultimate = penultimate->next) ; | ||||
|         data = penultimate->next->data; | ||||
|         free(penultimate->next); | ||||
|         penultimate->next = NULL; | ||||
| 
 | ||||
|         return data; | ||||
| } | ||||
| 
 | ||||
| int l_insert(l_node * node, void *data) | ||||
| { | ||||
|         int ret; | ||||
|         l_node *to_be_inserted; | ||||
| 
 | ||||
|         /* invalid input */ | ||||
|         if (!node || !data) { | ||||
|                 return -1; | ||||
|         } | ||||
| 
 | ||||
|         to_be_inserted = l_init_node(data); | ||||
|         if (!to_be_inserted) { | ||||
|                 return -2; | ||||
|         } | ||||
| 
 | ||||
|         ret = l_node_insert(node, to_be_inserted); | ||||
| 
 | ||||
|         return ret; | ||||
| } | ||||
| 
 | ||||
| int l_node_insert(l_node * node, l_node * to_be_inserted) | ||||
| { | ||||
|         l_node *tmp; | ||||
| 
 | ||||
|         /* invalid input */ | ||||
|         if (!node || !to_be_inserted) { | ||||
|                 return -1; | ||||
|         } | ||||
| 
 | ||||
|         tmp = node->next; | ||||
|         node->next = to_be_inserted; | ||||
|         to_be_inserted->next = tmp; | ||||
| 
 | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| void *l_remove(list * l, l_node * node) | ||||
| { | ||||
|         void *data; | ||||
|         if (l != NULL) { | ||||
|                 l_node_remove(l, node); | ||||
|         } | ||||
| 
 | ||||
|         if (node == NULL) { | ||||
|                 return NULL; | ||||
|         } | ||||
| 
 | ||||
|         data = node->data; | ||||
|         free(node); | ||||
| 
 | ||||
|         return data; | ||||
| } | ||||
| 
 | ||||
| l_node *l_node_remove(list * l, l_node * node) | ||||
| { | ||||
|         l_node *prev; | ||||
|         l_node *next; | ||||
| 
 | ||||
|         /* invalid input */ | ||||
|         if (!l || !node) { | ||||
|                 return NULL; | ||||
|         } | ||||
| 
 | ||||
|         /* empty list */ | ||||
|         if (!l->head) { | ||||
|                 return NULL; | ||||
|         } | ||||
| 
 | ||||
|         /* node is head */ | ||||
|         if (l->head == node) { | ||||
|                 l->head = node->next; | ||||
|                 node->next = NULL; | ||||
|                 return node; | ||||
|         } | ||||
| 
 | ||||
|         /* find the predecessor of node */ | ||||
|         for (prev = l->head; | ||||
|              prev->next && prev->next != node; prev = prev->next) ; | ||||
| 
 | ||||
|         /* node not in list */ | ||||
|         if (prev->next != node) { | ||||
|                 return node; | ||||
|         } | ||||
| 
 | ||||
|         next = node->next; | ||||
|         prev->next = next; | ||||
| 
 | ||||
|         return node; | ||||
| } | ||||
| 
 | ||||
| l_node *l_init_node(void *data) | ||||
| { | ||||
|         l_node *node; | ||||
| 
 | ||||
|         node = malloc(sizeof(l_node)); | ||||
|         if (!node) { | ||||
|                 return NULL; | ||||
|         } | ||||
| 
 | ||||
|         node->data = data; | ||||
|         node->next = NULL; | ||||
| 
 | ||||
|         return node; | ||||
| } | ||||
| 
 | ||||
| int l_length(list * l) | ||||
| { | ||||
|         l_node *iter; | ||||
|         int count; | ||||
| 
 | ||||
|         if (!l || !l->head) { | ||||
|                 return 0; | ||||
|         } | ||||
| 
 | ||||
|         count = 0; | ||||
|         iter = l->head; | ||||
|         while (iter) { | ||||
|                 count++; | ||||
|                 iter = iter->next; | ||||
|         } | ||||
| 
 | ||||
|         return count; | ||||
| } | ||||
| 
 | ||||
| int l_is_empty(list * l) | ||||
| { | ||||
|         return l->head == NULL; | ||||
| } | ||||
| 
 | ||||
| int l_move(list * from, list * to, l_node * node) | ||||
| { | ||||
| 
 | ||||
|         if (!from || !to || !node) { | ||||
|                 return -1; | ||||
|         } | ||||
|         node = l_node_remove(from, node); | ||||
|         return l_node_push(to, node); | ||||
| } | ||||
| 
 | ||||
| list *l_init(void) | ||||
| { | ||||
|         list *l = malloc(sizeof(list)); | ||||
|         l->head = NULL; | ||||
| 
 | ||||
|         return l; | ||||
| } | ||||
| 
 | ||||
| void l_sort(list * l, int (*f) (void *, void *)) | ||||
| { | ||||
|         list *old_list; | ||||
| 
 | ||||
|         if (!l || l_length(l) < 2) { | ||||
|                 /* nothing to do */ | ||||
|                 return; | ||||
|         } | ||||
| 
 | ||||
|         old_list = l_init(); | ||||
| 
 | ||||
|         old_list->head = l->head; | ||||
|         l->head = NULL; | ||||
| 
 | ||||
|         while (!l_is_empty(old_list)) { | ||||
|                 l_node *iter; | ||||
|                 l_node *max; | ||||
| 
 | ||||
|                 /* find max in old_list */ | ||||
|                 max = old_list->head; | ||||
|                 for (iter = old_list->head; iter; iter = iter->next) { | ||||
|                         if (f(max->data, iter->data) < 0) { | ||||
|                                 max = iter; | ||||
|                         } | ||||
|                 } | ||||
| 
 | ||||
|                 l_move(old_list, l, max); | ||||
|         } | ||||
| 
 | ||||
|         free(old_list); | ||||
| } | ||||
| 
 | ||||
| /* vim: set ts=8 sw=8 tw=0: */ | ||||
							
								
								
									
										59
									
								
								list.h
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								list.h
									
									
									
									
									
								
							| @ -1,59 +0,0 @@ | ||||
| #ifndef _LIST_H | ||||
| #define _LIST_H | ||||
| 
 | ||||
| typedef struct _l_node { | ||||
|         struct _l_node *next; | ||||
|         void *data; | ||||
| } l_node; | ||||
| 
 | ||||
| typedef struct _list { | ||||
|         l_node *head; | ||||
| } list; | ||||
| 
 | ||||
| /* append to end of list */ | ||||
| int l_push(list * l, void *data); | ||||
| 
 | ||||
| /* same as append but with a l_node */ | ||||
| int l_node_push(list * l, l_node * n); | ||||
| 
 | ||||
| /* remove and return last element of list */ | ||||
| void *l_pop(list * l); | ||||
| 
 | ||||
| /* insert after node. */ | ||||
| int l_insert(l_node * node, void *data); | ||||
| 
 | ||||
| /*
 | ||||
|  * same as insert, but using a node_t | ||||
|  */ | ||||
| int l_node_insert(l_node * node, l_node * to_be_inserted); | ||||
| 
 | ||||
| /*
 | ||||
|  * remove l_node from list and return a pointer to its data | ||||
|  */ | ||||
| void *l_remove(list * l, l_node * node); | ||||
| 
 | ||||
| /*
 | ||||
|  * same as l_remove but returns the node instead of the data | ||||
|  */ | ||||
| l_node *l_node_remove(list * l, l_node * node); | ||||
| 
 | ||||
| /*
 | ||||
|  * initialize a node | ||||
|  */ | ||||
| l_node *l_init_node(void *data); | ||||
| 
 | ||||
| /* return the length of the list */ | ||||
| int l_length(list * l); | ||||
| 
 | ||||
| /* is list empty */ | ||||
| int l_is_empty(list * l); | ||||
| 
 | ||||
| /* move node from 'from' to 'to' */ | ||||
| int l_move(list * from, list * to, l_node * node); | ||||
| 
 | ||||
| void l_sort(list * l, int (*f) (void *, void *)); | ||||
| 
 | ||||
| list *l_init(void); | ||||
| #endif | ||||
| 
 | ||||
| /* vim: set ts=8 sw=8 tw=0: */ | ||||
							
								
								
									
										257
									
								
								options.c
									
									
									
									
									
								
							
							
						
						
									
										257
									
								
								options.c
									
									
									
									
									
								
							| @ -1,4 +1,6 @@ | ||||
| /* copyright 2012 Sascha Kruse and contributors (see LICENSE for licensing information) */ | ||||
| #define _GNU_SOURCE | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| @ -9,21 +11,17 @@ | ||||
| #include "utils.h" | ||||
| 
 | ||||
| typedef struct _entry_t { | ||||
|     char *key; | ||||
|     char *value; | ||||
|         char *key; | ||||
|         char *value; | ||||
| } entry_t; | ||||
| 
 | ||||
| typedef struct _section_t { | ||||
|     char *name; | ||||
|     int entry_count; | ||||
|     entry_t *entries; | ||||
|         char *name; | ||||
|         int entry_count; | ||||
|         entry_t *entries; | ||||
| } section_t; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| static int section_count; | ||||
| static int section_count = 0; | ||||
| static section_t *sections; | ||||
| 
 | ||||
| static section_t *new_section(char *name); | ||||
| @ -32,19 +30,27 @@ static void add_entry(char *section_name, char *key, char *value); | ||||
| static char *get_value(char *section, char *key); | ||||
| static char *clean_value(char *value); | ||||
| 
 | ||||
| static int cmdline_argc; | ||||
| static char **cmdline_argv; | ||||
| 
 | ||||
| static char *usage_str = NULL; | ||||
| static void cmdline_usage_append(char *key, char *type, char *description); | ||||
| 
 | ||||
| static int cmdline_find_option(char *key); | ||||
| 
 | ||||
| section_t *new_section(char *name) | ||||
| { | ||||
|         section_count++; | ||||
|         sections = realloc(sections, sizeof(section_t) *section_count); | ||||
|         sections = realloc(sections, sizeof(section_t) * section_count); | ||||
|         sections[section_count - 1].name = strdup(name); | ||||
|         sections[section_count - 1].entries = NULL; | ||||
|         sections[section_count - 1].entry_count = 0; | ||||
|         return §ions[section_count -1]; | ||||
|         return §ions[section_count - 1]; | ||||
| } | ||||
| 
 | ||||
| void free_ini(void) | ||||
| { | ||||
|         for(int i = 0; i < section_count; i++) { | ||||
|         for (int i = 0; i < section_count; i++) { | ||||
|                 for (int j = 0; j < sections[i].entry_count; j++) { | ||||
|                         free(sections[i].entries[j].key); | ||||
|                         free(sections[i].entries[j].value); | ||||
| @ -97,10 +103,13 @@ char *get_value(char *section, char *key) | ||||
| char *ini_get_string(char *section, char *key, const char *def) | ||||
| { | ||||
|         char *value = get_value(section, key); | ||||
|         if (value == NULL) | ||||
|                 return def; | ||||
|         else | ||||
|         if (value) | ||||
|                 return strdup(value); | ||||
| 
 | ||||
|         if (def == NULL) | ||||
|                 return NULL; | ||||
|         else | ||||
|                 return strdup(def); | ||||
| } | ||||
| 
 | ||||
| int ini_get_int(char *section, char *key, int def) | ||||
| @ -112,7 +121,7 @@ int ini_get_int(char *section, char *key, int def) | ||||
|                 return atoi(value); | ||||
| } | ||||
| 
 | ||||
| double ini_get_double(char *section, char *key, int def) | ||||
| double ini_get_double(char *section, char *key, double def) | ||||
| { | ||||
|         char *value = get_value(section, key); | ||||
|         if (value == NULL) | ||||
| @ -135,7 +144,7 @@ char *next_section(char *section) | ||||
|                         if (i + 1 >= section_count) | ||||
|                                 return NULL; | ||||
|                         else | ||||
|                                 return sections[i+1].name; | ||||
|                                 return sections[i + 1].name; | ||||
|                 } | ||||
|         } | ||||
|         return NULL; | ||||
| @ -182,7 +191,7 @@ char *clean_value(char *value) | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| int load_ini_file(FILE *fp) | ||||
| int load_ini_file(FILE * fp) | ||||
| { | ||||
|         char line[BUFSIZ]; | ||||
| 
 | ||||
| @ -199,7 +208,9 @@ int load_ini_file(FILE *fp) | ||||
|                 if (*start == '[') { | ||||
|                         char *end = strstr(start + 1, "]"); | ||||
|                         if (!end) { | ||||
|                                 printf("Warning: invalid config file at line %d\n", line_num); | ||||
|                                 printf | ||||
|                                     ("Warning: invalid config file at line %d\n", | ||||
|                                      line_num); | ||||
|                                 printf("Missing ']'\n"); | ||||
|                                 continue; | ||||
|                         } | ||||
| @ -208,27 +219,30 @@ int load_ini_file(FILE *fp) | ||||
| 
 | ||||
|                         if (current_section) | ||||
|                                 free(current_section); | ||||
|                         current_section = (strdup(start+1)); | ||||
|                         current_section = (strdup(start + 1)); | ||||
|                         new_section(current_section); | ||||
|                         continue; | ||||
|                 } | ||||
| 
 | ||||
|                 char *equal = strstr(start + 1, "="); | ||||
|                 if (!equal) { | ||||
|                         printf("Warning: invalid config file at line %d\n", line_num); | ||||
|                         printf("Warning: invalid config file at line %d\n", | ||||
|                                line_num); | ||||
|                         printf("Missing '='\n"); | ||||
|                         continue; | ||||
|                 } | ||||
| 
 | ||||
|                 *equal = '\0'; | ||||
|                 char *key = rstrip(start); | ||||
|                 char *value = lskip(equal+1); | ||||
|                 char *value = lskip(equal + 1); | ||||
| 
 | ||||
|                 char *quote = strstr(value, "\""); | ||||
|                 if (quote) { | ||||
|                         char *closing_quote = strstr(quote + 1, "\""); | ||||
|                         if (!closing_quote) { | ||||
|                                 printf("Warning: invalid config file at line %d\n", line_num); | ||||
|                                 printf | ||||
|                                     ("Warning: invalid config file at line %d\n", | ||||
|                                      line_num); | ||||
|                                 printf("Missing '\"'\n"); | ||||
|                                 continue; | ||||
|                         } | ||||
| @ -244,7 +258,8 @@ int load_ini_file(FILE *fp) | ||||
|                 value = rstrip(value); | ||||
| 
 | ||||
|                 if (!current_section) { | ||||
|                         printf("Warning: invalid config file at line: %d\n", line_num); | ||||
|                         printf("Warning: invalid config file at line: %d\n", | ||||
|                                line_num); | ||||
|                         printf("Key value pair without a section\n"); | ||||
|                         continue; | ||||
|                 } | ||||
| @ -255,4 +270,196 @@ int load_ini_file(FILE *fp) | ||||
|                 free(current_section); | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| void cmdline_load(int argc, char *argv[]) | ||||
| { | ||||
|         cmdline_argc = argc; | ||||
|         cmdline_argv = argv; | ||||
| } | ||||
| 
 | ||||
| int cmdline_find_option(char *key) | ||||
| { | ||||
|         if (!key) { | ||||
|                 return -1; | ||||
|         } | ||||
|         char *key1 = strdup(key); | ||||
|         char *key2 = strstr(key1, "/"); | ||||
| 
 | ||||
|         if (key2) { | ||||
|                 *key2 = '\0'; | ||||
|                 key2++; | ||||
|         } | ||||
| 
 | ||||
|         /* look for first key */ | ||||
|         for (int i = 0; i < cmdline_argc; i++) { | ||||
|                 if (strcmp(key1, cmdline_argv[i]) == 0) { | ||||
|                         free(key1); | ||||
|                         return i; | ||||
|                 } | ||||
|         } | ||||
| 
 | ||||
|         /* look for second key if one was specified */ | ||||
|         if (key2) { | ||||
|                 for (int i = 0; i < cmdline_argc; i++) { | ||||
|                         if (strcmp(key2, cmdline_argv[i]) == 0) { | ||||
|                                 free(key1); | ||||
|                                 return i; | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
| 
 | ||||
|         free(key1); | ||||
|         return -1; | ||||
| } | ||||
| 
 | ||||
| static char *cmdline_get_value(char *key) | ||||
| { | ||||
|         int idx = cmdline_find_option(key); | ||||
|         if (idx < 0) { | ||||
|                 return NULL; | ||||
|         } | ||||
| 
 | ||||
|         if (idx + 1 >= cmdline_argc || cmdline_argv[idx + 1][0] == '-') { | ||||
|                 /* the argument is missing */ | ||||
|                 fprintf(stderr, "Warning: %s, missing argument. Ignoring\n", | ||||
|                         key); | ||||
|                 return NULL; | ||||
|         } | ||||
|         return cmdline_argv[idx + 1]; | ||||
| } | ||||
| 
 | ||||
| char *cmdline_get_string(char *key, const char *def, char *description) | ||||
| { | ||||
|         cmdline_usage_append(key, "string", description); | ||||
|         char *str = cmdline_get_value(key); | ||||
| 
 | ||||
|         if (str) | ||||
|                 return strdup(str); | ||||
|         if (def == NULL) | ||||
|                 return NULL; | ||||
|         else | ||||
|                 return strdup(def); | ||||
| } | ||||
| 
 | ||||
| int cmdline_get_int(char *key, int def, char *description) | ||||
| { | ||||
|         cmdline_usage_append(key, "double", description); | ||||
|         char *str = cmdline_get_value(key); | ||||
| 
 | ||||
|         if (str == NULL) | ||||
|                 return def; | ||||
|         else | ||||
|                 return atoi(str); | ||||
| } | ||||
| 
 | ||||
| double cmdline_get_double(char *key, double def, char *description) | ||||
| { | ||||
|         cmdline_usage_append(key, "double", description); | ||||
|         char *str = cmdline_get_value(key); | ||||
|         if (str == NULL) | ||||
|                 return def; | ||||
|         else | ||||
|                 return atof(str); | ||||
| } | ||||
| 
 | ||||
| int cmdline_get_bool(char *key, int def, char *description) | ||||
| { | ||||
|         cmdline_usage_append(key, "", description); | ||||
|         int idx = cmdline_find_option(key); | ||||
|         if (idx > 0) | ||||
|                 return true; | ||||
|         else | ||||
|                 return def; | ||||
| } | ||||
| 
 | ||||
| char *option_get_string(char *ini_section, char *ini_key, char *cmdline_key, | ||||
|                         const char *def, char *description) | ||||
| { | ||||
|         char *val = NULL; | ||||
| 
 | ||||
|         if (cmdline_key) { | ||||
|                 val = cmdline_get_string(cmdline_key, NULL, description); | ||||
|         } | ||||
| 
 | ||||
|         if (val) { | ||||
|                 return val; | ||||
|         } else { | ||||
|                 return ini_get_string(ini_section, ini_key, def); | ||||
|         } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| int option_get_int(char *ini_section, char *ini_key, char *cmdline_key, int def, | ||||
|                    char *description) | ||||
| { | ||||
|         /* *str is only used to check wether the cmdline option is actually set. */ | ||||
|         char *str = cmdline_get_value(cmdline_key); | ||||
| 
 | ||||
|         /* we call cmdline_get_int even when the option isn't set in order to
 | ||||
|          * add the usage info */ | ||||
|         int val = cmdline_get_int(cmdline_key, def, description); | ||||
| 
 | ||||
|         if (!str) | ||||
|                 return ini_get_int(ini_section, ini_key, def); | ||||
|         else | ||||
|                 return val; | ||||
| } | ||||
| 
 | ||||
| double option_get_double(char *ini_section, char *ini_key, char *cmdline_key, | ||||
|                          double def, char *description) | ||||
| { | ||||
|         char *str = cmdline_get_value(cmdline_key); | ||||
|         double val = cmdline_get_double(cmdline_key, def, description); | ||||
| 
 | ||||
|         if (!str) | ||||
|                 return ini_get_int(ini_section, ini_key, def); | ||||
|         else | ||||
|                 return val; | ||||
| } | ||||
| 
 | ||||
| int option_get_bool(char *ini_section, char *ini_key, char *cmdline_key, | ||||
|                     int def, char *description) | ||||
| { | ||||
|         int val = false; | ||||
| 
 | ||||
|         if (cmdline_key) | ||||
|                 val = cmdline_get_bool(cmdline_key, false, description); | ||||
| 
 | ||||
|         if (cmdline_key && val) { | ||||
|                 /* this can only be true if the value has been set,
 | ||||
|                  * so we can return */ | ||||
|                 return true; | ||||
|         } | ||||
| 
 | ||||
|         return ini_get_bool(ini_section, ini_key, def); | ||||
| } | ||||
| 
 | ||||
| void cmdline_usage_append(char *key, char *type, char *description) | ||||
| { | ||||
|         char *key_type; | ||||
|         if (type && strlen(type) > 0) | ||||
|                 asprintf(&key_type, "%s (%s)", key, type); | ||||
|         else | ||||
|                 asprintf(&key_type, "%s", key); | ||||
| 
 | ||||
|         if (!usage_str) { | ||||
|                 asprintf(&usage_str, "%-40s - %s\n", key_type, description); | ||||
|                 free(key_type); | ||||
|                 return; | ||||
|         } | ||||
| 
 | ||||
|         char *tmp; | ||||
|         asprintf(&tmp, "%s%-40s - %s\n", usage_str, key_type, description); | ||||
|         free(key_type); | ||||
| 
 | ||||
|         free(usage_str); | ||||
|         usage_str = tmp; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| char *cmdline_create_usage(void) | ||||
| { | ||||
|         return strdup(usage_str); | ||||
| } | ||||
| 
 | ||||
| /* vim: set ts=8 sw=8 tw=0: */ | ||||
|  | ||||
							
								
								
									
										20
									
								
								options.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								options.h
									
									
									
									
									
								
							| @ -3,14 +3,30 @@ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| 
 | ||||
| int load_ini_file(FILE *); | ||||
| char *ini_get_string(char *section, char *key, const char *def); | ||||
| int ini_get_int(char *section, char *key, int def); | ||||
| double ini_get_double(char *section, char *key, int def); | ||||
| double ini_get_double(char *section, char *key, double def); | ||||
| int ini_get_bool(char *section, char *key, int def); | ||||
| void free_ini(void); | ||||
| 
 | ||||
| void cmdline_load(int argc, char *argv[]); | ||||
| /* for all cmdline_get_* key can be either "-key" or "-key/-longkey" */ | ||||
| char *cmdline_get_string(char *key, const char *def, char *description); | ||||
| int cmdline_get_int(char *key, int def, char *description); | ||||
| double cmdline_get_double(char *key, double def, char *description); | ||||
| int cmdline_get_bool(char *key, int def, char *description); | ||||
| char *cmdline_create_usage(void); | ||||
| 
 | ||||
| char *option_get_string(char *ini_section, char *ini_key, char *cmdline_key, | ||||
|                         const char *def, char *description); | ||||
| int option_get_int(char *ini_section, char *ini_key, char *cmdline_key, int def, | ||||
|                    char *description); | ||||
| double option_get_double(char *ini_section, char *ini_key, char *cmdline_key, | ||||
|                          double def, char *description); | ||||
| int option_get_bool(char *ini_section, char *ini_key, char *cmdline_key, | ||||
|                     int def, char *description); | ||||
| 
 | ||||
| /* returns the next known section.
 | ||||
|  * if section == NULL returns first section. | ||||
|  * returns NULL if no more sections are available | ||||
|  | ||||
							
								
								
									
										45
									
								
								utils.c
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								utils.c
									
									
									
									
									
								
							| @ -1,3 +1,5 @@ | ||||
| #define _GNU_SOURCE | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include <ctype.h> | ||||
| #include <stdlib.h> | ||||
| @ -6,7 +8,6 @@ | ||||
| #include "utils.h" | ||||
| #include "dunst.h" | ||||
| 
 | ||||
| 
 | ||||
| char *rstrip(char *str) | ||||
| { | ||||
|         char *end; | ||||
| @ -20,7 +21,7 @@ char *rstrip(char *str) | ||||
| 
 | ||||
| char *lskip(char *s) | ||||
| { | ||||
|         for(; *s && isspace(*s); s++); | ||||
|         for (; *s && isspace(*s); s++) ; | ||||
|         return s; | ||||
| } | ||||
| 
 | ||||
| @ -44,17 +45,47 @@ char *string_replace(const char *needle, const char *replacement, | ||||
|         sprintf(tmp + strlen(tmp), "%s%s", replacement, start + strlen(needle)); | ||||
|         free(haystack); | ||||
| 
 | ||||
|         if (strstr(tmp, needle)) { | ||||
|                 return string_replace(needle, replacement, tmp); | ||||
|         } else { | ||||
|                 return tmp; | ||||
|         return tmp; | ||||
| } | ||||
| 
 | ||||
| char *string_append(char *a, const char *b, const char *sep) | ||||
| { | ||||
|         if (!a) | ||||
|                 return strdup(b); | ||||
| 
 | ||||
|         char *new; | ||||
|         if (!sep) | ||||
|                 asprintf(&new, "%s%s", a, b); | ||||
|         else | ||||
|                 asprintf(&new, "%s%s%s", a, sep, b); | ||||
|         free(a); | ||||
| 
 | ||||
|         return new; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| char **string_to_argv(const char *s) | ||||
| { | ||||
|         char *str = strdup(s); | ||||
|         char **argv = NULL; | ||||
|         char *p = strtok (str, " "); | ||||
|         int n_spaces = 0; | ||||
| 
 | ||||
|         while (p) { | ||||
|                 argv = realloc (argv, sizeof (char*) * ++n_spaces); | ||||
|                 argv[n_spaces-1] = p; | ||||
|                 p = strtok (NULL, " "); | ||||
|         } | ||||
|         argv = realloc (argv, sizeof (char*) * (n_spaces+1)); | ||||
|         argv[n_spaces] = NULL; | ||||
| 
 | ||||
|         return argv; | ||||
| } | ||||
| 
 | ||||
| int digit_count(int i) | ||||
| { | ||||
|         int len = 0; | ||||
|         if ( i == 0) { | ||||
|         if (i == 0) { | ||||
|                 return 1; | ||||
|         } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										6
									
								
								utils.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								utils.h
									
									
									
									
									
								
							| @ -8,8 +8,12 @@ char *lskip(char *str); | ||||
| char *string_replace(const char *needle, const char *replacement, | ||||
|                      char *haystack); | ||||
| 
 | ||||
| char *string_append(char *a, const char *b, const char *sep); | ||||
| 
 | ||||
| char **string_to_argv(const char *s); | ||||
| 
 | ||||
| /* exit with an error message */ | ||||
| void die(char * msg, int exit_value); | ||||
| void die(char *msg, int exit_value); | ||||
| 
 | ||||
| int digit_count(int i); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Sascha Kruse
						Sascha Kruse