grim/guifications1
Clone
Summary
Browse
Changes
Graph
a useless feature.. dunno if this will work on windows.. datallah any ideas?
2004-01-14, grim
104f6faa875a
a useless feature.. dunno if this will work on windows.. datallah any ideas?
/*
Guifications - The notification plugin to end all notification plugins!
Copyright (C) 2003-2004 Gary Kramlich
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include
<gtk/gtk.h>
#include
<gdk/gdk.h>
#include
<pango/pango.h>
#include
<string.h>
#include
"gtkblist.h"
#include
"blist.h"
#include
"server.h"
#include
"debug.h"
#include
"gf_pixbuf.h"
#include
"gf_types.h"
static
const
gchar
*
gf_format_text
(
GaimBuddy
*
buddy
,
gint
line
,
gf_event
event
,
gf_theme
*
theme
)
{
/* Formatting Options
%N = Screen Name %A = Alias
%P = Protocol %M = Away Message
%C = Account %W = Warning level
*/
char
formatted
[
255
],
*
format
;
gchar
*
buff
=
NULL
;
int
c
=
0
,
i
=
0
;
format
=
theme
->
notification
[
event
].
text
[
line
].
format
;
while
(
*
format
)
{
if
(
*
format
==
'%'
)
{
switch
(
*
(
format
+
1
))
{
case
'N'
:
/* screen name */
for
(
i
=
0
;
i
<
strlen
(
buddy
->
name
);
i
++
)
formatted
[
c
+
i
]
=
buddy
->
name
[
i
];
c
+=
i
;
break
;
case
'A'
:
/* alias, follows alias pref rules */
buff
=
g_strdup
(
gaim_get_buddy_alias
(
buddy
));
for
(
i
=
0
;
i
<
strlen
(
buff
);
i
++
)
formatted
[
c
+
i
]
=
buff
[
i
];
c
+=
i
;
g_free
(
buff
);
break
;
case
'P'
:
/* protocol */
buff
=
g_strdup
(
gaim_account_get_protocol_id
(
buddy
->
account
));
for
(
i
=
0
;
i
<
strlen
(
buff
);
i
++
)
formatted
[
c
+
i
]
=
buff
[
i
];
c
+=
i
;
g_free
(
buff
);
break
;
case
'M'
:
/* away message if event isn't away this value
gets removed */
if
(
event
==
gf_event_away
)
{
/*buff = g_strdup(serv_get_away(buddy->account->gc, buddy->name)); */
for
(
i
=
0
;
i
<
strlen
(
buff
);
i
++
)
formatted
[
c
+
i
]
=
buff
[
i
];
c
+=
i
;
g_free
(
buff
);
}
break
;
case
'C'
:
/* account name */
buff
=
g_strdup
(
buddy
->
account
->
username
);
for
(
i
=
0
;
i
<
strlen
(
buff
);
i
++
)
formatted
[
c
+
i
]
=
buff
[
i
];
c
+=
i
;
g_free
(
buff
);
break
;
case
'W'
:
/* warning level, if protocol isn't oscar this
value gets removed */
break
;
case
'%'
:
formatted
[
i
]
=
'%'
;
c
++
;
break
;
}
}
else
{
formatted
[
i
]
=
*
format
;
c
++
;
}
format
++
;
}
return
formatted
;
}
static
void
gf_background_get_size
(
gint
*
width
,
gint
*
height
,
gf_event
event
,
gf_theme
*
theme
)
{
GError
*
error
;
GdkPixbuf
*
background
;
gchar
*
filename
;
if
(
g_path_is_absolute
(
theme
->
notification
[
event
].
image
))
filename
=
g_strdup
(
theme
->
notification
[
event
].
image
);
else
filename
=
g_build_filename
(
theme
->
directory
,
theme
->
notification
[
event
].
image
,
NULL
);
background
=
gdk_pixbuf_new_from_file
(
filename
,
&
error
);
if
(
background
==
NULL
)
{
*
width
=
*
height
=
-1
;
gaim_debug_info
(
"Guifications"
,
"Error getting background image size: %s
\n
"
,
error
->
message
);
return
;
}
*
width
=
gdk_pixbuf_get_width
(
background
);
*
height
=
gdk_pixbuf_get_height
(
background
);
g_object_unref
(
background
);
}
static
gint
gf_icon_get_size
(
gint
icon
,
gf_event
event
,
gf_theme
*
theme
)
{
switch
(
theme
->
notification
[
event
].
icon
[
icon
].
size
)
{
case
icon_size_tiny
:
return
16
;
break
;
case
icon_size_small
:
return
24
;
break
;
case
icon_size_normal
:
return
48
;
break
;
case
icon_size_large
:
return
96
;
break
;
case
icon_size_huge
:
return
144
;
break
;
default
:
return
0
;
break
;
}
}
static
void
gf_icon_get_position
(
gint
*
x
,
gint
*
y
,
gint
icon
,
gf_event
event
,
gf_theme
*
theme
)
{
gint
bg_width
,
bg_height
;
gint
bg_half_width
,
bg_half_height
;
gint
icon_size
,
icon_half_size
;
gint
icon_offset_x
,
icon_offset_y
;
gint
icon_half_offset_x
,
icon_half_offset_y
;
gint
north
,
east
,
south
,
west
,
lat
,
lon
;
gf_background_get_size
(
&
bg_width
,
&
bg_height
,
event
,
theme
);
if
((
bg_width
==
-1
)
||
(
bg_height
==
-1
))
{
*
x
=
*
y
=
-1
;
gaim_debug_info
(
"Guifications"
,
"Failed to get background image size
\n
"
);
return
;
}
bg_half_width
=
bg_width
/
2
;
bg_half_height
=
bg_height
/
2
;
icon_size
=
gf_icon_get_size
(
icon
,
event
,
theme
);
icon_half_size
=
icon_size
/
2
;
icon_offset_x
=
theme
->
notification
[
event
].
icon
[
icon
].
item
.
offset_horizontal
;
icon_offset_y
=
theme
->
notification
[
event
].
icon
[
icon
].
item
.
offset_vertical
;
icon_half_offset_x
=
icon_offset_x
/
2
;
icon_half_offset_y
=
icon_offset_y
/
2
;
north
=
icon_half_offset_y
;
east
=
bg_width
-
(
icon_size
+
icon_offset_x
);
south
=
bg_height
-
(
icon_size
+
icon_offset_y
);
west
=
icon_offset_x
;
lon
=
bg_half_width
-
(
icon_half_size
+
icon_half_offset_x
);
/* x */
lat
=
bg_half_height
-
(
icon_half_size
+
icon_half_offset_y
);
/* y */
switch
(
theme
->
notification
[
event
].
icon
[
icon
].
position
)
{
case
item_position_nw
:
*
x
=
west
;
*
y
=
north
;
break
;
case
item_position_n
:
*
x
=
lon
;
*
y
=
north
;
break
;
case
item_position_ne
:
*
x
=
east
;
*
y
=
north
;
break
;
case
item_position_w
:
*
x
=
west
;
*
y
=
lat
;
break
;
case
item_position_c
:
*
x
=
lon
;
*
y
=
lat
;
break
;
case
item_position_e
:
*
x
=
east
;
*
y
=
lat
;
break
;
case
item_position_sw
:
*
x
=
west
;
*
y
=
south
;
break
;
case
item_position_s
:
*
x
=
lon
;
*
y
=
south
;
break
;
case
item_position_se
:
*
x
=
east
;
*
y
=
south
;
break
;
}
}
static
void
gf_get_text_position
(
gint
*
x
,
gint
*
y
,
gint
line
,
PangoLayout
*
layout
,
gf_event
event
,
gf_theme
*
theme
)
{
gint
bg_width
,
bg_height
;
gint
bg_half_width
,
bg_half_height
;
gint
text_width
,
text_height
;
gint
text_half_width
,
text_half_height
;
gint
text_offset_x
,
text_offset_y
;
gint
text_half_offset_x
,
text_half_offset_y
;
gint
north
,
east
,
south
,
west
,
lat
,
lon
;
gf_background_get_size
(
&
bg_width
,
&
bg_height
,
event
,
theme
);
bg_half_width
=
bg_width
/
2
;
bg_half_height
=
bg_height
/
2
;
pango_layout_get_pixel_size
(
layout
,
&
text_width
,
&
text_height
);
if
(
theme
->
notification
[
event
].
text
[
line
].
width
!=
0
)
text_width
=
theme
->
notification
[
event
].
text
[
line
].
width
;
text_half_width
=
text_width
/
2
;
text_half_height
=
text_height
/
2
;
text_offset_x
=
theme
->
notification
[
event
].
text
[
line
].
item
.
offset_horizontal
;
text_offset_y
=
theme
->
notification
[
event
].
text
[
line
].
item
.
offset_vertical
;
text_half_offset_x
=
text_offset_x
/
2
;
text_half_offset_y
=
text_offset_y
/
2
;
north
=
text_offset_y
;
east
=
bg_width
-
(
text_width
+
text_offset_x
);
south
=
bg_height
-
(
text_height
+
text_offset_y
);
west
=
text_offset_x
;
lon
=
bg_half_width
-
(
text_half_width
+
text_half_offset_x
);
/* x */
lat
=
bg_half_height
-
(
text_half_height
+
text_half_offset_y
);
/* y */
switch
(
theme
->
notification
[
event
].
text
[
line
].
position
)
{
case
item_position_nw
:
*
x
=
west
;
*
y
=
north
;
break
;
case
item_position_n
:
*
x
=
lon
;
*
y
=
north
;
break
;
case
item_position_ne
:
*
x
=
east
;
*
y
=
north
;
break
;
case
item_position_w
:
*
x
=
west
;
*
y
=
lat
;
break
;
case
item_position_c
:
*
x
=
lon
;
*
y
=
lat
;
break
;
case
item_position_e
:
*
x
=
east
;
*
y
=
lat
;
break
;
case
item_position_sw
:
*
x
=
west
;
*
y
=
south
;
break
;
case
item_position_s
:
*
x
=
lon
;
*
y
=
south
;
break
;
case
item_position_se
:
*
x
=
east
;
*
y
=
south
;
break
;
}
}
static
GdkPixbuf
*
gf_get_event_background
(
gf_event
event
,
gf_theme
*
theme
)
{
GError
*
error
;
GdkPixbuf
*
background
=
NULL
;
gchar
*
filename
;
if
(
g_path_is_absolute
(
theme
->
notification
[
event
].
image
))
filename
=
g_strdup
(
theme
->
notification
[
event
].
image
);
else
filename
=
g_build_filename
(
theme
->
directory
,
theme
->
notification
[
event
].
image
,
NULL
);
background
=
gdk_pixbuf_new_from_file
(
filename
,
&
error
);
if
(
background
==
NULL
)
gaim_debug_info
(
"Guifications"
,
"Error loading %s: %s
\n
"
,
filename
,
error
->
message
);
g_free
(
filename
);
return
background
;
}
GdkPixbuf
*
gf_make_pixbuf
(
GaimBuddy
*
buddy
,
gf_event
event
,
gf_theme
*
theme
)
{
GdkPixbuf
*
gf_pixbuf
=
NULL
;
GdkPixbuf
*
background
=
NULL
;
GdkPixbuf
*
icon
=
NULL
,
*
icon_scaled
=
NULL
;
gint
icon_size
=
0
,
icon_x
=
0
,
icon_y
=
0
;
gint
i
=
0
;
const
char
*
buddy_icon_file
;
if
((
background
=
gf_get_event_background
(
event
,
theme
))
==
NULL
)
return
NULL
;
gf_pixbuf
=
gdk_pixbuf_copy
(
background
);
g_object_unref
(
background
);
if
(
theme
->
notification
[
event
].
icons
>
0
)
for
(
i
=
0
;
i
<
theme
->
notification
[
event
].
icons
;
i
++
)
{
if
(
!
theme
->
notification
[
event
].
icon
[
i
].
item
.
visible
)
continue
;
switch
(
theme
->
notification
[
event
].
icon
[
i
].
type
)
{
case
icon_protocol
:
icon
=
create_prpl_icon
(
buddy
->
account
);
break
;
case
icon_buddy
:
if
((
buddy_icon_file
=
gaim_blist_node_get_string
((
GaimBlistNode
*
)
buddy
,
"buddy_icon"
))
==
NULL
)
continue
;
icon
=
gdk_pixbuf_new_from_file
(
buddy_icon_file
,
NULL
);
break
;
case
icon_status
:
icon
=
gaim_gtk_blist_get_status_icon
((
GaimBlistNode
*
)
buddy
,
GAIM_STATUS_ICON_LARGE
);
break
;
default
:
continue
;
break
;
}
icon_size
=
gf_icon_get_size
(
i
,
event
,
theme
);
icon_scaled
=
gdk_pixbuf_scale_simple
(
icon
,
icon_size
,
icon_size
,
GDK_INTERP_BILINEAR
);
g_object_unref
(
icon
);
gf_icon_get_position
(
&
icon_x
,
&
icon_y
,
i
,
event
,
theme
);
gdk_pixbuf_composite
(
icon_scaled
,
gf_pixbuf
,
icon_x
,
icon_y
,
icon_size
,
icon_size
,
icon_x
,
icon_y
,
1
,
1
,
GDK_INTERP_BILINEAR
,
255
);
g_object_unref
(
icon_scaled
);
}
if
(
theme
->
notification
[
event
].
lines
>
0
)
for
(
i
=
0
;
i
<
theme
->
notification
[
event
].
lines
;
i
++
)
{
}
return
gf_pixbuf
;
}