summaryrefslogtreecommitdiff
path: root/slashapp/display.c
diff options
context:
space:
mode:
Diffstat (limited to 'slashapp/display.c')
-rw-r--r--slashapp/display.c738
1 files changed, 518 insertions, 220 deletions
diff --git a/slashapp/display.c b/slashapp/display.c
index f74bf626b..d5cf66208 100644
--- a/slashapp/display.c
+++ b/slashapp/display.c
@@ -1,28 +1,71 @@
-/*###################################################################*/
-/*## ##*/
-/*###################################################################*/
+/* tick-a-stat, a GNOME panel applet
+ * (C) 1999 John Ellis
+ *
+ * Author: John Ellis
+ *
+ */
-#include "slashapp.h"
-#include "back.xpm"
#include "noimage.xpm"
+#include "slashapp.h"
-static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *icon,
- gint offset, gint center, gint show_count, gint delay);
-static void free_info_line(AppData *ad, InfoData *id);
-static gint check_info_for_removal(AppData *ad, InfoData *id);
-static GList *next_info_line(AppData *ad);
static void redraw_display(AppData *ad);
-static void draw_pixmap(AppData *ad, GdkPixmap *smap, GdkPixmap *tmap, gint x, gint y, gint w, gint h, gint xo, gint yo);
+static void draw_pixmap(AppData *ad, GdkPixmap *smap, GdkBitmap *mask, GdkPixmap *tmap, gint x, gint y, gint w, gint h, gint xo, gint yo);
+
+static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *icon,
+ gint offset, gint center, gint show_count, gint delay, gint priority);
+static void free_info_line(AppData *ad, InfoData *id);
+
+
+static InfoData *next_info_line(AppData *ad);
+
static void scroll_display_up(AppData *ad, gint m);
-static void draw_display_line(AppData *ad);
+static gint draw_display_line(AppData *ad);
static gint update_display_cb(gpointer data);
+
+
+static gint line_is_in_click_list(AppData *ad, InfoData *id);
+static void free_click_list(AppData *ad);
static void register_click_func(AppData *ad, InfoData *id);
static void scroll_click_func(AppData *ad, gint m);
static int display_click(GtkWidget *w, GdkEventButton *event, gpointer data);
static void display_motion(GtkWidget *w, GdkEventMotion *event, gpointer data);
+static void calc_display_sizes(AppData *ad);
+static void create_display_pixmaps(AppData *ad);
+
+/*
+ *----------------------------------------------------------------------------
+ * display generic drawing
+ *----------------------------------------------------------------------------
+ */
+
+static void redraw_display(AppData *ad)
+{
+ gdk_window_set_back_pixmap(ad->draw_area->window,ad->display,FALSE);
+ gdk_window_clear(ad->draw_area->window);
+}
+
+static void draw_pixmap(AppData *ad, GdkPixmap *smap, GdkBitmap *mask, GdkPixmap *tmap, gint x, gint y, gint w, gint h, gint xo, gint yo)
+{
+ gdk_gc_set_clip_mask(ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], mask);
+ gdk_gc_set_clip_origin(ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], x - xo, y - yo);
+
+ gdk_draw_pixmap(tmap,
+ ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)],
+ smap, xo, yo, x, y, w, h);
+
+ gdk_gc_set_clip_mask(ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], NULL);
+ gdk_gc_set_clip_origin(ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)], 0, 0);
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * display line addition/removal (private)
+ *----------------------------------------------------------------------------
+ */
+
static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *icon,
- gint offset, gint center, gint show_count, gint delay)
+ gint offset, gint center, gint show_count, gint delay, gint priority)
{
InfoData *id;
if (!text) return NULL;
@@ -31,6 +74,8 @@ static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *ico
id->click_func = NULL;
id->data = NULL;
id->free_func = NULL;
+ id->pre_func = NULL;
+ id->end_func = NULL;
id->text = g_strdup(text);
@@ -72,29 +117,15 @@ static InfoData *create_info_line(gchar *text, gchar *icon_path, GtkWidget *ico
id->show_count = show_count;
id->end_delay = delay;
+ id->priority = priority;
return id;
}
static void free_info_line(AppData *ad, InfoData *id)
{
- GList *list = ad->click_list;
-
if (!id) return;
- while(list)
- {
- GList *w = list;
- ClickData *cd = w->data;
- list = list->next;
-
- if (cd->line_id == id)
- {
- ad->click_list = g_list_remove(ad->click_list, cd);
- g_free(cd);
- }
- }
-
g_free(id->text);
g_free(id->icon_path);
@@ -103,25 +134,33 @@ static void free_info_line(AppData *ad, InfoData *id)
if (id->data && id->free_func) id->free_func(id->data);
g_free(id);
+ return;
+ ad = NULL;
}
void free_all_info_lines(AppData *ad)
{
- GList *list = ad->text;
+ GList *work = ad->info_list;
- if (!list) return;
- while(list)
+ while(work)
{
- InfoData *id = list->data;
- free_info_line(ad, id);
- list = list->next;
+ InfoData *id = work->data;
+ work = work->next;
+ ad->info_list = g_list_remove(ad->info_list, id);
+ if (!line_is_in_click_list(ad, id)) free_info_line(ad, id);
}
- g_list_free(ad->text);
- ad->text = NULL;
+
+ free_click_list(ad);
}
+/*
+ *----------------------------------------------------------------------------
+ * display line addition/removal (public)
+ *----------------------------------------------------------------------------
+ */
+
InfoData *add_info_line(AppData *ad, gchar *text, gchar *icon_path, gint offset, gint center,
- gint show_count, gint delay)
+ gint show_count, gint delay, gint priority)
{
InfoData *id;
GtkWidget *icon = NULL;
@@ -134,201 +173,273 @@ InfoData *add_info_line(AppData *ad, gchar *text, gchar *icon_path, gint offset,
icon = gnome_pixmap_new_from_xpm_d(noimage_xpm);
}
- id = create_info_line(text, icon_path, icon, offset, center, show_count, delay);
+ id = create_info_line(text, icon_path, icon, offset, center, show_count, delay, priority);
if (id)
{
- ad->text = g_list_append(ad->text, id);
- ad->text_lines++;
+ ad->info_list = g_list_append(ad->info_list, id);
}
return id;
}
InfoData *add_info_line_with_pixmap(AppData *ad, gchar *text, GtkWidget *icon, gint offset, gint center,
- gint show_count, gint delay)
+ gint show_count, gint delay, gint priority)
{
InfoData *id;
- id = create_info_line(text, NULL, icon, offset, center, show_count, delay);
+ id = create_info_line(text, NULL, icon, offset, center, show_count, delay, priority);
if (id)
{
- ad->text = g_list_append(ad->text, id);
- ad->text_lines++;
+ ad->info_list = g_list_append(ad->info_list, id);
}
return id;
}
+void set_info_click_signal(InfoData *id, void (*click_func)(gpointer data, InfoData *id, AppData *ad),
+ gpointer data, void (*free_func)(gpointer data))
+{
+ if (!id) return;
+ id->click_func = click_func;
+ id->data = data;
+ id->free_func = free_func;
+}
+
+void set_info_signals(InfoData *id,
+ void (*click_func)(gpointer data, InfoData *id, AppData *ad),
+ void (*free_func)(gpointer data),
+ void (*pre_func)(gpointer data, InfoData *id, AppData *ad),
+ void (*end_func)(gpointer data, InfoData *id, AppData *ad),
+ gpointer data)
+{
+ if (!id) return;
+ id->click_func = click_func;
+ id->free_func = free_func;
+ id->pre_func = pre_func;
+ id->end_func = end_func;
+ id->data = data;
+}
+
void remove_info_line(AppData *ad, InfoData *id)
{
+ GList *work;
if (!id) return;
- if (ad->current_text && ad->current_text->data == id)
- {
- /* if current line is being displayed, schedule to remove */
- id->show_count = 1;
- }
- else
+
+ work = g_list_find(ad->info_list, id);
+
+ if (work)
{
- ad->text = g_list_remove(ad->text, id);
- free_info_line(ad, id);
- ad->text_lines--;
+ ad->info_list = g_list_remove(ad->info_list, id);
+ if (!line_is_in_click_list(ad, id))
+ {
+ if (ad->info_current == id)
+ ad->free_current = TRUE;
+ else
+ free_info_line(ad, id);
+ }
}
}
void remove_all_lines(AppData *ad)
{
- GList *list;
-
- list = ad->text;
- while (list)
+ GList *work = ad->info_list;
+ while (work)
{
- InfoData *id = list->data;
- list = list->next;
- remove_info_line(ad, id);
+ InfoData *id = work->data;
+ work = work->next;
+ ad->info_list = g_list_remove(ad->info_list, id);
+ if (!line_is_in_click_list(ad, id)) free_info_line(ad, id);
}
}
-void set_info_click_signal(InfoData *id, void (*click_func)(AppData *ad, gpointer data),
- gpointer data, void (*free_func)(gpointer data))
+/*
+ *----------------------------------------------------------------------------
+ * display internal management
+ *----------------------------------------------------------------------------
+ */
+
+static gint line_is_in_line_list(AppData *ad, InfoData *id)
{
- if (!id) return;
- id->click_func = click_func;
- id->data = data;
- id->free_func = free_func;
+ GList *work = NULL;
+ work = g_list_find(ad->info_list, id);
+
+ if (work) return TRUE;
+ return FALSE;
}
-static gint check_info_for_removal(AppData *ad, InfoData *id)
+static gint info_line_unref(AppData *ad, InfoData *id)
{
if (id->show_count > 0)
{
id->show_count--;
- if (id->show_count == 0)
+ if (id->show_count < 1)
{
remove_info_line(ad, id);
- if (!ad->text)
- {
- ad->current_text = NULL;
- return TRUE;
- }
+ return TRUE;
}
}
return FALSE;
}
-static GList *next_info_line(AppData *ad)
+static InfoData *first_unshown_info_line(GList *list)
{
- GList *list = ad->text;
-
- /* check for the first unshown info item, they have priority*/
- while(list)
+ GList *work = list;
+ InfoData *ret_id = NULL;
+ while(work)
{
InfoData *id = list->data;
- if (!id->shown) return list;
- list = list->next;
+ if (!id->shown)
+ {
+ if (!ret_id || (ret_id && id->priority > ret_id->priority))
+ {
+ ret_id = id;
+ }
+ }
+ work = work->next;
}
- /* all have been shown, just return the next line */
- list = ad->current_text->next;
- if (!list) list = ad->text;
- return list;
+ return ret_id;
}
-static void redraw_display(AppData *ad)
+static InfoData *first_info_line(GList *list)
{
- gdk_window_set_back_pixmap(ad->draw_area->window,ad->display,FALSE);
- gdk_window_clear(ad->draw_area->window);
+ InfoData *id = first_unshown_info_line(list);
+ if (id) return id;
+
+ if (list) return list->data;
+
+ return NULL;
}
-static void draw_pixmap(AppData *ad, GdkPixmap *smap, GdkPixmap *tmap, gint x, gint y, gint w, gint h, gint xo, gint yo)
+
+static InfoData *next_info_line_from_line(AppData *ad, InfoData *id)
{
- gdk_draw_pixmap(tmap,
- ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)],
- smap, xo, yo, x, y, w, h);
+ GList *work;
+ InfoData *wid;
+
+ work = g_list_find(ad->info_list, id);
+ if (!work)
+ {
+ return first_info_line(ad->info_list);
+ }
+
+ wid = first_unshown_info_line(ad->info_list);
+ if (wid) return wid;
+
+ if (work->next)
+ {
+ work = work->next;
+ return work->data;
+ }
+
+ if (ad->info_list->data == id && id->show_count != 1) return NULL;
+
+ return ad->info_list->data;
+}
+
+static InfoData *next_info_line(AppData *ad)
+{
+ InfoData *id;
+
+ if (!ad->info_list) return NULL;
+
+ if (ad->info_next && line_is_in_line_list(ad, ad->info_next))
+ {
+ id = ad->info_next;
+ ad->info_next = NULL;
+ return id;
+ }
+
+ id = first_unshown_info_line(ad->info_list);
+ if (id) return id;
+
+ return ad->info_list->data;
}
-static void scroll_display_up(AppData *ad, gint m)
+static void display_info_finished(AppData *ad, InfoData *id)
{
- draw_pixmap (ad, ad->display, ad->disp_buf, 0, 0, ad->width, ad->height - m, 0, m);
- draw_pixmap (ad, ad->disp_buf, ad->display, 0, 0, ad->width, ad->height - m, 0, 0);
- draw_pixmap (ad, ad->background, ad->display, 0, ad->height - m, ad->width, m, 0, ad->height - m);
- if (ad->current_text)
+ if (id->end_func) id->end_func(id->data, id, ad);
+ if (id == ad->info_current)
{
- InfoData *id = ad->current_text->data;
- if (id->icon && id->icon_h > ad->current_line_pos * ad->scroll_height)
+ ad->info_next = next_info_line_from_line(ad, id);
+ if (ad->free_current)
{
- gint x,y;
- gint xo, yo;
- gint w, h;
-
- x = 2;
- y = ad->height - m;
- xo = 0;
- if (m == ad->scroll_height)
- yo = ad->current_line_pos * ad->scroll_height;
- else
- yo = (ad->current_line_pos * ad->scroll_height) + ad->scroll_height - ad->scroll_pos;
- w = id->icon_w;
- h = m;
- if (h + yo > id->icon_h) h = id->icon_h - yo;
- if (yo < id->icon_h && h > 0)
- draw_pixmap (ad, GNOME_PIXMAP(id->icon)->pixmap, ad->display,
- x, y, w, h, xo, yo);
+ free_info_line(ad, ad->info_current);
+ ad->free_current = FALSE;
}
+ ad->info_current = NULL;
}
- redraw_display(ad);
- scroll_click_func(ad, m);
+ info_line_unref(ad, id);
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * display icon drawing
+ *----------------------------------------------------------------------------
+ */
+
+/* returns the number of lines drawn, 0 means end of icon */
+static gint display_draw_icon(AppData *ad, InfoData *id, gint n)
+{
+ if (id->icon && id->icon_h >= ad->y_pos - n)
+ {
+ gint x,y;
+ gint xo, yo;
+ gint w, h;
+
+ x = 2;
+ y = ad->height - n;
+ xo = 0;
+ yo = ad->y_pos - n;
+ w = id->icon_w;
+ h = n;
+ if (h > id->icon_h - yo) h = id->icon_h - yo;
+ draw_pixmap (ad, GNOME_PIXMAP(id->icon)->pixmap, GNOME_PIXMAP(id->icon)->mask,
+ ad->display, x, y, w, h, xo, yo);
+ return h;
+ }
+
+ return 0;
}
-static void draw_display_line(AppData *ad)
+/*
+ *----------------------------------------------------------------------------
+ * display line drawing
+ *----------------------------------------------------------------------------
+ */
+
+static gint draw_display_line(AppData *ad)
{
InfoData *id;
- gint new_x_pos;
gchar c;
GdkFont *font;
+ gint new_line = FALSE;
+ int len; /* byte length of a character */
- if (!ad->text) return;
- if (!ad->current_text) ad->current_text = ad->text;
- id = ad->current_text->data;
- if (!id) return;
+ if (!ad->info_current && !ad->info_list) return TRUE;
+
+ if (!ad->info_current)
+ {
+ ad->info_current = next_info_line(ad);
+ if (!ad->info_current) return TRUE;
+
+ ad->text_pos = 0;
+ ad->x_pos = 0;
+ ad->y_pos = 0;
+ }
+
+ id = ad->info_current;
+ id->shown = TRUE;
font = ad->draw_area->style->font;
- if (ad->new_line)
+ if (ad->x_pos == 0)
{
- if (ad->text_pos > id->length)
- {
- GList *temp;
- if (id->icon && id->icon_h > ad->current_line_pos * ad->text_height)
- {
- ad->scroll_pos = ad->scroll_height;
- ad->current_line_pos ++;
- if (id->icon_h <= ad->current_line_pos * ad->text_height)
- ad->scroll_count = id->end_delay / 10 * (1000 / UPDATE_DELAY);
- return;
- }
- id->shown = TRUE;
- ad->text_pos = 0;
- temp = next_info_line(ad);
- ad->current_text = NULL;
- ad->current_line_pos = 0;
- check_info_for_removal(ad, id);
- if (!ad->text || !temp) return;
- ad->current_text = temp;
- id = ad->current_text->data;
- }
- ad->new_line = FALSE;
- ad->x_pos = 0;
- if (id->icon && id->icon_h > ad->current_line_pos * ad->text_height)
+ /* add or do any callbacks if new info */
+ if (ad->y_pos == 0)
{
- gint x,y;
- gint xo, yo;
- gint w, h;
- x = 2;
- y = ad->height - ad->text_height;
- xo = 0;
- yo = ad->current_line_pos * ad->text_height;
- w = id->icon_w;
- h = id->icon_h - (ad->current_line_pos * ad->text_height);
- draw_pixmap (ad, GNOME_PIXMAP(id->icon)->pixmap, ad->display, x, y, w, h, xo, yo);
+ if (id->pre_func) id->pre_func(id->data, id, ad);
+ if (id->click_func) register_click_func(ad, id);
+ ad->y_pos = ad->scroll_height;
}
if (id->center && !id->icon)
{
@@ -343,76 +454,119 @@ static void draw_display_line(AppData *ad)
}
}
else
- ad->x_pos = id->offset;
-
- /* add the click check */
- if (id->click_func && ad->current_line_pos == 0)
{
- register_click_func(ad, id);
+ display_draw_icon(ad, id, ad->scroll_height);
+ ad->x_pos += id->offset;
}
}
+ /* skip leading space on new line */
c = id->text[ad->text_pos];
+ len = mblen(&id->text[ad->text_pos], id->length);
if (ad->x_pos == id->offset && c == ' ' &&
- ad->text_pos < id->length - 1 && id->text[ad->text_pos +1] != ' ')
+ ad->text_pos < id->length - 1 && id->text[ad->text_pos + len] != ' ')
{
- ad->text_pos++;
+ ad->text_pos += len;
c = id->text[ad->text_pos];
+ len = mblen(&id->text[ad->text_pos], id->length);
}
- new_x_pos = ad->x_pos + gdk_char_width (font, c);
gdk_draw_text(ad->display, font,
- ad->draw_area->style->black_gc,
- ad->x_pos, ad->height - ad->text_y_line, id->text + ad->text_pos, 1);
+ ad->draw_area->style->fg_gc[GTK_WIDGET_STATE(ad->draw_area)],
+ ad->x_pos, ad->height - ad->text_y_line, id->text + ad->text_pos, len);
+ ad->x_pos += gdk_text_width(font, &id->text[ad->text_pos], len);
+ ad->text_pos += len;
- ad->text_pos ++;
- if (ad->text_pos > id->length)
+ if (ad->text_pos >= id->length)
{
- ad->new_line = TRUE;
+ new_line = TRUE;
}
else
{
- ad->x_pos = new_x_pos;
c = id->text[ad->text_pos];
- if (ad->x_pos + gdk_char_width (font, c) > ad->width)
+ len = mblen(&id->text[ad->text_pos], id->length);
+ if (ad->x_pos + gdk_text_width(font, &id->text[ad->text_pos], len) > ad->width)
{
- ad->new_line = TRUE;
+ new_line = TRUE;
}
else if (c == '\n')
{
ad->text_pos++;
- ad->new_line = TRUE;
+ new_line = TRUE;
}
else if (c == ' ' && ad->text_pos < id->length)
{
gint word_length;
- gint l = strlen(id->text);
gint p;
p = ad->text_pos + 1;
- while (p < l && id->text[p] != ' ' && id->text[p] != '\n') p++;
- word_length = gdk_text_width(font, id->text + ad->text_pos,
- p - ad->text_pos);
+ while (p < id->length && id->text[p] != ' ' && id->text[p] != '\n') p++;
+ word_length = gdk_text_width(font, id->text + ad->text_pos, p - ad->text_pos);
if (ad->x_pos + word_length > ad->width)
{
ad->text_pos++;
- ad->new_line = TRUE;
+ new_line = TRUE;
}
}
}
- if (ad->new_line)
+ if (new_line)
{
- ad->current_line_pos ++;
+ ad->x_pos = 0;
ad->scroll_pos = ad->scroll_height;
-
- if (ad->text_pos > id->length)
+ if (ad->text_pos >= id->length)
+ {
ad->scroll_count = id->end_delay / 10 * (1000 / UPDATE_DELAY);
- else
+ if (!id->icon || id->icon_h <= ad->y_pos)
+ {
+ display_info_finished(ad, ad->info_current);
+ }
+ }
+ else
+ {
ad->scroll_count = ad->scroll_delay / 10 * (1000 / UPDATE_DELAY);
+ }
+ }
+
+ return new_line;
+}
+/*
+ *----------------------------------------------------------------------------
+ * display scrolling
+ *----------------------------------------------------------------------------
+ */
+
+static void scroll_display_up(AppData *ad, gint n)
+{
+ draw_pixmap (ad, ad->display, NULL, ad->disp_buf, 0, 0, ad->width, ad->height - n, 0, n);
+ draw_pixmap (ad, ad->disp_buf, NULL, ad->display, 0, 0, ad->width, ad->height - n, 0, 0);
+ draw_pixmap (ad, ad->background, NULL, ad->display, 0, ad->height - n, ad->width, n, 0, ad->height - n);
+ ad->y_pos += n;
+ if (ad->info_current)
+ {
+ gint drawn = display_draw_icon(ad, ad->info_current, n);
+ if (ad->text_pos >= ad->info_current->length)
+ {
+ if (drawn > 0)
+ {
+ ad->scroll_pos += drawn;
+ }
+ else
+ {
+ display_info_finished(ad, ad->info_current);
+ }
+ }
}
+ redraw_display(ad);
+ scroll_click_func(ad, n);
}
+/*
+ *----------------------------------------------------------------------------
+ * main display loop
+ *----------------------------------------------------------------------------
+ */
+
static gint update_display_cb(gpointer data)
{
AppData *ad = data;
@@ -424,21 +578,23 @@ static gint update_display_cb(gpointer data)
return TRUE;
}
- if (ad->new_line && ad->scroll_pos > 0)
+ if (!ad->info_list && !ad->info_current) return TRUE;
+
+ /* draw the scrolling */
+ if (ad->scroll_pos > 0)
{
- /* draw the scrolling */
+ gint n;
if (ad->smooth_scroll)
{
- gint s = ad->scroll_speed;
- if (ad->scroll_pos - s < 1) s = ad->scroll_pos - 1;
- scroll_display_up(ad, s);
+ n = ad->scroll_speed;
+ if (ad->scroll_pos - n < 0) n = ad->scroll_pos;
}
else
{
- if (ad->scroll_pos - ad->scroll_speed < 1)
- scroll_display_up(ad, ad->scroll_height);
+ n = ad->scroll_pos;
}
- ad->scroll_pos -= ad->scroll_speed;
+ scroll_display_up(ad, n);
+ ad->scroll_pos -= n;
return TRUE;
}
@@ -449,13 +605,18 @@ static gint update_display_cb(gpointer data)
}
else
{
- draw_display_line(ad);
- while(!ad->new_line) draw_display_line(ad);
+ while(!draw_display_line(ad));
redraw_display(ad);
}
return TRUE;
}
+/*
+ *----------------------------------------------------------------------------
+ * display mouse and pointer functions
+ *----------------------------------------------------------------------------
+ */
+
void set_mouse_cursor (AppData *ad, gint icon)
{
GdkCursor *cursor = gdk_cursor_new (icon);
@@ -463,6 +624,33 @@ void set_mouse_cursor (AppData *ad, gint icon)
gdk_cursor_destroy (cursor);
}
+static gint line_is_in_click_list(AppData *ad, InfoData *id)
+{
+ GList *work = ad->click_list;
+
+ while(work)
+ {
+ ClickData *cd = work->data;
+ if (id == cd->line_id) return TRUE;
+ work = work->next;
+ }
+
+ return FALSE;
+}
+
+static void free_click_list(AppData *ad)
+{
+ GList * work = ad->click_list;
+ while (work)
+ {
+ ClickData *cd = work->data;
+ work = work->next;
+ ad->click_list = g_list_remove(ad->click_list, cd);
+ if (!line_is_in_click_list(ad, cd->line_id)) free_info_line(ad, cd->line_id);
+ g_free(cd);
+ }
+}
+
static void register_click_func(AppData *ad, InfoData *id)
{
ClickData *cd;
@@ -473,19 +661,20 @@ static void register_click_func(AppData *ad, InfoData *id)
cd->line_id = id;
cd->click_func = id->click_func;
- cd->data = id->data;
cd->x = 0;
cd->y = ad->height - ad->scroll_height;
cd->w = ad->width;
cd->h = ad->scroll_height;
+ cd->free_id = FALSE;
+
ad->click_list = g_list_append(ad->click_list, cd);
scroll_click_func(ad, 0);
}
-static void scroll_click_func(AppData *ad, gint m)
+static void scroll_click_func(AppData *ad, gint n)
{
GList *list = ad->click_list;
gint proximity = FALSE;
@@ -496,17 +685,20 @@ static void scroll_click_func(AppData *ad, gint m)
ClickData *cd = w->data;
list = list->next;
- cd->y -= m;
+ cd->y -= n;
- if (ad->current_text)
+ if (ad->info_current)
{
- InfoData *id = ad->current_text->data;
- if (id == cd->line_id && ad->text_pos <= id->length) cd->h += m;
+ InfoData *id = ad->info_current;
+ if (id == cd->line_id) cd->h += n;
}
if (cd->y + cd->h < 1)
{
ad->click_list = g_list_remove(ad->click_list, cd);
+ if (!line_is_in_line_list(ad, cd->line_id) &&
+ !line_is_in_click_list(ad, cd->line_id))
+ free_info_line(ad, cd->line_id);
g_free(cd);
}
else
@@ -546,7 +738,9 @@ static int display_click(GtkWidget *w, GdkEventButton *event, gpointer data)
if (x >= cd->x && x < cd->x + cd->w && y >= cd->y && y < cd->y + cd->h)
{
- if (cd->click_func) cd->click_func(ad, cd->data);
+ if (cd->click_func)
+ cd->click_func(cd->line_id->data,
+ cd->line_id, ad);
}
list = list->next;
@@ -585,40 +779,141 @@ static void display_motion(GtkWidget *w, GdkEventMotion *event, gpointer data)
w = NULL;
}
-void init_app_display(AppData *ad)
+/*
+ *----------------------------------------------------------------------------
+ * display initialization and resizing
+ *----------------------------------------------------------------------------
+ */
+
+static void calc_display_sizes(AppData *ad)
+{
+ if (ad->follow_hint_width)
+ {
+#ifdef HAVE_PANEL_PIXEL_SIZE
+ ad->width_hint = applet_widget_get_free_space(APPLET_WIDGET(ad->applet));
+ if (ad->width_hint < 8) ad->width_hint = 200; /* no space or corner panel */
+#endif
+ ad->win_width = ad->width_hint;
+ }
+ else
+ {
+ ad->win_width = ad->user_width;
+ }
+ ad->width = ad->win_width - 4; /* hard coded, this is bound to break */
+
+ if (ad->follow_hint_height)
+ {
+ ad->win_height = ad->sizehint;
+ }
+ else
+ {
+ ad->win_height = ad->user_height;
+ }
+ ad->height = ad->win_height - 4; /* hard coded, this is bound to break */
+}
+
+static void create_display_pixmaps(AppData *ad)
{
- gint w, h;
+/* the old way ?
+ ad->display_w = gnome_pixmap_new_from_xpm_d_at_size(back_xpm, ad->width, ad->height);
+ ad->display = GNOME_PIXMAP(ad->display_w)->pixmap;
+ ad->disp_buf_w = gnome_pixmap_new_from_xpm_d_at_size(back_xpm, ad->width, ad->height);
+ ad->disp_buf = GNOME_PIXMAP(ad->disp_buf_w)->pixmap;
+ ad->background_w = gnome_pixmap_new_from_xpm_d_at_size(back_xpm, ad->width, ad->height);
+ ad->background = GNOME_PIXMAP(ad->background_w)->pixmap;
+*/
+
+ /* clear any current pixmaps */
+ if (ad->display) gdk_pixmap_unref(ad->display);
+ if (ad->disp_buf) gdk_pixmap_unref(ad->disp_buf);
+ if (ad->background) gdk_pixmap_unref(ad->background);
+ ad->display = NULL;
+ ad->disp_buf = NULL;
+ ad->background = NULL;
+
+ ad->display = gdk_pixmap_new (ad->applet->window, ad->width, ad->height, -1);
+ ad->disp_buf = gdk_pixmap_new (ad->applet->window, ad->width, ad->height, -1);
+ ad->background = gdk_pixmap_new (ad->applet->window, ad->width, ad->height, -1);
+
+ gdk_draw_rectangle (ad->display,
+ ad->applet->style->base_gc[GTK_STATE_NORMAL],
+ TRUE, 0, 0, ad->width, ad->height);
+ gdk_draw_rectangle (ad->disp_buf,
+ ad->applet->style->base_gc[GTK_STATE_NORMAL],
+ TRUE, 0, 0, ad->width, ad->height);
+ gdk_draw_rectangle (ad->background,
+ ad->applet->style->base_gc[GTK_STATE_NORMAL],
+ TRUE, 0, 0, ad->width, ad->height);
+}
+void resized_app_display(AppData *ad, gint force)
+{
+ gint old_w = ad->width;
+ gint old_h = ad->height;
+
+ calc_display_sizes(ad);
+
+ if (old_w == ad->width && old_h == ad->height && !force) return;
+
+/* old way?
+ gtk_widget_destroy(ad->display_w);
+ gtk_widget_destroy(ad->disp_buf_w);
+ gtk_widget_destroy(ad->background_w);
+*/
+
+ create_display_pixmaps(ad);
+ gtk_widget_set_usize(ad->applet, ad->win_width, ad->win_height);
+ gtk_drawing_area_size(GTK_DRAWING_AREA(ad->draw_area), ad->width, ad->height);
+
+ ad->text_height = ad->draw_area->style->font->ascent +
+ ad->draw_area->style->font->descent;
+ ad->text_y_line = ad->draw_area->style->font->descent;
+
+ ad->scroll_height = ad->text_height;
+
+ redraw_display(ad);
+}
+
+/* this is called when themes and fonts change */
+static void app_display_style_change_cb(GtkWidget *widget, GtkStyle *previous_style, gpointer data)
+{
+ AppData *ad = data;
+
+ /* the size does not change, but this causes a redraw
+ in the case that the background color changed */
+ resized_app_display(ad, TRUE);
+ return;
+ widget = NULL;
+ previous_style = NULL;
+}
+
+void init_app_display(AppData *ad)
+{
ad->scroll_delay = 20;
- ad->current_line = 0;
- ad->current_line_pos = 0;
ad->scroll_count = 0;
ad->scroll_pos = 0;
- ad->new_line = TRUE;
- ad->text_pos = 0;
- ad->text = NULL;
- ad->current_text = NULL;
+ ad->info_list = NULL;
+ ad->free_current = FALSE;
+ ad->info_current = NULL;
+ ad->info_next = NULL;
ad->click_list = NULL;
- ad->display_w = gnome_pixmap_new_from_xpm_d(back_xpm);
- ad->display = GNOME_PIXMAP(ad->display_w)->pixmap;
- ad->disp_buf_w = gnome_pixmap_new_from_xpm_d(back_xpm);
- ad->disp_buf = GNOME_PIXMAP(ad->disp_buf_w)->pixmap;
- ad->background_w = gnome_pixmap_new_from_xpm_d(back_xpm);
- ad->background = GNOME_PIXMAP(ad->background_w)->pixmap;
+ ad->display = NULL;
+ ad->disp_buf = NULL;
+ ad->background = NULL;
- gdk_window_get_size(ad->display, &w, &h);
+ calc_display_sizes(ad);
+ create_display_pixmaps(ad);
- ad->width = w;
- ad->height = h;
+ gtk_widget_set_usize(ad->applet, ad->win_width, ad->win_height);
ad->frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(ad->frame), GTK_SHADOW_IN);
gtk_widget_show(ad->frame);
ad->draw_area = gtk_drawing_area_new();
- gtk_drawing_area_size(GTK_DRAWING_AREA(ad->draw_area), w, h);
+ gtk_drawing_area_size(GTK_DRAWING_AREA(ad->draw_area), ad->width, ad->height);
gtk_widget_set_events (ad->draw_area, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK);
gtk_signal_connect(GTK_OBJECT(ad->draw_area),"motion_notify_event",
(GtkSignalFunc) display_motion, ad);
@@ -639,6 +934,9 @@ void init_app_display(AppData *ad)
redraw_display(ad);
+ gtk_signal_connect(GTK_OBJECT(ad->draw_area),"style_set",
+ (GtkSignalFunc) app_display_style_change_cb, ad);
+
ad->display_timeout_id = gtk_timeout_add(UPDATE_DELAY, (GtkFunction)update_display_cb, ad);
}