replace r_line_cache stuff

This commit is contained in:
Sascha Kruse 2013-02-17 03:04:27 +01:00
parent 6de8d785ff
commit 8e29c4dc5b
2 changed files with 111 additions and 137 deletions

227
dunst.c
View File

@ -76,7 +76,6 @@ static bool pause_display = false;
static char **dmenu_cmd; static char **dmenu_cmd;
static unsigned long framec; static unsigned long framec;
static unsigned long sep_custom_col; static unsigned long sep_custom_col;
static r_line_cache line_cache;
bool dunst_grab_errored = false; bool dunst_grab_errored = false;
@ -111,10 +110,6 @@ str_array *extract_urls(const char *str);
void context_menu(void); void context_menu(void);
void run_script(notification *n); void run_script(notification *n);
void r_line_cache_init(r_line_cache *c);
void r_line_cache_append(r_line_cache *c, const char *s, ColorSet *col, bool is_begin, bool is_end);
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);
@ -501,87 +496,52 @@ void update_lists()
} }
} }
void r_line_cache_init(r_line_cache *c)
{
c->count = 0;
c->size = 0;
c->lines = NULL;
}
void r_line_cache_append(r_line_cache *c, const char *s, ColorSet *col, bool is_begin, bool is_end) GSList *do_word_wrap(char *text, int max_width)
{
if (!c || !s)
return;
/* resize cache if it's too small */
if (c->count >= c->size) {
c->size++;
c->lines = realloc(c->lines, c->size * sizeof(r_line));
}
c->count++;
c->lines[c->count-1].colors = col;
c->lines[c->count-1].str = g_strdup(s);
c->lines[c->count-1].is_begin = is_begin;
c->lines[c->count-1].is_end = is_end;
}
void r_line_cache_reset(r_line_cache *c)
{
for (int i = 0; i < c->count; i++) {
if (c->lines[i].str)
free(c->lines[i].str);
c->lines[i].str = NULL;
c->lines[i].colors = NULL;
}
c->count = 0;
}
int do_word_wrap(char *source, int max_width)
{ {
g_strstrip(source); GSList *result = NULL;
g_strstrip(text);
if (!source || strlen(source) == 0) if (!text || strlen(text) == 0)
return 0; return 0;
char *eol = source; char *begin = text;
char *end = text;
while (true) { while (true) {
if (*eol == '\0') if (*end == '\0') {
return 1; result = g_slist_append(result, g_strdup(begin));
if (*eol == '\n') { break;
*eol = '\0'; }
return 1 + do_word_wrap(eol + 1, max_width); if (*end == '\n') {
*end = ' ';
result = g_slist_append(result, g_strndup(begin, end - begin));
begin = ++end;
} }
if (word_wrap && max_width > 0) { if (word_wrap && max_width > 0 && textnw(dc, begin, (end - begin)) > max_width) {
if (textnw(dc, source, (eol - source) + 1) >= max_width) { /* find previous space */
/* go back to previous space */ char *space = end;
char *space = eol; while (space > begin && !isspace(*space))
while (space > source && !isspace(*space))
space--; space--;
if (space <= source) { if (space > begin) {
/* whe have a word longer than width, so we end = space;
* split mid-word. That one letter is
* collateral damage */
space = eol;
} }
*space = '\0'; result = g_slist_append(result, g_strndup(begin, end - begin));
if (*(space + 1) == '\0') begin = ++end;
return 1;
return 1 + do_word_wrap(space + 1, max_width);
}
}
eol++;
} }
end++;
} }
void add_notification_to_line_cache(notification *n, int max_width) return result;
}
char *generate_final_text(notification *n)
{ {
char *msg = g_strstrip(n->msg); char *msg = g_strstrip(n->msg);
char *buf; char *buf;
/* print dup_count and msg*/ /* print dup_count and msg*/
@ -615,18 +575,7 @@ void add_notification_to_line_cache(notification *n, int max_width)
buf = new_buf; buf = new_buf;
} }
return buf;
int linecnt = do_word_wrap(buf, max_width);
n->line_count = linecnt;
char *cur = buf;
for (int i = 0; i < linecnt; i++) {
r_line_cache_append(&line_cache, cur, n->colors,i == 0, i == linecnt-1);
while (*cur != '\0')
cur++;
cur++;
}
free(buf);
} }
int calculate_x_offset(int line_width, int text_width) int calculate_x_offset(int line_width, int text_width)
@ -752,39 +701,52 @@ void move_and_map(int width, int height)
} }
void fill_line_cache(int width) GSList *generate_render_texts(int width)
{ {
/* create cache with all lines */ GSList *render_texts = NULL;
for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) {
add_notification_to_line_cache(iter->data, width);
}
assert(line_cache.count > 0); for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) {
render_text *rt = g_malloc(sizeof(render_text));
rt->colors = ((notification*)iter->data)->colors;
char *text = generate_final_text(iter->data);
rt->lines = do_word_wrap(text, width);
free(text);
render_texts = g_slist_append(render_texts, rt);
}
/* add (x more) */ /* add (x more) */
if (indicate_hidden && queue->length > 0) { if (indicate_hidden && queue->length > 0) {
if (geometry.h != 1) { if (geometry.h != 1) {
char *tmp; render_text *rt = g_malloc(sizeof(render_text));
tmp = g_strdup_printf("(%d more)", queue->length); rt->colors = ((render_text *) g_slist_last(render_texts)->data)->colors;
ColorSet *last_colors = rt->lines = g_slist_append(NULL, g_strdup_printf("%d more)", queue->length));
line_cache.lines[line_cache.count-1].colors; render_texts = g_slist_append(render_texts, rt);
r_line_cache_append(&line_cache, tmp, last_colors, true, true);
free(tmp);
} else { } else {
char *old = line_cache.lines[0].str; GSList *last_lines = ((render_text *) g_slist_last(render_texts)->data)->lines;
char *new; GSList *last_line = g_slist_last(last_lines);
new = g_strdup_printf("%s (%d more)", old, queue->length); char *old = last_line->data;
char *new = g_strdup_printf("%s (%d more)", old, queue->length);
free(old); free(old);
line_cache.lines[0].str = new; last_line->data = new;
} }
} }
return render_texts;
}
void free_render_text(void *data) {
g_slist_free_full(((render_text *) data)->lines, g_free);
}
void free_render_texts(GSList *texts) {
g_slist_free_full(texts, free_render_text);
} }
void draw_win(void) void draw_win(void)
{ {
r_line_cache_reset(&line_cache);
update_screen_info(); update_screen_info();
int outer_width = calculate_width(); int outer_width = calculate_width();
@ -798,28 +760,31 @@ void draw_win(void)
width = outer_width - (2 * frame_width) - (2 * h_padding); width = outer_width - (2 * frame_width) - (2 * h_padding);
fill_line_cache(width); GSList *texts = generate_render_texts(width);
int line_count = 0;
for (GSList *iter = texts; iter; iter = iter->next) {
render_text *tmp = iter->data;
line_count += g_slist_length(tmp->lines);
}
/* if we have a dynamic width, calculate the actual width */ /* if we have a dynamic width, calculate the actual width */
if (width == 0) { if (width == 0) {
for (int i = 0; i < line_cache.count; i++) { for (GSList *iter = texts; iter; iter = iter->next) {
char *line = line_cache.lines[i].str; GSList *lines = ((render_text *) iter->data)->lines;
width = MAX(width, textw(dc, line)); for (GSList *iiter = lines; iiter; iiter = iiter->next)
width = MAX(width, textw(dc, iiter->data));
} }
outer_width = width + (2 * frame_width) + (2 * h_padding); outer_width = width + (2 * frame_width) + (2 * h_padding);
} }
/* resize dc to correct width */ /* resize dc to correct width */
int height = (line_cache.count * line_height) int height = (line_count * line_height)
+ displayed->length * 2 * padding + displayed->length * 2 * padding
+ ((indicate_hidden && queue->length > 0) ? 2 * padding : 0) + ((indicate_hidden && queue->length > 0 && geometry.h != 1) ? 2 * padding : 0)
+ (separator_height * (displayed->length - 1)) + (separator_height * (displayed->length - 1))
+ (2 * frame_width); + (2 * frame_width);
resizedc(dc, outer_width, height); resizedc(dc, outer_width, height);
/* draw frame /* draw frame
@ -835,38 +800,53 @@ void draw_win(void)
dc->y = frame_width; dc->y = frame_width;
dc->x = frame_width; dc->x = frame_width;
for (int i = 0; i < line_cache.count; i++) { for (GSList *iter = texts; iter; iter = iter->next) {
render_text *cur = iter->data;
ColorSet *colors = cur->colors;
int line_count = 0;
bool first_line = true;
for (GSList *iiter = cur->lines; iiter; iiter = iiter->next) {
char *line = iiter->data;
line_count++;
int pad = 0;
bool last_line = iiter->next == NULL;
if (first_line && last_line)
pad = 2*padding;
else if (first_line || last_line)
pad = padding;
dc->x = frame_width; dc->x = frame_width;
r_line line = line_cache.lines[i];
/* draw background */ /* draw background */
int pad = 0; drawrect(dc, 0, 0, width + (2*h_padding), pad + line_height, true, colors->BG);
pad += line.is_begin ? padding : 0;
pad += line.is_end ? padding : 0;
drawrect(dc, 0, 0, width + (2*h_padding), pad + line_height, true, line.colors->BG);
/* draw text */ /* draw text */
dc->x = calculate_x_offset(width, textw(dc, line.str)); dc->x = calculate_x_offset(width, textw(dc, line));
dc->y += ((line_height - font_h) / 2); dc->y += ((line_height - font_h) / 2);
dc->y += line.is_begin ? padding : 0; dc->y += first_line ? padding : 0;
drawtextn(dc, line.str, strlen(line.str), line.colors); drawtextn(dc, line, strlen(line), colors);
dc->y += line_height - ((line_height - font_h) / 2); dc->y += line_height - ((line_height - font_h) / 2);
dc->y += line.is_end ? padding : 0; dc->y += last_line ? padding : 0;
first_line = false;
}
/* draw separator */ /* draw separator */
if (separator_height > 0 && i < line_cache.count - 1 && line.is_end) { if (separator_height > 0 && iter->next) {
dc->x = frame_width; dc->x = frame_width;
double color; double color;
if (sep_color == AUTO) if (sep_color == AUTO)
color = calculate_foreground_color(line.colors->BG); color = calculate_foreground_color(colors->BG);
else if (sep_color == FOREGROUND) else if (sep_color == FOREGROUND)
color = line.colors->FG; color = colors->FG;
else if (sep_color == FRAME) else if (sep_color == FRAME)
color = framec; color = framec;
else { else {
@ -879,6 +859,8 @@ void draw_win(void)
} }
move_and_map(outer_width, height); move_and_map(outer_width, height);
free_render_texts(texts);
} }
char char
@ -1860,7 +1842,6 @@ int main(int argc, char *argv[])
now = time(&now); now = time(&now);
r_line_cache_init(&line_cache);
history = g_queue_new(); history = g_queue_new();
displayed = g_queue_new(); displayed = g_queue_new();
queue = g_queue_new(); queue = g_queue_new();

15
dunst.h
View File

@ -2,6 +2,7 @@
#pragma once #pragma once
#include <glib.h>
#include <stdbool.h> #include <stdbool.h>
#include "draw.h" #include "draw.h"
@ -84,18 +85,10 @@ typedef struct _keyboard_shortcut {
bool is_valid; bool is_valid;
} keyboard_shortcut; } keyboard_shortcut;
typedef struct _r_line { typedef struct _render_text {
ColorSet *colors; ColorSet *colors;
char *str; GSList *lines;
bool is_begin; } render_text;
bool is_end;
} r_line;
typedef struct r_line_cache {
int count;
int size;
r_line *lines;
} r_line_cache;
extern int verbosity; extern int verbosity;