pidgin/purple-plugin-pack
Clone
Summary
Browse
Changes
Graph
Add the turtles target to keep the foot clan at bay
default
tip
13 months ago, Gary Kramlich
63ad7e4f10b4
Add the turtles target to keep the foot clan at bay
Testing Done:
Ran `ninja turtles` and verified it worked correctly.
Reviewed at https://reviews.imfreedom.org/r/2409/
/*
* irssi - Implements several irssi features for Purple
* Copyright (C) 2005-2008 Gary Kramlich <grim@reaperworld.com>
* Copyright (C) 2006-2008 John Bailey <rekkanoryo@rekkanoryo.org>
* Copyright (C) 2006-2008 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02111-1301, USA.
*/
/* If you can't figure out what this line is for, DON'T TOUCH IT. */
#include
"../common/pp_internal.h"
#include
<blist.h>
#include
<cmds.h>
#include
<plugin.h>
#include
<gtkblist.h>
#include
<gtkconv.h>
#include
"layout.h"
#define IRSSI_LAYOUT_SETTING "irssi::layout"
#define SETTING_TO_INTS(s, i1, i2) { \
(i1) = (s) & 0x3ff; \
(i2) = (s) >> 10; \
}
#define SETTING_FROM_INTS(i1, i2) (((i1) << 10 ) + (i2))
/******************************************************************************
* Globals
*****************************************************************************/
static
PurpleCmdId
irssi_layout_cmd_id
=
0
;
/******************************************************************************
* Helpers
*****************************************************************************/
static
PurpleBlistNode
*
irssi_layout_get_node_from_conv
(
PurpleConversation
*
conv
)
{
PurpleAccount
*
account
=
NULL
;
PurpleBlistNode
*
node
=
NULL
;
PurpleConversationType
type
=
purple_conversation_get_type
(
conv
);
const
char
*
name
=
NULL
;
account
=
purple_conversation_get_account
(
conv
);
name
=
purple_conversation_get_name
(
conv
);
/* this is overkill for now, but who knows, we _may_ need it later */
if
(
type
==
PURPLE_CONV_TYPE_CHAT
)
node
=
(
PurpleBlistNode
*
)
purple_blist_find_chat
(
account
,
name
);
else
if
(
type
==
PURPLE_CONV_TYPE_IM
)
node
=
(
PurpleBlistNode
*
)
purple_find_buddy
(
account
,
name
);
return
node
;
}
static
PurpleConversation
*
irssi_layout_get_conv_from_node
(
PurpleBlistNode
*
node
,
gboolean
create
)
{
PurpleAccount
*
account
=
NULL
;
PurpleConversation
*
conv
=
NULL
;
PurpleConversationType
ctype
=
PURPLE_CONV_TYPE_UNKNOWN
;
const
gchar
*
name
=
NULL
;
switch
(
node
->
type
)
{
case
PURPLE_BLIST_CHAT_NODE
:
{
PurpleChat
*
chat
=
(
PurpleChat
*
)
node
;
ctype
=
PURPLE_CONV_TYPE_CHAT
;
name
=
purple_chat_get_name
(
chat
);
account
=
chat
->
account
;
break
;
}
case
PURPLE_BLIST_BUDDY_NODE
:
{
PurpleBuddy
*
buddy
=
(
PurpleBuddy
*
)
node
;
ctype
=
PURPLE_CONV_TYPE_IM
;
name
=
buddy
->
name
;
account
=
buddy
->
account
;
break
;
}
default
:
return
NULL
;
break
;
}
conv
=
purple_find_conversation_with_account
(
ctype
,
name
,
account
);
if
(
!
conv
&&
create
)
{
conv
=
purple_conversation_new
(
ctype
,
account
,
name
);
/* dirty hack alert! */
if
(
ctype
==
(
PurpleConversationType
)
PURPLE_BLIST_CHAT_NODE
)
{
PurpleChat
*
chat
=
(
PurpleChat
*
)
node
;
purple_conv_chat_left
(
PURPLE_CONV_CHAT
(
conv
));
serv_join_chat
(
account
->
gc
,
chat
->
components
);
}
}
return
conv
;
}
static
gint
irssi_layout_get_setting
(
PidginConversation
*
gtkconv
)
{
PurpleConversation
*
conv
=
gtkconv
->
active_conv
;
PurpleBlistNode
*
node
=
NULL
;
gint
ret
=
0
;
node
=
irssi_layout_get_node_from_conv
(
conv
);
if
(
node
)
ret
=
purple_blist_node_get_int
(
node
,
IRSSI_LAYOUT_SETTING
);
return
ret
;
}
static
void
irssi_layout_reset
(
void
)
{
PurpleBlistNode
*
node
=
purple_blist_get_root
();
for
(;
node
;
node
=
purple_blist_node_next
(
node
,
TRUE
))
purple_blist_node_remove_setting
(
node
,
IRSSI_LAYOUT_SETTING
);
}
static
void
irssi_layout_save
(
void
)
{
PurpleBlistNode
*
node
=
NULL
;
GList
*
wins
=
NULL
;
gint
i
,
j
;
/* reset the previous layouts if any exist */
irssi_layout_reset
();
/* now save the layout... */
wins
=
pidgin_conv_windows_get_list
();
for
(
i
=
1
;
wins
;
wins
=
wins
->
next
,
i
++
)
{
PidginWindow
*
win
=
wins
->
data
;
GList
*
convs
=
pidgin_conv_window_get_gtkconvs
(
win
);
for
(
j
=
1
;
convs
;
convs
=
convs
->
next
,
j
++
)
{
PidginConversation
*
gtkconv
=
convs
->
data
;
PurpleConversation
*
conv
=
gtkconv
->
active_conv
;
node
=
irssi_layout_get_node_from_conv
(
conv
);
if
(
node
)
purple_blist_node_set_int
(
node
,
IRSSI_LAYOUT_SETTING
,
SETTING_FROM_INTS
(
i
,
j
));
}
}
}
static
void
irssi_layout_load
(
void
)
{
PurpleConversation
*
conv
=
NULL
;
PurpleBlistNode
*
node
;
PidginConversation
*
gtkconv
=
NULL
;
PidginWindow
*
window
=
NULL
;
GList
*
convs
=
NULL
,
*
settings
=
NULL
,
*
wins
=
NULL
;
gint
current
=
1
;
node
=
purple_blist_get_root
();
/* build our GList's with the conversation and the setting */
for
(;
node
;
node
=
purple_blist_node_next
(
node
,
FALSE
))
{
gint
setting
=
purple_blist_node_get_int
(
node
,
IRSSI_LAYOUT_SETTING
);
if
(
setting
==
0
)
continue
;
conv
=
irssi_layout_get_conv_from_node
(
node
,
FALSE
);
if
(
conv
)
{
convs
=
g_list_prepend
(
convs
,
conv
);
settings
=
g_list_prepend
(
settings
,
GINT_TO_POINTER
(
setting
));
}
}
/* now restore the layout */
/* we start by looping until all of our settings are handled */
while
(
convs
)
{
GList
*
l1
=
NULL
,
*
l2
=
NULL
;
/* now go through the list and make sure we put the conversations in
* the correct windows.
*/
for
(
l1
=
convs
,
l2
=
settings
;
l1
;
)
{
GList
*
s
=
NULL
;
gint
win
,
pos
,
setting
;
/* this is a junk var needed for the horrible macro below */
(
void
)
pos
;
setting
=
GPOINTER_TO_INT
(
l2
->
data
);
SETTING_TO_INTS
(
setting
,
pos
,
win
);
if
(
win
!=
current
)
continue
;
conv
=
l1
->
data
;
gtkconv
=
PIDGIN_CONVERSATION
(
conv
);
/* pop of the nodes we just handled but hold our places and update
* the head pointers.
*/
/* convs */
s
=
l1
;
l1
=
l1
->
next
;
convs
=
g_list_delete_link
(
convs
,
s
);
/* settings */
s
=
l2
;
l2
=
l2
->
next
;
settings
=
g_list_delete_link
(
settings
,
s
);
/* now find the actual window this should go into */
wins
=
pidgin_conv_windows_get_list
();
window
=
g_list_nth_data
(
wins
,
win
-
1
);
if
(
!
window
)
{
/* make dat der dun winda */
window
=
pidgin_conv_window_new
();
}
/* add the conversation to the window */
if
(
gtkconv
->
win
!=
window
)
{
pidgin_conv_window_remove_gtkconv
(
gtkconv
->
win
,
gtkconv
);
pidgin_conv_window_add_gtkconv
(
window
,
gtkconv
);
}
}
current
++
;
}
/* All the conversations are in the correct windows. Now we make sure
* they're in their right positions.
*/
for
(
wins
=
pidgin_conv_windows_get_list
();
wins
;
wins
=
wins
->
next
)
{
gint
count
,
i
,
pos
,
position
;
gint
w
;
/* junk var */
(
void
)
w
;
window
=
wins
->
data
;
count
=
pidgin_conv_window_get_gtkconv_count
(
window
);
if
(
count
<=
1
)
continue
;
for
(
position
=
1
;
position
<
count
;
position
++
)
{
gtkconv
=
pidgin_conv_window_get_gtkconv_at_index
(
window
,
position
);
pos
=
irssi_layout_get_setting
(
gtkconv
);
SETTING_TO_INTS
(
pos
,
pos
,
w
);
if
(
pos
<=
0
)
continue
;
/* this could probably use tweaking, but it _should_ work */
for
(
i
=
pos
;
i
<
position
;
i
++
)
{
PidginConversation
*
gtkconv2
=
NULL
;
gint
p
;
gtkconv2
=
pidgin_conv_window_get_gtkconv_at_index
(
window
,
i
);
p
=
irssi_layout_get_setting
(
gtkconv2
);
if
(
p
<=
0
||
p
<=
pos
)
continue
;
gtk_notebook_reorder_child
(
GTK_NOTEBOOK
(
window
->
notebook
),
gtkconv
->
tab_cont
,
i
);
}
}
}
}
static
PurpleCmdRet
irssi_layout_cmd_cb
(
PurpleConversation
*
conv
,
const
gchar
*
cmd
,
gchar
**
args
,
gchar
**
error
,
void
*
data
)
{
const
gchar
*
sub_cmd
=
args
[
0
];
if
(
!
g_ascii_strcasecmp
(
sub_cmd
,
"load"
))
{
irssi_layout_load
();
}
else
if
(
!
g_ascii_strcasecmp
(
sub_cmd
,
"save"
))
{
irssi_layout_save
();
}
else
if
(
!
g_ascii_strcasecmp
(
sub_cmd
,
"reset"
))
{
irssi_layout_reset
();
}
return
PURPLE_CMD_RET_OK
;
}
/******************************************************************************
* "API"
*****************************************************************************/
void
irssi_layout_init
(
PurplePlugin
*
plugin
)
{
const
gchar
*
help
;
if
(
irssi_layout_cmd_id
!=
0
)
return
;
/*
* XXX: Translators: DO NOT TRANSLATE the first "layout" or the "\nsave"
* or "reset" at the beginning of the last line below, or the HTML tags.
*/
help
=
_
(
"<pre>layout <save|reset>: Remember the layout of the "
"current conversations to reopen them when Purple is restarted.
\n
"
"save - saves the current layout
\n
"
"reset - clears the current saved layout
\n
"
"</pre>"
);
irssi_layout_cmd_id
=
purple_cmd_register
(
"layout"
,
"w"
,
PURPLE_CMD_P_PLUGIN
,
PURPLE_CMD_FLAG_IM
|
PURPLE_CMD_FLAG_CHAT
,
NULL
,
PURPLE_CMD_FUNC
(
irssi_layout_cmd_cb
),
help
,
NULL
);
}
void
irssi_layout_uninit
(
PurplePlugin
*
plugin
)
{
if
(
irssi_layout_cmd_id
==
0
)
return
;
purple_cmd_unregister
(
irssi_layout_cmd_id
);
}