replaced stack/queue with GList/GQueue

This commit is contained in:
Sascha Kruse 2013-02-16 05:25:51 +01:00
parent c4947fc0cd
commit 34714fe1f9
3 changed files with 82 additions and 256 deletions

View File

@ -4,140 +4,6 @@
#include "container.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 *str_array_malloc(void)
{ {

View File

@ -3,13 +3,6 @@
#include "dunst.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 { typedef struct _str_array {
int count; int count;
char **strs; char **strs;
@ -20,65 +13,5 @@ void str_array_dup_append(str_array *a, const char *str);
void str_array_append(str_array *a, char *str); void str_array_append(str_array *a, char *str);
void str_array_deep_free(str_array *a); 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 #endif
/* vim: set ts=8 sw=8 tw=0: */ /* vim: set ts=8 sw=8 tw=0: */

137
dunst.c
View File

@ -84,12 +84,14 @@ bool dunst_grab_errored = false;
int next_notification_id = 1; int next_notification_id = 1;
/* notification lists */ /* notification lists */
n_queue *queue = NULL; /* all new notifications get into here */ GQueue *queue = NULL; /* all new notifications get into here */
n_queue *displayed = NULL; /* currently displayed notifications */ GQueue *displayed = NULL; /* currently displayed notifications */
n_stack *history = NULL; /* history of displayed notifications */ GQueue *history = NULL; /* history of displayed notifications */
/* misc funtions */ /* misc funtions */
void apply_rules(notification * n); void apply_rules(notification * n);
int cmp_notification(const void *a, const void *b);
int cmp_notification_data(const void *va, const void *vb, void *data);
void check_timeouts(void); void check_timeouts(void);
char *fix_markup(char *str); char *fix_markup(char *str);
void handle_mouse_click(XEvent ev); void handle_mouse_click(XEvent ev);
@ -116,6 +118,33 @@ void r_line_cache_reset(r_line_cache *c);
void init_shortcut(keyboard_shortcut * shortcut); void init_shortcut(keyboard_shortcut * shortcut);
KeySym string_to_mask(char *str); KeySym string_to_mask(char *str);
int cmp_notification(const void *va, const void *vb)
{
notification *a = (notification*) va;
notification *b = (notification*) vb;
if (!sort)
return 1;
if (a == NULL && b == NULL)
return 1;
else if (a == NULL)
return 1;
else if (b == NULL)
return -1;
if (a->urgency != b->urgency) {
return b->urgency - a->urgency;
} else {
return a->timestamp - b->timestamp;
}
}
int cmp_notification_data(const void *va, const void *vb, void *data)
{
return cmp_notification(va, vb);
}
str_array *extract_urls( const char * to_match) str_array *extract_urls( const char * to_match)
{ {
static bool is_initialized = false; static bool is_initialized = false;
@ -164,16 +193,14 @@ str_array *extract_urls( const char * to_match)
void context_menu(void) { void context_menu(void) {
char *dmenu_input = NULL; char *dmenu_input = NULL;
n_queue *iter = displayed; for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) {
for (int i = 0; i < ((notification*)iter->data)->urls->count; i++) {
while (iter) {
for (int i = 0; i < iter->n->urls->count; i++) {
dmenu_input = string_append(dmenu_input, dmenu_input = string_append(dmenu_input,
(iter->n->urls->strs)[i], "\n"); (((notification*)iter->data)->urls->strs)[i], "\n");
} }
iter = iter->next;
} }
if (!dmenu_input) if (!dmenu_input)
return; return;
@ -409,11 +436,11 @@ void apply_rules(notification * n)
void check_timeouts(void) void check_timeouts(void)
{ {
/* nothing to do */ /* nothing to do */
if (!displayed) if (displayed->length == 0)
return; return;
for (n_queue *iter = displayed; iter; iter = iter->next) { for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) {
notification *n = iter->n; notification *n = iter->data;
/* don't timeout when user is idle */ /* don't timeout when user is idle */
if (is_idle()) { if (is_idle()) {
@ -443,9 +470,8 @@ void update_lists()
check_timeouts(); check_timeouts();
if (pause_display) { if (pause_display) {
while (displayed) { while (displayed->length > 0) {
notification *n = n_queue_dequeue(&displayed); g_queue_insert_sorted(queue, g_queue_pop_head(queue), cmp_notification_data, NULL);
n_queue_enqueue(&queue, n);
} }
return; return;
} }
@ -462,14 +488,14 @@ void update_lists()
/* move notifications from queue to displayed */ /* move notifications from queue to displayed */
while (queue) { while (queue->length > 0) {
if (limit > 0 && n_queue_len(&displayed) >= limit) { if (limit > 0 && displayed->length >= limit) {
/* the list is full */ /* the list is full */
break; break;
} }
notification *n = n_queue_dequeue(&queue); notification *n = g_queue_pop_head(queue);
if (!n) if (!n)
return; return;
@ -478,7 +504,7 @@ void update_lists()
run_script(n); run_script(n);
} }
n_queue_enqueue(&displayed, n); g_queue_insert_sorted(displayed, n, cmp_notification_data, NULL);
} }
} }
@ -736,18 +762,17 @@ void move_and_map(int width, int height)
void fill_line_cache(int width) void fill_line_cache(int width)
{ {
/* create cache with all lines */ /* create cache with all lines */
for (n_queue *iter = displayed; iter; iter = iter->next) { for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) {
add_notification_to_line_cache(iter->n, width); add_notification_to_line_cache(iter->data, width);
} }
assert(line_cache.count > 0); assert(line_cache.count > 0);
/* add (x more) */ /* add (x more) */
int queue_cnt = n_queue_len(&queue); if (indicate_hidden && queue->length > 0) {
if (indicate_hidden && queue_cnt > 0) {
if (geometry.h != 1) { if (geometry.h != 1) {
char *tmp; char *tmp;
tmp = g_strdup_printf("(%d more)", queue_cnt); tmp = g_strdup_printf("(%d more)", queue->length);
ColorSet *last_colors = ColorSet *last_colors =
line_cache.lines[line_cache.count-1].colors; line_cache.lines[line_cache.count-1].colors;
r_line_cache_append(&line_cache, tmp, last_colors, true, true); r_line_cache_append(&line_cache, tmp, last_colors, true, true);
@ -755,7 +780,7 @@ void fill_line_cache(int width)
} else { } else {
char *old = line_cache.lines[0].str; char *old = line_cache.lines[0].str;
char *new; char *new;
new = g_strdup_printf("%s (%d more)", old, queue_cnt); new = g_strdup_printf("%s (%d more)", old, queue->length);
free(old); free(old);
line_cache.lines[0].str = new; line_cache.lines[0].str = new;
} }
@ -795,9 +820,9 @@ void draw_win(void)
/* resize dc to correct width */ /* resize dc to correct width */
int height = (line_cache.count * line_height) int height = (line_cache.count * line_height)
+ n_queue_len(&displayed) * 2 * padding + displayed->length * 2 * padding
+ ((indicate_hidden && n_queue_len(&queue) > 0) ? 2 * padding : 0) + ((indicate_hidden && queue->length > 0) ? 2 * padding : 0)
+ (separator_height * (n_queue_len(&displayed) - 1)) + (separator_height * (displayed->length - 1))
+ (2 * frame_width); + (2 * frame_width);
@ -923,8 +948,8 @@ void handle_mouse_click(XEvent ev)
if (ev.xbutton.button == Button1) { if (ev.xbutton.button == Button1) {
int y = separator_height; int y = separator_height;
notification *n = NULL; notification *n = NULL;
for (n_queue *iter = displayed; iter; iter = iter->next) { for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) {
n = iter->n; n = iter->data;
int text_h = MAX(font_h, line_height) * n->line_count; int text_h = MAX(font_h, line_height) * n->line_count;
int padding = 2 * h_padding; int padding = 2 * h_padding;
@ -969,7 +994,7 @@ void handleXEvents(void)
&& XLookupKeysym(&ev.xkey, 0) == close_ks.sym && XLookupKeysym(&ev.xkey, 0) == close_ks.sym
&& close_ks.mask == ev.xkey.state) { && close_ks.mask == ev.xkey.state) {
if (displayed) { if (displayed) {
close_notification(displayed->n, 2); close_notification(g_queue_peek_head_link(displayed)->data, 2);
} }
} }
if (history_ks.str if (history_ks.str
@ -993,28 +1018,28 @@ void handleXEvents(void)
void move_all_to_history() void move_all_to_history()
{ {
while (displayed) { while (displayed->length > 0) {
close_notification(displayed->n, 2); close_notification(g_queue_peek_head_link(displayed)->data, 2);
} }
notification *n = n_queue_dequeue(&queue); notification *n = g_queue_pop_head(queue);
while (n) { while (n) {
n_stack_push(&history, n); g_queue_push_tail(history, n);
n = n_queue_dequeue(&queue); n = g_queue_pop_head(queue);
} }
} }
void history_pop(void) void history_pop(void)
{ {
if (!history) if (g_queue_is_empty(history))
return; return;
notification *n = n_stack_pop(&history); notification *n = g_queue_pop_tail(history);
n->redisplayed = true; n->redisplayed = true;
n->start = 0; n->start = 0;
n->timeout = sticky_history ? 0 : n->timeout; n->timeout = sticky_history ? 0 : n->timeout;
n_queue_enqueue(&queue, n); g_queue_push_head(queue, n);
if (!visible) { if (!visible) {
map_win(); map_win();
@ -1088,8 +1113,8 @@ int init_notification(notification * n, int id)
n->dup_count = 0; n->dup_count = 0;
/* check if n is a duplicate */ /* check if n is a duplicate */
for (n_queue *iter = queue; iter; iter = iter->next) { for (GList *iter = g_queue_peek_head_link(queue); iter; iter = iter->next) {
notification *orig = iter->n; notification *orig = iter->data;
if (strcmp(orig->appname, n->appname) == 0 if (strcmp(orig->appname, n->appname) == 0
&& strcmp(orig->msg, n->msg) == 0) { && strcmp(orig->msg, n->msg) == 0) {
orig->dup_count++; orig->dup_count++;
@ -1098,8 +1123,8 @@ int init_notification(notification * n, int id)
} }
} }
for (n_queue *iter = displayed; iter; iter = iter->next) { for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) {
notification *orig = iter->n; notification *orig = iter->data;
if (strcmp(orig->appname, n->appname) == 0 if (strcmp(orig->appname, n->appname) == 0
&& strcmp(orig->msg, n->msg) == 0) { && strcmp(orig->msg, n->msg) == 0) {
orig->dup_count++; orig->dup_count++;
@ -1144,7 +1169,7 @@ int init_notification(notification * n, int id)
close_notification(n, 2); close_notification(n, 2);
printf("skipping notification: %s %s\n", n->body, n->summary); printf("skipping notification: %s %s\n", n->body, n->summary);
} else { } else {
n_queue_enqueue(&queue, n); g_queue_insert_sorted(queue, n, cmp_notification_data, NULL);
} }
char *tmp = g_strconcat(n->summary, " ", n->body, NULL); char *tmp = g_strconcat(n->summary, " ", n->body, NULL);
@ -1171,21 +1196,21 @@ int close_notification_by_id(int id, int reason)
{ {
notification *target = NULL; notification *target = NULL;
for (n_queue *iter = displayed; iter; iter = iter->next) { for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) {
notification *n = iter->n; notification *n = iter->data;
if (n->id == id) { if (n->id == id) {
n_queue_remove(&displayed, n); g_queue_remove(displayed, n);
n_stack_push(&history, n); g_queue_push_tail(history, n);
target = n; target = n;
break; break;
} }
} }
for (n_queue *iter = queue; iter; iter = iter->next) { for (GList *iter = g_queue_peek_head_link(queue); iter; iter = iter->next) {
notification *n = iter->n; notification *n = iter->data;
if (n->id == id) { if (n->id == id) {
n_queue_remove(&queue, n); g_queue_remove(queue, n);
n_stack_push(&history, n); g_queue_push_tail(history, n);
target = n; target = n;
break; break;
} }
@ -1315,7 +1340,7 @@ void run(void)
/* move messages from notification_queue to displayed_notifications */ /* move messages from notification_queue to displayed_notifications */
update_lists(); update_lists();
if (displayed) { if (displayed->length > 0) {
if (!visible) { if (!visible) {
map_win(); map_win();
} else { } else {
@ -1535,7 +1560,7 @@ void setup(void)
void map_win(void) void map_win(void)
{ {
/* window is already mapped or there's nothing to show */ /* window is already mapped or there's nothing to show */
if (visible || !displayed) { if (visible || g_queue_is_empty(displayed)) {
return; return;
} }
@ -1843,7 +1868,9 @@ int main(int argc, char *argv[])
now = time(&now); now = time(&now);
r_line_cache_init(&line_cache); r_line_cache_init(&line_cache);
history = g_queue_new();
displayed = g_queue_new();
queue = g_queue_new();
rules.count = LENGTH(default_rules); rules.count = LENGTH(default_rules);
rules.rules = calloc(rules.count, sizeof(rule_t)); rules.rules = calloc(rules.count, sizeof(rule_t));