grim/guifications1
Clone
Summary
Browse
Changes
Graph
compiles on windows now, crashes at startup though. Updated README to let people know about gaim pre 0.75 support being dropped
2004-01-02, grim
cce21470e16b
compiles on windows now, crashes at startup though. Updated README to let people know about gaim pre 0.75 support being dropped
/*
Guifications - The notification plugin to end all notification plugins!
Copyright (C) 2003 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
<glib.h>
#include
<gtk/gtk.h>
#include
<pango/pango.h>
#include
<string.h>
#include
"account.h"
#include
"blist.h"
#include
"gaim.h"
#include
"prefs.h"
#include
"prpl.h"
#include
"debug.h"
#ifdef _WIN32
#include
"win32dep.h"
#endif
#include
"gf_utils.h"
#include
"gf_prefs.h"
/**********************************************************************/
void
gf_resize
(
GtkWidget
*
window
,
GtkWidget
*
box
)
{
if
(
window
!=
NULL
)
{
gtk_window_resize
(
GTK_WINDOW
(
window
),
get_window_width
(
box
),
get_window_height
(
box
));
gtk_window_move
(
GTK_WINDOW
(
window
),
get_window_x
(
window
),
get_window_y
(
window
));
}
}
/**********************************************************************/
gint
get_window_x
(
GtkWidget
*
window
)
{
GtkRequisition
req
;
gtk_widget_size_request
(
window
,
&
req
);
switch
(
gaim_prefs_get_int
(
GF_PREF_BEHAVIOR_WINDOW_POS
))
{
case
window_position_nw
:
case
window_position_sw
:
return
0
;
case
window_position_ne
:
case
window_position_se
:
return
gdk_screen_width
()
-
req
.
width
;
}
return
0
;
}
/**********************************************************************/
gint
get_window_y
(
GtkWidget
*
window
)
{
GtkRequisition
req
;
gtk_widget_size_request
(
window
,
&
req
);
switch
(
gaim_prefs_get_int
(
GF_PREF_BEHAVIOR_WINDOW_POS
))
{
case
window_position_ne
:
case
window_position_nw
:
return
0
;
case
window_position_se
:
case
window_position_sw
:
return
gdk_screen_height
()
-
req
.
height
;
}
return
0
;
}
/**********************************************************************/
gint
get_window_width
(
GtkWidget
*
box
)
{
GtkWidget
*
child
;
GtkRequisition
req
;
GList
*
children
;
gint
new_size
=
0
;
children
=
gtk_container_get_children
(
GTK_CONTAINER
(
box
));
if
(
gaim_prefs_get_bool
(
GF_PREF_BEHAVIOR_WINDOW_VERTICAL
))
{
child
=
children
->
data
;
gtk_widget_size_request
(
child
,
&
req
);
return
req
.
width
;
}
else
{
while
(
children
)
{
child
=
children
->
data
;
children
=
children
->
next
;
gtk_widget_size_request
(
child
,
&
req
);
new_size
+=
req
.
width
;
}
g_list_free
(
children
);
return
new_size
;
}
}
/**********************************************************************/
gint
get_window_height
(
GtkWidget
*
box
)
{
GtkWidget
*
child
;
GtkRequisition
req
;
GList
*
children
;
gint
new_size
=
0
;
children
=
gtk_container_get_children
(
GTK_CONTAINER
(
box
));
if
(
gaim_prefs_get_bool
(
GF_PREF_BEHAVIOR_WINDOW_VERTICAL
))
{
while
(
children
)
{
child
=
children
->
data
;
children
=
children
->
next
;
gtk_widget_size_request
(
child
,
&
req
);
new_size
+=
req
.
height
;
}
g_list_free
(
children
);
return
new_size
;
}
else
{
child
=
children
->
data
;
gtk_widget_size_request
(
child
,
&
req
);
return
req
.
height
;
}
}
/**********************************************************************/
void
get_image_size
(
dimensions
*
image_size
)
{
GdkPixbuf
*
image
=
NULL
;
if
(
gaim_prefs_get_bool
(
GF_PREF_APPEARANCE_IMAGE
))
{
image
=
gdk_pixbuf_new_from_file
(
gaim_prefs_get_string
(
GF_PREF_APPEARANCE_IMAGE_FILE
),
NULL
);
if
(
image
==
NULL
)
{
gaim_prefs_set_bool
(
GF_PREF_APPEARANCE_IMAGE
,
FALSE
);
gaim_prefs_set_string
(
GF_PREF_APPEARANCE_IMAGE_FILE
,
""
);
image_size
->
width
=
140
;
image_size
->
height
=
120
;
}
else
{
image_size
->
width
=
gdk_pixbuf_get_width
(
image
);
image_size
->
height
=
gdk_pixbuf_get_height
(
image
);
g_object_unref
(
image
);
}
}
else
{
image_size
->
width
=
140
;
image_size
->
height
=
120
;
}
}
/**********************************************************************/
void
get_zoom_size
(
dimensions
image_size
,
dimensions
*
zoom_size
)
{
gfloat
width
=
0
,
height
=
0
;
gfloat
owidth
=
image_size
.
width
,
oheight
=
image_size
.
height
;
switch
(
gaim_prefs_get_int
(
GF_PREF_BEHAVIOR_ZOOM
))
{
case
window_zoom_200
:
width
=
owidth
*
2.0f
;
height
=
oheight
*
2.0f
;
break
;
case
window_zoom_175
:
width
=
owidth
*
1.75f
;
height
=
oheight
*
1.75f
;
break
;
case
window_zoom_150
:
width
=
owidth
*
1.5f
;
height
=
oheight
*
1.5f
;
break
;
case
window_zoom_125
:
width
=
owidth
*
1.25f
;
height
=
oheight
*
1.25f
;
break
;
case
window_zoom_75
:
width
=
owidth
*
0.75f
;
height
=
oheight
*
0.75f
;
break
;
case
window_zoom_50
:
width
=
owidth
*
0.5f
;
height
=
oheight
*
0.5f
;
break
;
case
window_zoom_25
:
width
=
owidth
*
0.25f
;
height
=
oheight
*
0.25f
;
break
;
case
window_zoom_100
:
default
:
width
=
owidth
;
height
=
oheight
;
}
zoom_size
->
width
=
width
;
zoom_size
->
height
=
height
;
}
/**********************************************************************/
void
clip_layout
(
PangoLayout
**
layout
,
gboolean
use_color
,
const
gchar
*
text_x
,
const
gchar
*
text_color
)
{
PangoLayout
*
lay
=
(
*
layout
),
*
elipse
=
NULL
;
gboolean
loop
=
TRUE
;
const
gchar
*
text
=
NULL
;
gchar
*
new_text
=
NULL
,
*
left_text
=
NULL
,
*
right_text
=
NULL
;
gint
width
=
0
,
ewidth
=
0
,
offset
=
0
,
mid
=
0
;
dimensions
dim
;
offset
=
gaim_prefs_get_int
(
text_x
);
get_image_size
(
&
dim
);
elipse
=
pango_layout_copy
(
lay
);
pango_layout_set_text
(
elipse
,
"..."
,
-1
);
pango_layout_get_pixel_size
(
elipse
,
&
ewidth
,
NULL
);
g_object_unref
(
elipse
);
pango_layout_get_pixel_size
(
lay
,
&
width
,
NULL
);
if
((
width
+
offset
)
>
dim
.
width
)
{
switch
(
gaim_prefs_get_int
(
GF_PREF_APPEARANCE_TEXT_CLIPPING
))
{
case
text_clipping_truncate
:
while
(
loop
)
{
pango_layout_get_pixel_size
(
lay
,
&
width
,
NULL
);
if
((
width
+
offset
)
<=
dim
.
width
)
loop
=
FALSE
;
else
{
text
=
pango_layout_get_text
(
lay
);
new_text
=
g_strndup
(
text
,
strlen
(
text
)
-
1
);
pango_layout_set_text
(
lay
,
new_text
,
-1
);
}
}
g_free
(
new_text
);
break
;
case
text_clipping_elipse_start
:
while
(
loop
)
{
pango_layout_get_pixel_size
(
lay
,
&
width
,
NULL
);
if
((
width
+
offset
+
ewidth
)
<=
dim
.
width
)
loop
=
FALSE
;
else
{
text
=
pango_layout_get_text
(
lay
);
new_text
=
g_strrndup
(
text
,
strlen
(
text
)
-
1
);
pango_layout_set_text
(
lay
,
new_text
,
-1
);
}
}
text
=
pango_layout_get_text
(
lay
);
new_text
=
g_strdup_printf
(
"...%s"
,
text
);
pango_layout_set_text
(
lay
,
new_text
,
-1
);
g_free
(
new_text
);
break
;
case
text_clipping_elipse_middle
:
while
(
loop
)
{
pango_layout_get_pixel_size
(
lay
,
&
width
,
NULL
);
if
((
width
+
offset
+
ewidth
)
<=
dim
.
width
)
loop
=
FALSE
;
else
{
text
=
pango_layout_get_text
(
lay
);
mid
=
strlen
(
text
)
/
2
;
if
(
is_even
(
strlen
(
text
)))
{
left_text
=
g_strndup
(
text
,
mid
);
right_text
=
g_strrndup
(
text
,
mid
-
1
);
}
else
{
left_text
=
g_strndup
(
text
,
mid
);
right_text
=
g_strrndup
(
text
,
mid
);
}
new_text
=
g_strdup_printf
(
"%s%s"
,
left_text
,
right_text
);
pango_layout_set_text
(
lay
,
new_text
,
-1
);
}
}
new_text
=
g_strdup_printf
(
"%s...%s"
,
left_text
,
right_text
);
g_free
(
left_text
);
g_free
(
right_text
);
pango_layout_set_text
(
lay
,
new_text
,
-1
);
g_free
(
new_text
);
break
;
case
text_clipping_elipse_end
:
while
(
loop
)
{
pango_layout_get_pixel_size
(
lay
,
&
width
,
NULL
);
if
((
width
+
offset
+
ewidth
)
<=
dim
.
width
)
loop
=
FALSE
;
else
{
text
=
pango_layout_get_text
(
lay
);
new_text
=
g_strndup
(
text
,
strlen
(
text
)
-
1
);
pango_layout_set_text
(
lay
,
new_text
,
-1
);
}
}
text
=
pango_layout_get_text
(
lay
);
new_text
=
g_strdup_printf
(
"%s..."
,
text
);
pango_layout_set_text
(
lay
,
new_text
,
-1
);
g_free
(
new_text
);
break
;
}
}
text
=
pango_layout_get_text
(
lay
);
new_text
=
g_markup_escape_text
(
text
,
-1
);
pango_layout_set_text
(
lay
,
new_text
,
-1
);
set_color
(
&
lay
,
use_color
,
text_color
);
}
/**********************************************************************/
gchar
*
g_strrndup
(
const
gchar
*
src
,
gint
n
)
{
gchar
*
dest
=
g_malloc
(
strlen
(
src
));
gint
i
=
0
,
j
=
0
;
for
(
i
=
strlen
(
src
)
-
n
;
i
<
strlen
(
src
);
i
++
)
{
dest
[
j
]
=
src
[
i
];
j
++
;
}
dest
[
j
]
=
'\0'
;
return
dest
;
}
/**********************************************************************/
void
set_color
(
PangoLayout
**
layout
,
gboolean
custom_color
,
const
gchar
*
pref
)
{
PangoLayout
*
lay
=
(
*
layout
);
const
gchar
*
text
;
text
=
pango_layout_get_text
(
lay
);
if
(
custom_color
)
pango_layout_set_markup
(
lay
,
set_text_color
(
text
,
pref
),
-1
);
else
pango_layout_set_markup
(
lay
,
g_strdup_printf
(
"<span foreground=
\"
%s
\"
>%s</span>"
,
"#000000000000"
,
text
),
-1
);
}
/**********************************************************************/
gchar
*
set_text_color
(
const
gchar
*
text
,
const
gchar
*
pref
)
{
gchar
*
ret
=
NULL
;
ret
=
g_strdup_printf
(
"<span foreground=
\"
%s
\"
>%s</span>"
,
gaim_prefs_get_string
(
pref
),
text
);
return
ret
;
}
/**********************************************************************/
gint
get_proto_icon_size
()
{
switch
(
gaim_prefs_get_int
(
GF_PREF_APPEARANCE_PROT_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
;
}
return
0
;
}
/**********************************************************************/
void
get_text_pos
(
gint
*
x
,
gint
*
y
,
gboolean
line
,
PangoLayout
*
layout
)
{
dimensions
dim
;
gint
height
,
width
;
gint
dhh
,
dhw
;
gint
hh
,
hw
;
gint
ox
,
oy
;
gint
ohx
,
ohy
;
gint
north
,
east
,
south
,
west
,
lat
,
lon
;
get_image_size
(
&
dim
);
pango_layout_get_pixel_size
(
layout
,
&
width
,
&
height
);
dhh
=
dim
.
height
/
2
;
dhw
=
dim
.
width
/
2
;
hh
=
height
/
2
;
hw
=
width
/
2
;
ox
=
gaim_prefs_get_int
(
GF_PREF_APPEARANCE_TEXT_X
);
oy
=
gaim_prefs_get_int
(
GF_PREF_APPEARANCE_TEXT_Y
);
ohx
=
ox
/
2
;
ohy
=
oy
/
2
;
north
=
line
?
oy
:
height
+
oy
;
east
=
dim
.
width
-
(
width
+
ox
);
south
=
line
?
dim
.
height
-
(
height
*
2
+
oy
)
:
dim
.
height
-
(
height
+
oy
);
west
=
ox
;
lat
=
line
?
dhh
-
(
height
+
ohy
)
:
dhh
+
ohy
;
/* y */
lon
=
dhw
-
(
hw
+
ohx
);
/* x */
switch
(
gaim_prefs_get_int
(
GF_PREF_APPEARANCE_TEXT_POS
))
{
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
;
}
}
/**********************************************************************/
void
get_icon_pos
(
gint
*
x
,
gint
*
y
)
{
dimensions
dim
;
gint
height
,
width
;
gint
dhh
,
dhw
;
gint
hh
,
hw
;
gint
ox
,
oy
;
gint
ohx
,
ohy
;
gint
north
,
east
,
south
,
west
,
lat
,
lon
;
get_image_size
(
&
dim
);
dhh
=
dim
.
height
/
2
;
dhw
=
dim
.
width
/
2
;
width
=
height
=
get_proto_icon_size
();
hw
=
hh
=
width
/
2
;
ox
=
gaim_prefs_get_int
(
GF_PREF_APPEARANCE_PROT_X
);
oy
=
gaim_prefs_get_int
(
GF_PREF_APPEARANCE_PROT_Y
);
ohx
=
ox
/
2
;
ohy
=
oy
/
2
;
north
=
oy
;
east
=
dim
.
width
-
(
width
+
ox
);
south
=
dim
.
height
-
(
height
+
oy
);
west
=
ox
;
lat
=
dhh
-
(
hh
+
ohy
);
/* y */
lon
=
dhw
-
(
hw
+
ohx
);
/* x */
switch
(
gaim_prefs_get_int
(
GF_PREF_APPEARANCE_PROT_POS
))
{
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
;
}
}
/**********************************************************************/
GdkPixbuf
*
get_proto_icon
(
GaimBuddy
*
buddy
)
{
GaimPluginProtocolInfo
*
prplinfo
=
NULL
;
GdkPixbuf
*
src
=
NULL
,
*
ret
=
NULL
;
gchar
*
proto
,
*
file
;
gint
height
=
0
,
width
=
0
;
prplinfo
=
GAIM_PLUGIN_PROTOCOL_INFO
(
gaim_find_prpl
(
gaim_account_get_protocol_id
(
buddy
->
account
)));
proto
=
g_strdup_printf
(
"%s.png"
,
prplinfo
->
list_icon
(
buddy
->
account
,
buddy
));
file
=
g_build_filename
(
DATADIR
,
"pixmaps"
,
"gaim"
,
"status"
,
"default"
,
proto
,
NULL
);
g_free
(
proto
);
src
=
gdk_pixbuf_new_from_file
(
file
,
NULL
);
g_free
(
file
);
width
=
height
=
get_proto_icon_size
();
ret
=
gdk_pixbuf_scale_simple
(
src
,
width
,
height
,
GDK_INTERP_BILINEAR
);
g_object_unref
(
src
);
return
ret
;
}
/**********************************************************************/
gboolean
is_even
(
gint
number
)
{
if
((
number
&
1
)
==
1
)
return
FALSE
;
else
return
TRUE
;
}
/**********************************************************************/