split long message on action and notice

This commit is contained in:
misdre 2013-04-05 23:14:51 +02:00
parent c2a5b4fb7d
commit bc5d16c4fb
1 changed files with 94 additions and 45 deletions

View File

@ -2576,10 +2576,57 @@ cmd_load (struct session *sess, char *tbuf, char *word[], char *word_eol[])
return FALSE;
}
char *
split_text(struct session *sess, char *text, int cmd_length, char *splitted_text)
{
unsigned int max;
/* maximum allowed text */
/* :nickname!username@host.com cmd_length */
max = 512; /* rfc 2812 */
max -= 3; /* :, !, @ */
max -= cmd_length;
max -= strlen (sess->server->nick);
max -= strlen (sess->channel);
if (sess->me && sess->me->hostname)
max -= strlen (sess->me->hostname);
else
{
max -= 9; /* username */
max -= 65; /* max possible hostname and '@' */
}
if (strlen (text) > max)
{
unsigned int i = 0;
int size;
/* traverse the utf8 string and find the nearest cut point that
doesn't split 1 char in half */
while (1)
{
size = g_utf8_skip[((unsigned char *)text)[i]];
if ((i + size) >= max)
break;
i += size;
}
max = i;
splitted_text = g_strdup_printf ("%.*s", max, text);
return splitted_text;
}
return NULL;
}
static int
cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
{
char *act = word_eol[2];
char *splitted_text = NULL;
int cmd_length = 22; /* " PRIVMSG ", " ", :, \001ACTION, " ", \001, \r, \n */
int offset = 0;
if (!(*act))
return FALSE;
@ -2601,9 +2648,21 @@ cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[])
/* DCC CHAT failed, try through server */
if (sess->server->connected)
{
sess->server->p_action (sess->server, sess->channel, act);
while ((splitted_text = split_text (sess, act + offset, cmd_length, splitted_text)))
{
sess->server->p_action (sess->server, sess->channel, splitted_text);
/* print it to screen */
inbound_action (sess, sess->channel, sess->server->nick, "", act, TRUE, FALSE);
inbound_action (sess, sess->channel, sess->server->nick, "", splitted_text, TRUE, FALSE);
if (*splitted_text)
offset += strlen(splitted_text);
g_free(splitted_text);
}
sess->server->p_action (sess->server, sess->channel, act + offset);
/* print it to screen */
inbound_action (sess, sess->channel, sess->server->nick, "", act + offset, TRUE, FALSE);
} else
{
notc_msg (sess);
@ -2769,10 +2828,27 @@ cmd_nick (struct session *sess, char *tbuf, char *word[], char *word_eol[])
static int
cmd_notice (struct session *sess, char *tbuf, char *word[], char *word_eol[])
{
char *text = word_eol[3];
char *splitted_text = NULL;
int cmd_length = 12; /* " NOTICE ", " ", :, \r, \n */
int offset = 0;
if (*word[2] && *word_eol[3])
{
sess->server->p_notice (sess->server, word[2], word_eol[3]);
EMIT_SIGNAL (XP_TE_NOTICESEND, sess, word[2], word_eol[3], NULL, NULL, 0);
while ((splitted_text = split_text (sess, text + offset, cmd_length, splitted_text)))
{
sess->server->p_notice (sess->server, word[2], splitted_text);
EMIT_SIGNAL (XP_TE_NOTICESEND, sess, word[2], splitted_text, NULL, NULL, 0);
if (*splitted_text)
offset += strlen(splitted_text);
g_free(splitted_text);
}
sess->server->p_notice (sess->server, word[2], text + offset);
EMIT_SIGNAL (XP_TE_NOTICESEND, sess, word[2], text + offset, NULL, NULL, 0);
return TRUE;
}
return FALSE;
@ -4257,52 +4333,25 @@ handle_say (session *sess, char *text, int check_spch)
if (sess->server->connected)
{
unsigned int max;
unsigned char t = 0;
char *splitted_text = NULL;
int cmd_length = 13; /* " PRIVMSG ", " ", :, \r, \n */
int offset = 0;
/* maximum allowed message text */
/* :nickname!username@host.com PRIVMSG #channel :text\r\n */
max = 512;
max -= 16; /* :, !, @, " PRIVMSG ", " ", :, \r, \n */
max -= strlen (sess->server->nick);
max -= strlen (sess->channel);
if (sess->me && sess->me->hostname)
max -= strlen (sess->me->hostname);
else
while ((splitted_text = split_text (sess, text + offset, cmd_length, splitted_text)))
{
max -= 9; /* username */
max -= 65; /* max possible hostname and '@' */
}
inbound_chanmsg (sess->server, sess, sess->channel, sess->server->nick,
splitted_text, TRUE, FALSE);
sess->server->p_message (sess->server, sess->channel, splitted_text);
if (strlen (text) > max)
{
unsigned int i = 0;
int size;
if (*splitted_text)
offset += strlen(splitted_text);
/* traverse the utf8 string and find the nearest cut point that
doesn't split 1 char in half */
while (1)
{
size = g_utf8_skip[((unsigned char *)text)[i]];
if ((i + size) >= max)
break;
i += size;
}
max = i;
t = text[max];
text[max] = 0; /* insert a NULL terminator to shorten it */
g_free(splitted_text);
}
inbound_chanmsg (sess->server, sess, sess->channel, sess->server->nick,
text, TRUE, FALSE);
sess->server->p_message (sess->server, sess->channel, text);
if (t)
{
text[max] = t;
handle_say (sess, text + max, FALSE);
}
text + offset, TRUE, FALSE);
sess->server->p_message (sess->server, sess->channel, text + offset);
} else
{
notc_msg (sess);