..adding new files..

git-svn-id: http://svn.irssi.org/repos/irssi/trunk@171 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2000-04-26 08:03:38 +00:00 committed by cras
commit c95034c6de
206 changed files with 31247 additions and 0 deletions

View file

@ -0,0 +1 @@
SUBDIRS = core irc

View file

@ -0,0 +1,38 @@
noinst_LTLIBRARIES = libfe_common_core.la
INCLUDES = \
$(GLIB_CFLAGS) \
-I$(top_srcdir)/src -I$(top_srcdir)/src/core/ \
-DHELPDIR=\""$(datadir)/irssi/help"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\"
libfe_common_core_la_SOURCES = \
autorun.c \
command-history.c \
fe-common-core.c \
fe-core-commands.c \
fe-log.c \
fe-server.c \
fe-settings.c \
hilight-text.c \
keyboard.c \
module-formats.c \
nick-hilight.c \
printtext.c \
themes.c \
translation.c \
window-items.c \
windows.c
noinst_HEADERS = \
command-history.h \
fe-common-core.h \
hilight-text.h \
keyboard.h \
module-formats.h \
module.h \
printtext.h \
themes.h \
translation.h \
window-items.h \
windows.h

View file

@ -0,0 +1,62 @@
/*
autorun.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "signals.h"
#include "line-split.h"
#include "special-vars.h"
#include "windows.h"
static void sig_autorun(void)
{
char tmpbuf[1024], *str, *path;
LINEBUF_REC *buffer = NULL;
int f, ret, recvlen;
/* open ~/.irssi/startup and run all commands in it */
path = g_strdup_printf("%s/.irssi/startup", g_get_home_dir());
f = open(path, O_RDONLY);
g_free(path);
if (f == -1) {
/* file not found */
return;
}
do {
recvlen = read(f, tmpbuf, sizeof(tmpbuf));
ret = line_split(tmpbuf, recvlen, &str, &buffer);
eval_special_string(str, "", active_win->active_server, active_win->active);
} while (ret > 0);
line_split_free(buffer);
close(f);
}
void autorun_init(void)
{
signal_add_last("irssi init finished", (SIGNAL_FUNC) sig_autorun);
}
void autorun_deinit(void)
{
signal_remove("irssi init finished", (SIGNAL_FUNC) sig_autorun);
}

View file

@ -0,0 +1,182 @@
/*
command-history.c : irssi
Copyright (C) 1999 Timo Sirainen
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 "module.h"
#include "signals.h"
#include "misc.h"
#include "special-vars.h"
#include "settings.h"
#include "windows.h"
#include "window-items.h"
/* command history */
static GList *cmdhist, *histpos;
static int histlines;
static int window_history;
void command_history_add(WINDOW_REC *window, const char *text, int prepend)
{
GList **pcmdhist, *link;
int *phistlines;
g_return_if_fail(text != NULL);
if (window_history) {
/* window specific command history */
pcmdhist = &window->cmdhist;
phistlines = &window->histlines;
} else {
/* global command history */
pcmdhist = &cmdhist;
phistlines = &histlines;
}
if (settings_get_int("max_command_history") < 1 || *phistlines < settings_get_int("max_command_history"))
(*phistlines)++;
else {
link = *pcmdhist;
g_free(link->data);
*pcmdhist = g_list_remove_link(*pcmdhist, link);
g_list_free_1(link);
}
if (prepend)
*pcmdhist = g_list_prepend(*pcmdhist, g_strdup(text));
else
*pcmdhist = g_list_append(*pcmdhist, g_strdup(text));
}
const char *command_history_prev(WINDOW_REC *window, const char *text)
{
GList *pos, **phistpos;
phistpos = window_history ? &window->histpos : &histpos;
pos = *phistpos;
if (*phistpos == NULL)
*phistpos = g_list_last(window_history ? window->cmdhist : cmdhist);
else
*phistpos = (*phistpos)->prev;
if (*text != '\0' &&
(pos == NULL || strcmp(pos->data, text) != 0)) {
/* save the old entry to history */
command_history_add(window, text, FALSE);
}
return *phistpos == NULL ? "" : (*phistpos)->data;
}
const char *command_history_next(WINDOW_REC *window, const char *text)
{
GList *pos, **phistpos;
phistpos = window_history ? &window->histpos : &histpos;
pos = *phistpos;
if (*phistpos == NULL)
*phistpos = window_history ? window->cmdhist : cmdhist;
else
*phistpos = (*phistpos)->next;
if (*text != '\0' &&
(pos == NULL || strcmp(pos->data, text) != 0)) {
/* save the old entry to history */
command_history_add(window, text, TRUE);
}
return *phistpos == NULL ? "" : (*phistpos)->data;
}
void command_history_clear_pos(WINDOW_REC *window)
{
window->histpos = NULL;
histpos = NULL;
}
static void sig_window_created(WINDOW_REC *window)
{
window->histlines = 0;
window->cmdhist = NULL;
window->histpos = NULL;
}
static void sig_window_destroyed(WINDOW_REC *window)
{
g_list_foreach(window->cmdhist, (GFunc) g_free, NULL);
g_list_free(window->cmdhist);
}
static char *special_history_func(const char *text, void *item, int *free_ret)
{
WINDOW_REC *window;
GList *tmp;
char *findtext, *ret;
window = item == NULL ? active_win : window_item_window(item);
findtext = g_strdup_printf("*%s*", text);
ret = NULL;
tmp = window_history ? window->cmdhist : cmdhist;
for (; tmp != NULL; tmp = tmp->next) {
const char *line = tmp->data;
if (match_wildcards(findtext, line)) {
*free_ret = TRUE;
ret = g_strdup(line);
}
}
g_free(findtext);
return ret;
}
static void read_settings(void)
{
window_history = settings_get_bool("toggle_window_history");
}
void command_history_init(void)
{
settings_add_int("history", "max_textwidget_lines", 1000);
settings_add_int("history", "block_remove_lines", 20);
settings_add_int("history", "max_command_history", 100);
settings_add_bool("history", "toggle_window_history", FALSE);
special_history_func_set(special_history_func);
histlines = 0;
cmdhist = NULL; histpos = NULL;
read_settings();
signal_add("window created", (SIGNAL_FUNC) sig_window_created);
signal_add("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
}
void command_history_deinit(void)
{
signal_remove("window created", (SIGNAL_FUNC) sig_window_created);
signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
g_list_foreach(cmdhist, (GFunc) g_free, NULL);
g_list_free(cmdhist);
}

View file

@ -0,0 +1,16 @@
#ifndef __COMMAND_HISTORY_H
#define __COMMAND_HISTORY_H
#include "windows.h"
void command_history_init(void);
void command_history_deinit(void);
void command_history_add(WINDOW_REC *window, const char *text, int prepend);
const char *command_history_prev(WINDOW_REC *window, const char *text);
const char *command_history_next(WINDOW_REC *window, const char *text);
void command_history_clear_pos(WINDOW_REC *window);
#endif

View file

@ -0,0 +1,132 @@
/*
fe-common-core.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "levels.h"
#include "settings.h"
#include "hilight-text.h"
#include "command-history.h"
#include "keyboard.h"
#include "printtext.h"
#include "themes.h"
#include "translation.h"
#include "windows.h"
#include "window-items.h"
#include <sys/signal.h>
void autorun_init(void);
void autorun_deinit(void);
void fe_core_log_init(void);
void fe_core_log_deinit(void);
void fe_server_init(void);
void fe_server_deinit(void);
void fe_settings_init(void);
void fe_settings_deinit(void);
void nick_hilight_init(void);
void nick_hilight_deinit(void);
void fe_core_commands_init(void);
void fe_core_commands_deinit(void);
void fe_common_core_init(void)
{
settings_add_bool("lookandfeel", "toggle_show_menubar", TRUE);
settings_add_bool("lookandfeel", "toggle_show_toolbar", FALSE);
settings_add_bool("lookandfeel", "toggle_show_statusbar", TRUE);
settings_add_bool("lookandfeel", "toggle_show_nicklist", TRUE);
settings_add_bool("lookandfeel", "toggle_show_timestamps", FALSE);
settings_add_bool("lookandfeel", "toggle_show_msgs_timestamps", FALSE);
settings_add_bool("lookandfeel", "toggle_hide_text_style", FALSE);
settings_add_bool("lookandfeel", "toggle_bell_beeps", FALSE);
settings_add_bool("lookandfeel", "toggle_actlist_moves", FALSE);
settings_add_bool("lookandfeel", "toggle_show_nickmode", TRUE);
settings_add_bool("lookandfeel", "toggle_show_topicbar", TRUE);
settings_add_bool("lookandfeel", "toggle_use_status_window", FALSE);
settings_add_bool("lookandfeel", "toggle_use_msgs_window", TRUE);
settings_add_bool("lookandfeel", "toggle_autoraise_msgs_window", FALSE);
settings_add_bool("lookandfeel", "toggle_autocreate_query", TRUE);
settings_add_bool("lookandfeel", "toggle_notifylist_popups", FALSE);
settings_add_bool("lookandfeel", "toggle_use_tabbed_windows", TRUE);
settings_add_int("lookandfeel", "tab_orientation", 3);
settings_add_str("lookandfeel", "current_theme", "default");
autorun_init();
nick_hilight_init();
hilight_text_init();
command_history_init();
keyboard_init();
printtext_init();
fe_log_init();
fe_server_init();
fe_settings_init();
themes_init();
translation_init();
windows_init();
window_items_init();
fe_core_commands_init();
}
void fe_common_core_deinit(void)
{
autorun_deinit();
nick_hilight_deinit();
hilight_text_deinit();
command_history_deinit();
keyboard_deinit();
printtext_deinit();
fe_log_deinit();
fe_server_deinit();
fe_settings_deinit();
themes_deinit();
translation_deinit();
windows_deinit();
window_items_deinit();
fe_core_commands_deinit();
}
void fe_common_core_finish_init(void)
{
WINDOW_REC *window;
signal(SIGPIPE, SIG_IGN);
if (settings_get_bool("toggle_use_status_window")) {
window = window_create(NULL, TRUE);
window_set_name(window, "(status)");
window_set_level(window, MSGLEVEL_ALL ^ (settings_get_bool("toggle_use_msgs_window") ? (MSGLEVEL_MSGS|MSGLEVEL_ACTIONS) : 0));
}
if (settings_get_bool("toggle_use_msgs_window")) {
window = window_create(NULL, TRUE);
window_set_name(window, "(msgs)");
window_set_level(window, MSGLEVEL_MSGS|MSGLEVEL_ACTIONS);
}
if (windows == NULL) {
/* we have to have at least one window.. */
window = window_create(NULL, TRUE);
}
}

View file

@ -0,0 +1,8 @@
#ifndef __FE_COMMON_CORE_H
#define __FE_COMMON_CORE_H
void fe_common_core_init(void);
void fe_common_core_deinit(void);
void fe_common_core_finish_init(void);
#endif

View file

@ -0,0 +1,266 @@
/*
fe-core-commands.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "commands.h"
#include "levels.h"
#include "line-split.h"
#include "irssi-version.h"
#include "windows.h"
static gchar *ret_texts[] =
{
"Invalid parameter",
"Not enough parameters given",
"Not connected to IRC server yet",
"Not joined to any channels yet",
"Error: getsockname() failed",
"Error: listen() failed",
"Multiple matches found, be more specific",
"Nick not found",
"Not joined to such channel",
"Server not found",
"Channel not fully synchronized yet, try again after a while",
"Doing this is not a good idea. Add -YES if you really mean it",
};
static gint commands_compare(COMMAND_REC *rec, COMMAND_REC *rec2)
{
if (rec->category == NULL && rec2->category != NULL)
return -1;
if (rec2->category == NULL && rec->category != NULL)
return 1;
return strcmp(rec->cmd, rec2->cmd);
}
static void help_category(GSList *cmdlist, gint items, gint max)
{
COMMAND_REC *rec, *last;
GString *str;
GSList *tmp;
gint lines, cols, line, col, skip;
gchar *cmdbuf;
str = g_string_new(NULL);
cols = max > 65 ? 1 : (65 / max);
lines = items <= cols ? 1 : items / cols+1;
last = NULL; cmdbuf = g_malloc(max+1); cmdbuf[max] = '\0';
for (line = 0, col = 0, skip = 1, tmp = cmdlist; line < lines; last = rec, tmp = tmp->next)
{
rec = tmp->data;
if (--skip == 0)
{
skip = lines;
memset(cmdbuf, ' ', max);
memcpy(cmdbuf, rec->cmd, strlen(rec->cmd));
g_string_sprintfa(str, "%s ", cmdbuf);
cols++;
}
if (col == cols || tmp->next == NULL)
{
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, str->str);
g_string_truncate(str, 0);
col = 0; line++;
tmp = g_slist_nth(cmdlist, line-1); skip = 1;
}
}
if (str->len != 0)
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, str->str);
g_string_free(str, TRUE);
g_free(cmdbuf);
}
static int show_help(COMMAND_REC *cmd)
{
char tmpbuf[1024], *str, *path;
LINEBUF_REC *buffer = NULL;
int f, ret, recvlen;
/* helpdir/command or helpdir/category/command */
if (cmd->category == NULL)
path = g_strdup_printf("%s/%s", HELPDIR, cmd->cmd);
else
path = g_strdup_printf("%s/%s/%s", HELPDIR, cmd->category, cmd->cmd);
f = open(path, O_RDONLY);
g_free(path);
if (f == -1)
return FALSE;
/* just print to screen whatever is in the file */
do
{
recvlen = read(f, tmpbuf, sizeof(tmpbuf));
ret = line_split(tmpbuf, recvlen, &str, &buffer);
printtext(NULL, NULL, MSGLEVEL_NEVER, str);
}
while (ret > 0);
line_split_free(buffer);
close(f);
return TRUE;
}
static void cmd_help(gchar *data)
{
COMMAND_REC *rec, *last, *helpitem;
GSList *tmp, *cmdlist;
gint len, max, items, findlen;
gboolean header;
g_return_if_fail(data != NULL);
/* sort the commands list */
commands = g_slist_sort(commands, (GCompareFunc) commands_compare);
/* print command, sort by category */
cmdlist = NULL; last = NULL; header = FALSE; helpitem = NULL;
max = items = 0; findlen = strlen(data);
for (tmp = commands; tmp != NULL; last = rec, tmp = tmp->next)
{
rec = tmp->data;
if (last != NULL && rec->category != NULL &&
(last->category == NULL || strcmp(rec->category, last->category) != 0))
{
/* category changed */
if (items > 0)
{
if (!header)
{
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "Irssi commands:");
header = TRUE;
}
if (last->category != NULL)
{
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "");
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s:", last->category);
}
help_category(cmdlist, items, max);
}
g_slist_free(cmdlist); cmdlist = NULL;
items = 0; max = 0;
}
if (last != NULL && g_strcasecmp(rec->cmd, last->cmd) == 0)
continue; /* don't display same command twice */
if (strlen(rec->cmd) >= findlen && g_strncasecmp(rec->cmd, data, findlen) == 0)
{
if (rec->cmd[findlen] == '\0')
{
helpitem = rec;
break;
}
else if (strchr(rec->cmd+findlen+1, ' ') == NULL)
{
/* not a subcommand (and matches the query) */
len = strlen(rec->cmd);
if (max < len) max = len;
items++;
cmdlist = g_slist_append(cmdlist, rec);
}
}
}
if ((helpitem == NULL && items == 0) || (helpitem != NULL && !show_help(helpitem)))
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "No help for %s", data);
if (items != 0)
{
/* display the last category */
if (!header)
{
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "Irssi commands:");
header = TRUE;
}
if (last->category != NULL)
{
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "");
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s:", last->category);
}
help_category(cmdlist, items, max);
g_slist_free(cmdlist);
}
}
static void cmd_echo(const char *data, void *server, WI_ITEM_REC *item)
{
g_return_if_fail(data != NULL);
printtext(server, item == NULL ? NULL : item->name, MSGLEVEL_CRAP, "%s", data);
}
static void cmd_version(char *data)
{
g_return_if_fail(data != NULL);
if (*data == '\0')
printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "Client: "PACKAGE" " IRSSI_VERSION);
}
static void cmd_unknown(const char *data, void *server, WI_ITEM_REC *item)
{
char *cmd;
cmd = g_strdup(data); g_strup(cmd);
printtext(server, item == NULL ? NULL : item->name, MSGLEVEL_CRAP, "Unknown command: %s", cmd);
g_free(cmd);
signal_stop();
}
static void event_cmderror(gpointer error)
{
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, ret_texts[GPOINTER_TO_INT(error)]);
}
void fe_core_commands_init(void)
{
command_bind("help", NULL, (SIGNAL_FUNC) cmd_help);
command_bind("echo", NULL, (SIGNAL_FUNC) cmd_echo);
command_bind("version", NULL, (SIGNAL_FUNC) cmd_version);
signal_add("unknown command", (SIGNAL_FUNC) cmd_unknown);
signal_add("default command", (SIGNAL_FUNC) cmd_unknown);
signal_add("error command", (SIGNAL_FUNC) event_cmderror);
}
void fe_core_commands_deinit(void)
{
command_unbind("help", (SIGNAL_FUNC) cmd_help);
command_unbind("echo", (SIGNAL_FUNC) cmd_echo);
command_unbind("version", (SIGNAL_FUNC) cmd_version);
signal_remove("unknown command", (SIGNAL_FUNC) cmd_unknown);
signal_remove("default command", (SIGNAL_FUNC) cmd_unknown);
signal_remove("error command", (SIGNAL_FUNC) event_cmderror);
}

402
src/fe-common/core/fe-log.c Normal file
View file

@ -0,0 +1,402 @@
/*
fe-log.c : irssi
Copyright (C) 1999 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "commands.h"
#include "server.h"
#include "levels.h"
#include "misc.h"
#include "log.h"
#include "special-vars.h"
#include "settings.h"
#include "windows.h"
#include "window-items.h"
/* close autologs after 5 minutes of inactivity */
#define AUTOLOG_INACTIVITY_CLOSE (60*5)
#define LOG_DIR_CREATE_MODE 0770
static int autolog_level;
static int autoremove_tag;
static const char *autolog_path;
static void cmd_log_open(const char *data)
{
/* /LOG OPEN [-noopen] [-autoopen] [-channels <channels>] [-window]
[-rotate hour|day|week|month] <fname> [<levels>] */
char *params, *args, *itemarg, *rotatearg, *fname, *levels;
char window[MAX_INT_STRLEN];
LOG_REC *log;
int opened, level, rotate;
args = "channels rotate";
params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST,
&args, &itemarg, &rotatearg, &fname, &levels);
if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
rotate = LOG_ROTATE_NEVER;
if (stristr(args, "-rotate")) {
rotate = log_str2rotate(rotatearg);
if (rotate < 0) rotate = LOG_ROTATE_NEVER;
}
level = level2bits(levels);
if (level == 0) level = MSGLEVEL_ALL;
if (stristr(args, "-window")) {
/* log by window ref# */
ltoa(window, active_win->refnum);
itemarg = window;
}
log = log_create_rec(fname, level, itemarg);
if (log != NULL && log->handle == -1 && stristr(args, "-noopen") == NULL) {
/* start logging */
opened = log_start_logging(log);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
opened ? IRCTXT_LOG_OPENED :
IRCTXT_LOG_CREATE_FAILED, fname);
if (!opened) log_close(log);
}
if (log != NULL) {
if (stristr(args, "-autoopen"))
log->autoopen = TRUE;
log->rotate = rotate;
log_update(log);
}
g_free(params);
}
static void cmd_log_close(const char *data)
{
LOG_REC *log;
log = log_find(data);
if (log == NULL)
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_LOG_NOT_OPEN, data);
else {
log_close(log);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_CLOSED, data);
}
}
static void cmd_log_start(const char *data)
{
LOG_REC *log;
log = log_find(data);
if (log != NULL) {
log_start_logging(log);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_OPENED, data);
}
}
static void cmd_log_stop(const char *data)
{
LOG_REC *log;
log = log_find(data);
if (log == NULL || log->handle == -1)
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_LOG_NOT_OPEN, data);
else {
log_stop_logging(log);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_CLOSED, data);
}
}
static void cmd_log_list(void)
{
GSList *tmp;
char *levelstr, *items, *rotate;
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_LOG_LIST_HEADER);
for (tmp = logs; tmp != NULL; tmp = tmp->next) {
LOG_REC *rec = tmp->data;
levelstr = bits2level(rec->level);
items = rec->items == NULL ? NULL :
g_strjoinv(",", rec->items);
rotate = rec->rotate == 0 ? NULL :
g_strdup_printf(" -rotate %s", log_rotate2str(rec->rotate));
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_LOG_LIST,
rec->fname, items != NULL ? items : "",
levelstr, rotate != NULL ? rotate : "",
rec->autoopen ? " -autoopen" : "");
g_free_not_null(rotate);
g_free_not_null(items);
g_free(levelstr);
}
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_LOG_LIST_FOOTER);
}
static void cmd_log(const char *data, SERVER_REC *server, void *item)
{
command_runsub("log", data, server, item);
}
static LOG_REC *log_find_item(const char *item)
{
GSList *tmp;
for (tmp = logs; tmp != NULL; tmp = tmp->next) {
LOG_REC *rec = tmp->data;
if (rec->items != NULL && strarray_find(rec->items, item) != -1)
return rec;
}
return NULL;
}
static void cmd_window_log(const char *data)
{
/* /WINDOW LOG ON|OFF|TOGGLE [<filename>] */
LOG_REC *log;
char *params, *set, *fname, window[MAX_INT_STRLEN];
int open_log, close_log;
params = cmd_get_params(data, 2, &set, &fname);
ltoa(window, active_win->refnum);
log = log_find_item(window);
open_log = close_log = FALSE;
if (g_strcasecmp(set, "ON") == 0)
open_log = TRUE;
else if (g_strcasecmp(set, "OFF") == 0) {
close_log = TRUE;
} else if (g_strcasecmp(set, "TOGGLE") == 0) {
open_log = log == NULL;
close_log = log != NULL;
} else {
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_NOT_TOGGLE);
g_free(params);
return;
}
if (open_log && log == NULL) {
/* irc.log.<windowname> or irc.log.Window<ref#> */
fname = *fname != '\0' ? g_strdup(fname) :
g_strdup_printf("~/irc.log.%s%s",
active_win->name != NULL ? active_win->name : "Window",
active_win->name != NULL ? "" : window);
log = log_create_rec(fname, MSGLEVEL_ALL, window);
if (log != NULL) log_update(log);
g_free(fname);
}
if (open_log && log != NULL) {
log_start_logging(log);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_OPENED, log->fname);
} else if (close_log && log != NULL && log->handle != -1) {
log_stop_logging(log);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_CLOSED, log->fname);
}
g_free(params);
}
/* Create log file entry to window, but don't start logging */
static void cmd_window_logfile(const char *data)
{
LOG_REC *log;
char window[MAX_INT_STRLEN];
ltoa(window, active_win->refnum);
log = log_find_item(window);
if (log != NULL) {
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLOG_FILE_LOGGING);
return;
}
log = log_create_rec(data, MSGLEVEL_ALL, window);
if (log == NULL)
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLOG_FILE, data);
else
log_update(log);
}
static void autologs_close_all(void)
{
GSList *tmp, *next;
for (tmp = logs; tmp != NULL; tmp = next) {
LOG_REC *rec = tmp->data;
next = tmp->next;
if (rec->temp) log_close(rec);
}
}
static void autolog_log(void *server, const char *target)
{
LOG_REC *log;
char *fname, *dir, *str;
log = log_find_item(target);
if (log != NULL) return;
fname = parse_special_string(autolog_path, server, NULL, target, NULL);
if (log_find(fname) == NULL) {
str = convert_home(fname);
dir = g_dirname(str);
g_free(str);
mkdir(dir, LOG_DIR_CREATE_MODE);
g_free(dir);
log = log_create_rec(fname, autolog_level, target);
if (log != NULL) {
log->temp = TRUE;
log_update(log);
log_start_logging(log);
}
}
g_free(fname);
}
/* write to logs created with /WINDOW LOG */
static void sig_printtext_stripped(void *server, const char *target, gpointer levelp, const char *text)
{
char windownum[MAX_INT_STRLEN];
WINDOW_REC *window;
LOG_REC *log;
int level;
level = GPOINTER_TO_INT(levelp);
if ((autolog_level & level) && target != NULL && *target != '\0')
autolog_log(server, target);
window = window_find_closest(server, target, level);
if (window != NULL) {
ltoa(windownum, window->refnum);
log = log_find_item(windownum);
if (log != NULL) log_write_rec(log, text);
}
}
static int sig_autoremove(void)
{
GSList *tmp, *next;
time_t removetime;
removetime = time(NULL)-AUTOLOG_INACTIVITY_CLOSE;
for (tmp = logs; tmp != NULL; tmp = next) {
LOG_REC *rec = tmp->data;
next = tmp->next;
/* FIXME: here is a small kludge - We don't want autolog to
automatically close the logs with channels, only with
private messages. However, this is CORE module and we
don't know how to figure out if item is a channel or not,
so just assume that channels are everything that don't
start with alphanumeric character. */
if (!rec->temp || rec->last > removetime ||
rec->items == NULL || !isalnum(**rec->items))
continue;
log_close(rec);
}
return 1;
}
static void sig_window_item_remove(WINDOW_REC *window, WI_ITEM_REC *item)
{
GSList *tmp;
for (tmp = logs; tmp != NULL; tmp = tmp->next) {
LOG_REC *rec = tmp->data;
if (rec->temp && g_strcasecmp(rec->items[0], item->name) == 0) {
log_close(rec);
break;
}
}
}
static void sig_log_locked(LOG_REC *log)
{
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
IRCTXT_LOG_LOCKED, log->fname);
}
static void read_settings(void)
{
int old_autolog = autolog_level;
autolog_path = settings_get_str("autolog_path");
autolog_level = !settings_get_bool("autolog") ? 0 :
level2bits(settings_get_str("autolog_level"));
if (old_autolog && !autolog_level)
autologs_close_all();
}
void fe_log_init(void)
{
autoremove_tag = g_timeout_add(60000, (GSourceFunc) sig_autoremove, NULL);
settings_add_str("log", "autolog_path", "~/irclogs/$tag/$0.log");
settings_add_str("log", "autolog_level", "all");
settings_add_bool("log", "autolog", FALSE);
autolog_level = 0;
read_settings();
command_bind("log", NULL, (SIGNAL_FUNC) cmd_log);
command_bind("log open", NULL, (SIGNAL_FUNC) cmd_log_open);
command_bind("log close", NULL, (SIGNAL_FUNC) cmd_log_close);
command_bind("log start", NULL, (SIGNAL_FUNC) cmd_log_start);
command_bind("log stop", NULL, (SIGNAL_FUNC) cmd_log_stop);
command_bind("log ", NULL, (SIGNAL_FUNC) cmd_log_list);
command_bind("window log", NULL, (SIGNAL_FUNC) cmd_window_log);
command_bind("window logfile", NULL, (SIGNAL_FUNC) cmd_window_logfile);
signal_add_first("print text stripped", (SIGNAL_FUNC) sig_printtext_stripped);
signal_add("window item remove", (SIGNAL_FUNC) sig_window_item_remove);
signal_add("log locked", (SIGNAL_FUNC) sig_log_locked);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
}
void fe_log_deinit(void)
{
g_source_remove(autoremove_tag);
command_unbind("log", (SIGNAL_FUNC) cmd_log);
command_unbind("log open", (SIGNAL_FUNC) cmd_log_open);
command_unbind("log close", (SIGNAL_FUNC) cmd_log_close);
command_unbind("log start", (SIGNAL_FUNC) cmd_log_start);
command_unbind("log stop", (SIGNAL_FUNC) cmd_log_stop);
command_unbind("log ", (SIGNAL_FUNC) cmd_log_list);
command_unbind("window log", (SIGNAL_FUNC) cmd_window_log);
command_unbind("window logfile", (SIGNAL_FUNC) cmd_window_logfile);
signal_remove("print text stripped", (SIGNAL_FUNC) sig_printtext_stripped);
signal_remove("window item remove", (SIGNAL_FUNC) sig_window_item_remove);
signal_remove("log locked", (SIGNAL_FUNC) sig_log_locked);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
}

View file

@ -0,0 +1,96 @@
/*
fe-server.c : irssi
Copyright (C) 1999 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "settings.h"
#include "network.h"
#include "levels.h"
#include "server.h"
static void sig_server_looking(SERVER_REC *server)
{
g_return_if_fail(server != NULL);
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOOKING_UP, server->connrec->address);
}
static void sig_server_connecting(SERVER_REC *server, IPADDR *ip)
{
char ipaddr[MAX_IP_LEN];
g_return_if_fail(server != NULL);
g_return_if_fail(ip != NULL);
net_ip2host(ip, ipaddr);
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CONNECTING,
server->connrec->address, ipaddr, server->connrec->port);
}
static void sig_server_connected(SERVER_REC *server)
{
g_return_if_fail(server != NULL);
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE,
IRCTXT_CONNECTION_ESTABLISHED, server->connrec->address);
}
static void sig_connect_failed(SERVER_REC *server, gchar *msg)
{
g_return_if_fail(server != NULL);
if (msg == NULL) {
/* no message so this wasn't unexpected fail - send
connection_lost message instead */
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
IRCTXT_CONNECTION_LOST, server->connrec->address);
} else {
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
IRCTXT_CANT_CONNECT, server->connrec->address, server->connrec->port, msg);
}
}
static void sig_server_disconnected(SERVER_REC *server)
{
g_return_if_fail(server != NULL);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
IRCTXT_CONNECTION_LOST, server->connrec->address);
}
void fe_server_init(void)
{
signal_add("server looking", (SIGNAL_FUNC) sig_server_looking);
signal_add("server connecting", (SIGNAL_FUNC) sig_server_connecting);
signal_add("server connected", (SIGNAL_FUNC) sig_server_connected);
signal_add("server connect failed", (SIGNAL_FUNC) sig_connect_failed);
signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
}
void fe_server_deinit(void)
{
signal_remove("server looking", (SIGNAL_FUNC) sig_server_looking);
signal_remove("server connecting", (SIGNAL_FUNC) sig_server_connecting);
signal_remove("server connected", (SIGNAL_FUNC) sig_server_connected);
signal_remove("server connect failed", (SIGNAL_FUNC) sig_connect_failed);
signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
}

View file

@ -0,0 +1,215 @@
/*
fe-settings.c : irssi
Copyright (C) 1999 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "commands.h"
#include "server.h"
#include "lib-config/iconfig.h"
#include "settings.h"
#include "levels.h"
static void set_print(SETTINGS_REC *rec)
{
const char *value;
char value_int[MAX_INT_STRLEN];
switch (rec->type) {
case SETTING_TYPE_BOOLEAN:
value = settings_get_bool(rec->key) ? "ON" : "OFF";
break;
case SETTING_TYPE_INT:
g_snprintf(value_int, sizeof(value_int), "%d", settings_get_int(rec->key));
value = value_int;
break;
case SETTING_TYPE_STRING:
value = settings_get_str(rec->key);
break;
default:
value = "";
}
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s = %s", rec->key, value);
}
static void set_boolean(const char *key, const char *value)
{
if (g_strcasecmp(value, "ON") == 0)
iconfig_set_bool("settings", key, TRUE);
else if (g_strcasecmp(value, "OFF") == 0)
iconfig_set_bool("settings", key, FALSE);
else if (g_strcasecmp(value, "TOGGLE") == 0)
iconfig_set_bool("settings", key, !settings_get_bool(key));
else
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_NOT_TOGGLE);
}
static void cmd_set(char *data)
{
GSList *sets, *tmp;
char *params, *key, *value, *last_section;
int keylen, found;
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value);
keylen = strlen(key);
last_section = ""; found = 0;
sets = settings_get_sorted();
for (tmp = sets; tmp != NULL; tmp = tmp->next) {
SETTINGS_REC *rec = tmp->data;
if ((*value != '\0' && g_strcasecmp(rec->key, key) != 0) ||
(*value == '\0' && keylen != 0 && g_strncasecmp(rec->key, key, keylen) != 0))
continue;
if (strcmp(last_section, rec->section) != 0) {
/* print section */
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%_[ %s ]", rec->section);
last_section = rec->section;
}
if (*value != '\0') {
/* change the setting */
switch (rec->type) {
case SETTING_TYPE_BOOLEAN:
set_boolean(key, value);
break;
case SETTING_TYPE_INT:
iconfig_set_int("settings", key, atoi(value));
break;
case SETTING_TYPE_STRING:
iconfig_set_str("settings", key, value);
break;
}
signal_emit("setup changed", 0);
}
set_print(rec);
found = TRUE;
}
g_slist_free(sets);
if (!found)
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown setting %s", key);
g_free(params);
}
static void cmd_toggle(const char *data)
{
char *params, *key, *value;
int type;
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value);
type = settings_get_type(key);
if (type == -1)
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown setting %_%s", key);
else if (type != SETTING_TYPE_BOOLEAN)
printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Setting %_%s%_ isn't boolean, use /SET", key);
else {
set_boolean(key, *value != '\0' ? value : "TOGGLE");
set_print(settings_get_record(key));
}
g_free(params);
}
static void show_aliases(const char *alias)
{
CONFIG_NODE *node;
GSList *tmp;
int aliaslen;
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_ALIASLIST_HEADER);
node = iconfig_node_traverse("aliases", FALSE);
tmp = node == NULL ? NULL : node->value;
aliaslen = strlen(alias);
for (; tmp != NULL; tmp = tmp->next) {
CONFIG_NODE *node = tmp->data;
if (node->type != NODE_TYPE_KEY)
continue;
if (aliaslen != 0 && g_strncasecmp(node->key, alias, aliaslen) != 0)
continue;
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_ALIASLIST_LINE,
node->key, node->value);
}
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_ALIASLIST_FOOTER);
}
static void alias_remove(const char *alias)
{
if (iconfig_get_str("aliases", alias, NULL) == NULL)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_ALIAS_NOT_FOUND, alias);
else {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_ALIAS_REMOVED, alias);
iconfig_set_str("aliases", alias, NULL);
}
}
static void cmd_alias(const char *data)
{
char *params, *alias, *value;
g_return_if_fail(data != NULL);
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &alias, &value);
if (*alias == '-') {
if (alias[1] != '\0') alias_remove(alias+1);
} else if (*alias == '\0' || *value == '\0')
show_aliases(alias);
else {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_ALIAS_ADDED, alias);
iconfig_set_str("aliases", alias, value);
}
g_free(params);
}
static void cmd_unalias(const char *data)
{
g_return_if_fail(data != NULL);
if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
alias_remove(data);
}
void fe_settings_init(void)
{
command_bind("set", NULL, (SIGNAL_FUNC) cmd_set);
command_bind("toggle", NULL, (SIGNAL_FUNC) cmd_toggle);
command_bind("alias", NULL, (SIGNAL_FUNC) cmd_alias);
command_bind("unalias", NULL, (SIGNAL_FUNC) cmd_unalias);
}
void fe_settings_deinit(void)
{
command_unbind("set", (SIGNAL_FUNC) cmd_set);
command_unbind("toggle", (SIGNAL_FUNC) cmd_toggle);
command_unbind("alias", (SIGNAL_FUNC) cmd_alias);
command_unbind("unalias", (SIGNAL_FUNC) cmd_unalias);
}

View file

@ -0,0 +1,354 @@
/*
hilight-text.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "commands.h"
#include "misc.h"
#include "lib-config/iconfig.h"
#include "settings.h"
#include "levels.h"
#include "server.h"
#include "hilight-text.h"
#define DEFAULT_HILIGHT_CHECK_LEVEL \
(MSGLEVEL_PUBLIC | MSGLEVEL_MSGS | MSGLEVEL_NOTICES | MSGLEVEL_ACTIONS)
static int hilight_next;
GSList *hilights;
static void hilight_add_config(HILIGHT_REC *rec)
{
CONFIG_NODE *node;
node = iconfig_node_traverse("(hilights", TRUE);
node = config_node_section(node, NULL, NODE_TYPE_BLOCK);
config_node_set_str(node, "text", rec->text);
if (rec->level > 0) config_node_set_int(node, "level", rec->level);
if (rec->color) config_node_set_str(node, "color", rec->color);
if (rec->nickmask) config_node_set_bool(node, "nickmask", TRUE);
if (rec->fullword) config_node_set_bool(node, "fullword", TRUE);
if (rec->regexp) config_node_set_bool(node, "regexp", TRUE);
if (rec->channels != NULL && *rec->channels != NULL) {
node = config_node_section(node, "channels", NODE_TYPE_LIST);
config_node_add_list(node, rec->channels);
}
}
static void hilight_remove_config(HILIGHT_REC *rec)
{
CONFIG_NODE *node;
node = iconfig_node_traverse("hilights", FALSE);
if (node != NULL) config_node_list_remove(node, g_slist_index(hilights, rec));
}
static void hilight_destroy(HILIGHT_REC *rec)
{
g_free(rec->text);
g_free_not_null(rec->color);
g_free(rec);
}
static void hilights_destroy_all(void)
{
g_slist_foreach(hilights, (GFunc) hilight_destroy, NULL);
g_slist_free(hilights);
hilights = NULL;
}
static void hilight_remove(HILIGHT_REC *rec)
{
hilight_remove_config(rec);
hilights = g_slist_remove(hilights, rec);
hilight_destroy(rec);
}
static HILIGHT_REC *hilight_find(const char *text, char **channels)
{
GSList *tmp;
char **chan;
g_return_val_if_fail(text != NULL, NULL);
for (tmp = hilights; tmp != NULL; tmp = tmp->next) {
HILIGHT_REC *rec = tmp->data;
if (g_strcasecmp(rec->text, text) != 0)
continue;
if ((channels == NULL && rec->channels == NULL))
return rec; /* no channels - ok */
if (channels != NULL && strcmp(*channels, "*") == 0)
return rec; /* ignore channels */
if (channels == NULL || rec->channels == NULL)
continue; /* other doesn't have channels */
if (strarray_length(channels) != strarray_length(rec->channels))
continue; /* different amount of channels */
/* check that channels match */
for (chan = channels; *chan != NULL; chan++) {
if (strarray_find(rec->channels, *chan) == -1)
break;
}
if (*chan == NULL)
return rec; /* channels ok */
}
return NULL;
}
static void sig_print_text(SERVER_REC *server, const char *channel, gpointer level, const char *str)
{
if (hilight_next) {
hilight_next = FALSE;
signal_stop();
}
}
static void sig_print_text_stripped(SERVER_REC *server, const char *channel, gpointer plevel, const char *str)
{
GSList *tmp;
char *color, *newstr;
int len, level, best_match;
g_return_if_fail(str != NULL);
level = GPOINTER_TO_INT(plevel);
if (level & (MSGLEVEL_NOHILIGHT|MSGLEVEL_HILIGHT)) return;
color = NULL; best_match = 0;
for (tmp = hilights; tmp != NULL; tmp = tmp->next) {
HILIGHT_REC *rec = tmp->data;
if (rec->nickmask)
continue;
if ((level & (rec->level > 0 ? rec->level : DEFAULT_HILIGHT_CHECK_LEVEL)) == 0)
continue;
if (rec->channels != NULL && !strarray_find(rec->channels, channel))
continue;
if (rec->regexp) {
if (!regexp_match(str, rec->text))
continue;
} else if (rec->fullword) {
if (stristr_full(str, rec->text) == NULL)
continue;
} else {
if (stristr(str, rec->text) == NULL)
continue;
}
len = strlen(rec->text);
if (best_match < len) {
best_match = len;
color = rec->color;
}
}
if (best_match > 0) {
hilight_next = FALSE;
if (color == NULL) color = "\00316";
newstr = g_strconcat(isdigit(*color) ? "\003" : "", color, str, NULL);
signal_emit("print text", 4, server, channel, GINT_TO_POINTER(level | MSGLEVEL_HILIGHT), newstr);
g_free(newstr);
hilight_next = TRUE;
}
}
static void read_hilight_config(void)
{
CONFIG_NODE *node;
HILIGHT_REC *rec;
GSList *tmp;
char *text, *color;
hilights_destroy_all();
node = iconfig_node_traverse("hilights", FALSE);
if (node == NULL) return;
for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
node = tmp->data;
if (node->type != NODE_TYPE_BLOCK)
continue;
text = config_node_get_str(node, "text", NULL);
if (text == NULL || *text == '\0')
continue;
rec = g_new0(HILIGHT_REC, 1);
hilights = g_slist_append(hilights, rec);
color = config_node_get_str(node, "color", NULL);
rec->text = g_strdup(text);
rec->color = color == NULL || *color == '\0' ? NULL :
g_strdup(color);
rec->level = config_node_get_int(node, "level", 0);
rec->nickmask = config_node_get_bool(node, "nickmask", FALSE);
rec->fullword = config_node_get_bool(node, "fullword", FALSE);
rec->regexp = config_node_get_bool(node, "regexp", FALSE);
node = config_node_section(node, "channels", -1);
if (node != NULL) rec->channels = config_node_get_list(node);
}
}
static void hilight_print(int index, HILIGHT_REC *rec)
{
char *chans, *levelstr;
chans = rec->channels == NULL ? NULL :
g_strjoinv(",", rec->channels);
levelstr = rec->level == 0 ? NULL :
bits2level(rec->level);
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
IRCTXT_HILIGHT_LINE, index, rec->text,
chans != NULL ? chans : "",
levelstr != NULL ? levelstr : "",
rec->nickmask ? " -nick" : "",
rec->fullword ? " -word" : "",
rec->regexp ? " -regexp" : "");
g_free_not_null(chans);
g_free_not_null(levelstr);
}
static void cmd_hilight_show(void)
{
GSList *tmp;
int index;
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_HILIGHT_HEADER);
index = 1;
for (tmp = hilights; tmp != NULL; tmp = tmp->next, index++) {
HILIGHT_REC *rec = tmp->data;
hilight_print(index, rec);
}
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_HILIGHT_FOOTER);
}
static void cmd_hilight(const char *data)
{
/* /HILIGHT [-nick | -regexp | -word] [-color <color>] [-level <level>] [-channels <channels>] <text> */
char *params, *args, *colorarg, *levelarg, *chanarg, *text;
char **channels;
HILIGHT_REC *rec;
g_return_if_fail(data != NULL);
if (*data == '\0') {
cmd_hilight_show();
return;
}
args = "color level channels";
params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST,
&args, &colorarg, &levelarg, &chanarg, &text);
if (*text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
channels = *chanarg == '\0' ? NULL :
g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1);
rec = hilight_find(text, channels);
if (rec == NULL) {
rec = g_new0(HILIGHT_REC, 1);
rec->text = g_strdup(text);
rec->channels = channels;
} else {
g_free_and_null(rec->color);
g_strfreev(channels);
hilight_remove_config(rec);
hilights = g_slist_remove(hilights, rec);
}
hilights = g_slist_append(hilights, rec);
rec->nickmask = stristr(args, "-nick") != NULL;
rec->fullword = stristr(args, "-word") != NULL;
rec->regexp = stristr(args, "-regexp") != NULL;
rec->level = level2bits(replace_chars(levelarg, ',', ' '));
if (*colorarg != '\0') rec->color = g_strdup(colorarg);
hilight_print(g_slist_index(hilights, rec)+1, rec);
hilight_add_config(rec);
g_free(params);
}
static void cmd_dehilight(const char *data)
{
HILIGHT_REC *rec;
GSList *tmp;
if (is_numeric(data, ' ')) {
/* with index number */
tmp = g_slist_nth(hilights, atol(data)-1);
rec = tmp == NULL ? NULL : tmp->data;
} else {
/* with mask */
char *chans[2] = { "*", NULL };
rec = hilight_find(data, chans);
}
if (rec == NULL)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_HILIGHT_NOT_FOUND, data);
else
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_HILIGHT_REMOVED, rec->text);
hilight_remove(rec);
}
void hilight_text_init(void)
{
hilight_next = FALSE;
read_hilight_config();
signal_add_first("print text", (SIGNAL_FUNC) sig_print_text);
signal_add_first("print text stripped", (SIGNAL_FUNC) sig_print_text_stripped);
signal_add("setup reread", (SIGNAL_FUNC) read_hilight_config);
command_bind("hilight", NULL, (SIGNAL_FUNC) cmd_hilight);
command_bind("dehilight", NULL, (SIGNAL_FUNC) cmd_dehilight);
}
void hilight_text_deinit(void)
{
hilights_destroy_all();
signal_remove("print text", (SIGNAL_FUNC) sig_print_text);
signal_remove("print text stripped", (SIGNAL_FUNC) sig_print_text_stripped);
signal_remove("setup reread", (SIGNAL_FUNC) read_hilight_config);
command_unbind("hilight", (SIGNAL_FUNC) cmd_hilight);
command_unbind("dehilight", (SIGNAL_FUNC) cmd_dehilight);
}

View file

@ -0,0 +1,22 @@
#ifndef __HILIGHT_TEXT_H
#define __HILIGHT_TEXT_H
typedef struct {
char *text;
char **channels; /* if non-NULL, check the text only from these channels */
int level; /* match only messages with this level, 0=default */
char *color; /* if starts with number, \003 is automatically
inserted before it. */
int nickmask:1; /* `text 'is a nick mask - colorify the nick */
int fullword:1; /* match `text' only for full words */
int regexp:1; /* `text' is a regular expression */
} HILIGHT_REC;
extern GSList *hilights;
void hilight_text_init(void);
void hilight_text_deinit(void);
#endif

View file

@ -0,0 +1,297 @@
/*
keyboard.c : irssi
Copyright (C) 1999 Timo Sirainen
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 "module.h"
#include "signals.h"
#include "lib-config/iconfig.h"
#include "settings.h"
#include "keyboard.h"
#include "windows.h"
GSList *keyinfos;
static GHashTable *keys;
KEYINFO_REC *key_info_find(gchar *id)
{
GSList *tmp;
for (tmp = keyinfos; tmp != NULL; tmp = tmp->next)
{
KEYINFO_REC *rec = tmp->data;
if (g_strcasecmp(rec->id, id) == 0)
return rec;
}
return NULL;
}
/* Bind a key for function */
void key_bind(gchar *id, gchar *data, gchar *description, gchar *key_default, SIGNAL_FUNC func)
{
KEYINFO_REC *info;
KEY_REC *rec;
g_return_if_fail(id != NULL);
g_return_if_fail(func != NULL);
/* create key info record */
info = key_info_find(id);
if (info == NULL)
{
g_return_if_fail(description != NULL);
info = g_new0(KEYINFO_REC, 1);
info->id = g_strdup(id);
info->description = g_strdup(description);
keyinfos = g_slist_append(keyinfos, info);
/* add the signal */
id = g_strconcat("key ", id, NULL);
signal_add(id, func);
g_free(id);
signal_emit("keyinfo created", 1, info);
}
if (key_default == NULL || *key_default == '\0')
{
/* just create a possible key command, don't bind it to any key yet */
return;
}
/* create/replace key record */
rec = g_hash_table_lookup(keys, key_default);
if (rec != NULL)
{
if (rec->data != NULL)
g_free(rec->data);
}
else
{
rec = g_new0(KEY_REC, 1);
info->keys = g_slist_append(info->keys, rec);
rec->key = g_strdup(key_default);
g_hash_table_insert(keys, rec->key, rec);
}
rec->info = info;
rec->data = data == NULL ? NULL : g_strdup(data);
}
static void keyinfo_remove(KEYINFO_REC *info)
{
GSList *tmp;
g_return_if_fail(info != NULL);
keyinfos = g_slist_remove(keyinfos, info);
signal_emit("keyinfo destroyed", 1, info);
/* destroy all keys */
for (tmp = info->keys; tmp != NULL; tmp = tmp->next)
{
KEY_REC *rec = tmp->data;
g_hash_table_remove(keys, rec->key);
if (rec->data != NULL) g_free(rec->data);
g_free(rec->key);
g_free(rec);
}
/* destroy key info */
g_slist_free(info->keys);
g_free(info->description);
g_free(info->id);
g_free(info);
}
/* Unbind key */
void key_unbind(gchar *id, SIGNAL_FUNC func)
{
KEYINFO_REC *info;
g_return_if_fail(id != NULL);
g_return_if_fail(func != NULL);
/* remove keys */
info = key_info_find(id);
if (info != NULL)
keyinfo_remove(info);
/* remove signal */
id = g_strconcat("key ", id, NULL);
signal_remove(id, func);
g_free(id);
}
/* Configure new key */
void key_configure_add(gchar *id, gchar *data, gchar *key)
{
KEYINFO_REC *info;
KEY_REC *rec;
g_return_if_fail(id != NULL);
g_return_if_fail(key != NULL && *key != '\0');
info = key_info_find(id);
if (info == NULL)
return;
rec = g_new0(KEY_REC, 1);
info->keys = g_slist_append(info->keys, rec);
rec->info = info;
rec->data = data == NULL ? NULL : g_strdup(data);
rec->key = g_strdup(key);
g_hash_table_insert(keys, rec->key, rec);
}
/* Remove key */
void key_configure_remove(gchar *key)
{
KEY_REC *rec;
g_return_if_fail(key != NULL);
rec = g_hash_table_lookup(keys, key);
if (rec == NULL) return;
rec->info->keys = g_slist_remove(rec->info->keys, rec);
g_hash_table_remove(keys, key);
if (rec->data != NULL) g_free(rec->data);
g_free(rec->key);
g_free(rec);
}
gboolean key_pressed(gchar *key, gpointer data)
{
KEY_REC *rec;
gboolean ret;
gchar *str;
g_return_val_if_fail(key != NULL, FALSE);
rec = g_hash_table_lookup(keys, key);
if (rec == NULL) return FALSE;
str = g_strconcat("key ", rec->info->id, NULL);
ret = signal_emit(str, 3, rec->data, data, rec->info);
g_free(str);
return ret;
}
void keyboard_save(void)
{
CONFIG_NODE *keyboard, *node, *listnode;
GSList *tmp, *tmp2;
/* remove old keyboard settings */
config_node_set_str(NULL, "(keyboard", NULL);
keyboard = iconfig_node_traverse("(keyboard", TRUE);
for (tmp = keyinfos; tmp != NULL; tmp = tmp->next) {
KEYINFO_REC *info = tmp->data;
node = config_node_section(keyboard, info->id, TRUE);
for (tmp2 = info->keys; tmp2 != NULL; tmp2 = tmp2->next) {
KEY_REC *key = tmp2->data;
listnode = config_node_section(node, NULL, NODE_TYPE_BLOCK);
if (key->data != NULL)
config_node_set_str(listnode, "data", key->data);
config_node_set_str(listnode, "key", key->key);
}
}
}
static void sig_command(gchar *data)
{
signal_emit("send command", 3, data, active_win->active_server, active_win->active);
}
void read_keyinfo(KEYINFO_REC *info, CONFIG_NODE *node)
{
GSList *tmp;
char *data, *key;
g_return_if_fail(info != NULL);
g_return_if_fail(node != NULL);
g_return_if_fail(is_node_list(node));
/* remove all old keys */
while (info->keys != NULL)
key_configure_remove(((KEY_REC *) info->keys->data)->key);
/* add the new keys */
for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
node = tmp->data;
data = config_node_get_str(node->value, "data", NULL);
key = config_node_get_str(node->value, "key", NULL);
if (key != NULL) key_configure_add(info->id, data, key);
}
}
static void read_keyboard_config(void)
{
KEYINFO_REC *info;
CONFIG_NODE *node;
GSList *tmp;
while (keyinfos != NULL)
keyinfo_remove(keyinfos->data);
if (keys != NULL) g_hash_table_destroy(keys);
keys = g_hash_table_new((GHashFunc) g_str_hash, (GCompareFunc) g_str_equal);
node = iconfig_node_traverse("keyboard", FALSE);
if (node == NULL) return;
for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
node = tmp->data;
if (node->key == NULL || node->value == NULL)
continue;
info = key_info_find(node->key);
if (info != NULL) read_keyinfo(info, node->value);
}
}
void keyboard_init(void)
{
keyinfos = NULL; keys = NULL;
key_bind("command", NULL, "Run any IRC command", NULL, (SIGNAL_FUNC) sig_command);
read_keyboard_config();
signal_add("setup reread", (SIGNAL_FUNC) read_keyboard_config);
}
void keyboard_deinit(void)
{
while (keyinfos != NULL)
keyinfo_remove(keyinfos->data);
g_hash_table_destroy(keys);
signal_remove("setup reread", (SIGNAL_FUNC) read_keyboard_config);
}

View file

@ -0,0 +1,40 @@
#ifndef __KEYBOARD_H
#define __KEYBOARD_H
#include "signals.h"
typedef struct
{
char *id;
char *description;
GSList *keys;
}
KEYINFO_REC;
typedef struct
{
KEYINFO_REC *info;
char *key;
void *data;
}
KEY_REC;
extern GSList *keyinfos;
void key_bind(gchar *id, gchar *data, gchar *description, gchar *key_default, SIGNAL_FUNC func);
void key_unbind(gchar *id, SIGNAL_FUNC func);
void key_configure_add(gchar *id, gchar *data, gchar *key);
void key_configure_remove(gchar *key);
KEYINFO_REC *key_info_find(gchar *id);
gboolean key_pressed(gchar *key, gpointer data);
void keyboard_save(void);
void keyboard_init(void);
void keyboard_deinit(void);
#endif

View file

@ -0,0 +1,87 @@
/*
module-formats.c : irssi
Copyright (C) 2000 Timo Sirainen
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 "module.h"
#include "printtext.h"
FORMAT_REC fecommon_core_formats[] =
{
{ MODULE_NAME, N_("Core"), 0 },
/* ---- */
{ NULL, N_("Windows"), 0 },
{ "line_start", N_("%B-%W!%B-%n "), 0 },
{ "line_start_irssi", N_("%B-%W!%B- %WIrssi:%n "), 0 },
{ "timestamp", N_("[$[-2.0]3:$[-2.0]4] "), 6, { 1, 1, 1, 1, 1, 1 } },
{ "daychange", N_("Day changed to $[-2.0]1-$[-2.0]0 $2"), 3, { 1, 1, 1 } },
{ "talking_with", N_("You are now talking with %_$0%_"), 1, { 0 } },
/* ---- */
{ NULL, N_("Server"), 0 },
{ "looking_up", N_("Looking up %_$0%_"), 1, { 0 } },
{ "connecting", N_("Connecting to %_$0%_ %K[%n$1%K]%n port %_$2%_"), 3, { 0, 0, 1 } },
{ "connection_established", N_("Connection to %_$0%_ established"), 1, { 0 } },
{ "cant_connect", N_("Unable to connect server %_$0%_ port %_$1%_ %K[%n$2%K]"), 3, { 0, 1, 0 } },
{ "connection_lost", N_("Connection lost to %_$0%_"), 1, { 0 } },
{ "server_changed", N_("Changed to %_$2%_ server %_$1%_"), 3, { 0, 0, 0 } },
{ "unknown_server_tag", N_("Unknown server tag %_$0%_"), 1, { 0 } },
/* ---- */
{ NULL, N_("Highlighting"), 0 },
{ "hilight_header", N_("Highlights:"), 0 },
{ "hilight_line", N_("$[-4]0 $1 $2 $3$3$4$5"), 7, { 1, 0, 0, 0, 0, 0, 0 } },
{ "hilight_footer", "", 0 },
{ "hilight_not_found", N_("Highlight not found: $0"), 1, { 0 } },
{ "hilight_removed", N_("Highlight removed: $0"), 1, { 0 } },
/* ---- */
{ NULL, N_("Aliases"), 0 },
{ "alias_added", N_("Alias $0 added"), 1, { 0 } },
{ "alias_removed", N_("Alias $0 removed"), 1, { 0 } },
{ "alias_not_found", N_("No such alias: $0"), 1, { 0 } },
{ "aliaslist_header", N_("Aliases:"), 0 },
{ "aliaslist_line", N_("$[10]0 $1"), 2, { 0, 0 } },
{ "aliaslist_footer", "", 0 },
/* ---- */
{ NULL, N_("Logging"), 0 },
{ "log_opened", N_("Log file %W$0%n opened"), 1, { 0 } },
{ "log_closed", N_("Log file %W$0%n closed"), 1, { 0 } },
{ "log_create_failed", N_("Couldn't create log file %W$0"), 1, { 0 } },
{ "log_locked", N_("Log file %W$0%n is locked, probably by another running Irssi"), 1, { 0 } },
{ "log_not_open", N_("Log file %W$0%n not open"), 1, { 0 } },
{ "log_started", N_("Started logging to file %W$0"), 1, { 0 } },
{ "log_stopped", N_("Stopped logging to file %W$0"), 1, { 0 } },
{ "log_list_header", N_("Logs:"), 0 },
{ "log_list", N_("$0: $1 $2$3$4"), 5, { 0, 0, 0, 0, 0 } },
{ "log_list_footer", N_(""), 0 },
{ "windowlog_file", N_("Window LOGFILE set to $0"), 1, { 0 } },
{ "windowlog_file_logging", N_("Can't change window's logfile while log is on"), 0 },
/* ---- */
{ NULL, N_("Misc"), 0 },
{ "not_toggle", N_("Value must be either ON, OFF or TOGGLE"), 0 }
};

View file

@ -0,0 +1,62 @@
#include "printtext.h"
enum {
IRCTXT_MODULE_NAME,
IRCTXT_FILL_1,
IRCTXT_LINE_START,
IRCTXT_LINE_START_IRSSI,
IRCTXT_TIMESTAMP,
IRCTXT_DAYCHANGE,
IRCTXT_TALKING_WITH,
IRCTXT_FILL_2,
IRCTXT_LOOKING_UP,
IRCTXT_CONNECTING,
IRCTXT_CONNECTION_ESTABLISHED,
IRCTXT_CANT_CONNECT,
IRCTXT_CONNECTION_LOST,
IRCTXT_SERVER_CHANGED,
IRCTXT_UNKNOWN_SERVER_TAG,
IRCTXT_FILL_3,
IRCTXT_HILIGHT_HEADER,
IRCTXT_HILIGHT_LINE,
IRCTXT_HILIGHT_FOOTER,
IRCTXT_HILIGHT_NOT_FOUND,
IRCTXT_HILIGHT_REMOVED,
IRCTXT_FILL_4,
IRCTXT_ALIAS_ADDED,
IRCTXT_ALIAS_REMOVED,
IRCTXT_ALIAS_NOT_FOUND,
IRCTXT_ALIASLIST_HEADER,
IRCTXT_ALIASLIST_LINE,
IRCTXT_ALIASLIST_FOOTER,
IRCTXT_FILL_5,
IRCTXT_LOG_OPENED,
IRCTXT_LOG_CLOSED,
IRCTXT_LOG_CREATE_FAILED,
IRCTXT_LOG_LOCKED,
IRCTXT_LOG_NOT_OPEN,
IRCTXT_LOG_STARTED,
IRCTXT_LOG_STOPPED,
IRCTXT_LOG_LIST_HEADER,
IRCTXT_LOG_LIST,
IRCTXT_LOG_LIST_FOOTER,
IRCTXT_WINDOWLOG_FILE,
IRCTXT_WINDOWLOG_FILE_LOGGING,
IRCTXT_FILL_6,
IRCTXT_NOT_TOGGLE
};
extern FORMAT_REC fecommon_core_formats[];
#define MODULE_FORMATS fecommon_core_formats

View file

@ -0,0 +1,3 @@
#include "common.h"
#define MODULE_NAME "fe-common/core"

View file

@ -0,0 +1,115 @@
/*
nick-hilight.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "signals.h"
#include "levels.h"
#include "server.h"
#include "windows.h"
#include "window-items.h"
static void sig_hilight_text(SERVER_REC *server, const char *channel, gpointer levelptr, const char *msg)
{
WINDOW_REC *window;
int level, oldlevel;
level = GPOINTER_TO_INT(levelptr);
window = window_find_closest(server, channel, level);
if (window == active_win || (level & (MSGLEVEL_NEVER|MSGLEVEL_NO_ACT|MSGLEVEL_MSGS)))
return;
oldlevel = window->new_data;
if (window->new_data < NEWDATA_TEXT) {
window->new_data = NEWDATA_TEXT;
signal_emit("window hilight", 1, window);
}
signal_emit("window activity", 2, window, GINT_TO_POINTER(oldlevel));
}
static void sig_dehilight(WINDOW_REC *window, WI_ITEM_REC *item)
{
g_return_if_fail(window != NULL);
if (item != NULL && item->new_data != 0) {
item->new_data = 0;
signal_emit("window item hilight", 1, item);
}
}
static void sig_dehilight_window(WINDOW_REC *window)
{
int oldlevel;
g_return_if_fail(window != NULL);
if (window->new_data == 0)
return;
if (window->new_data != 0) {
oldlevel = window->new_data;
window->new_data = 0;
signal_emit("window hilight", 2, window, GINT_TO_POINTER(oldlevel));
}
signal_emit("window activity", 2, window, GINT_TO_POINTER(oldlevel));
g_slist_foreach(window->items, (GFunc) sig_dehilight, NULL);
}
static void sig_hilight_window_item(WI_ITEM_REC *item)
{
WINDOW_REC *window;
GSList *tmp;
int level, oldlevel;
window = window_item_window(item); level = 0;
for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
item = tmp->data;
if (item->new_data > level)
level = item->new_data;
}
oldlevel = window->new_data;
if (window->new_data < level || level == 0) {
window->new_data = level;
signal_emit("window hilight", 2, window, GINT_TO_POINTER(oldlevel));
}
signal_emit("window activity", 2, window, GINT_TO_POINTER(oldlevel));
}
void nick_hilight_init(void)
{
signal_add("print text", (SIGNAL_FUNC) sig_hilight_text);
signal_add("window item changed", (SIGNAL_FUNC) sig_dehilight);
signal_add("window changed", (SIGNAL_FUNC) sig_dehilight_window);
signal_add("window dehilight", (SIGNAL_FUNC) sig_dehilight_window);
signal_add("window item hilight", (SIGNAL_FUNC) sig_hilight_window_item);
}
void nick_hilight_deinit(void)
{
signal_remove("print text", (SIGNAL_FUNC) sig_hilight_text);
signal_remove("window item changed", (SIGNAL_FUNC) sig_dehilight);
signal_remove("window changed", (SIGNAL_FUNC) sig_dehilight_window);
signal_remove("window dehilight", (SIGNAL_FUNC) sig_dehilight_window);
signal_remove("window item hilight", (SIGNAL_FUNC) sig_hilight_window_item);
}

View file

@ -0,0 +1,858 @@
/*
printtext.c : irssi
Copyright (C) 1999 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "modules.h"
#include "signals.h"
#include "commands.h"
#include "special-vars.h"
#include "settings.h"
#include "levels.h"
#include "server.h"
#include "translation.h"
#include "themes.h"
#include "windows.h"
static gboolean toggle_show_timestamps, toggle_show_msgs_timestamps, toggle_hide_text_style;
static gint printtag;
static gchar ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
static gint signal_gui_print_text;
static gint signal_print_text_stripped;
static gint signal_print_text;
static gint signal_print_text_finished;
void printbeep(void)
{
signal_emit_id(signal_gui_print_text, 6, active_win, NULL, NULL,
GINT_TO_POINTER(PRINTFLAG_BEEP), "", MSGLEVEL_NEVER);
}
/* parse ANSI color string */
static char *convert_ansi(char *str, int *fgcolor, int *bgcolor, int *flags)
{
gchar *start;
gint fg, bg, fl, num;
if (*str != '[') return str;
start = str;
fg = *fgcolor < 0 ? current_theme->default_color : *fgcolor;
bg = *bgcolor < 0 ? -1 : *bgcolor;
fl = *flags;
str++; num = 0;
for (;; str++)
{
if (*str == '\0') return start;
if (isdigit((gint) *str))
{
num = num*10 + (*str-'0');
continue;
}
if (*str != ';' && *str != 'm') return start;
switch (num)
{
case 0:
/* reset colors back to default */
fg = current_theme->default_color;
bg = -1;
break;
case 1:
/* hilight */
fg |= 8;
break;
case 5:
/* blink */
bg = bg == -1 ? 8 : bg | 8;
break;
case 7:
/* reverse */
fl |= PRINTFLAG_REVERSE;
break;
default:
if (num >= 30 && num <= 37)
fg = (fg & 0xf8) + ansitab[num-30];
if (num >= 40 && num <= 47)
{
if (bg == -1) bg = 0;
bg = (bg & 0xf8) + ansitab[num-40];
}
break;
}
num = 0;
if (*str == 'm')
{
if (!toggle_hide_text_style)
{
*fgcolor = fg;
*bgcolor = bg == -1 ? -1 : bg;
*flags = fl;
}
str++;
break;
}
}
return str;
}
#define IN_COLOR_CODE 2
#define IN_SECOND_CODE 4
char *strip_codes(const char *input)
{
const char *p;
gchar *str, *out;
gint loop_state;
loop_state = 0;
out = str = g_strdup(input);
for (p = input; *p != '\0'; p++) /* Going through the string till the end k? */
{
if (*p == '\003')
{
if (p[1] < 17 && p[1] > 0)
{
p++;
if (p[1] < 17 && p[1] > 0) p++;
continue;
}
loop_state = IN_COLOR_CODE;
continue;
}
if (loop_state & IN_COLOR_CODE)
{
if (isdigit( (gint) *p )) continue;
if (*p != ',' || (loop_state & IN_SECOND_CODE))
{
/* we're no longer in a color code */
*out++ = *p;
loop_state &= ~IN_COLOR_CODE|IN_SECOND_CODE;
continue;
}
/* we're in the second code */
loop_state |= IN_SECOND_CODE;
continue;
}
/* we're not in a color code that means we should add the character */
if (*p == 4 && p[1] != '\0' && p[2] != '\0')
{
p += 2;
continue;
}
if (*p == 2 || *p == 22 || *p == 27 || *p == 31 || *p == 15)
continue;
*out++ = *p;
}
*out = '\0';
return str;
}
static gboolean expand_styles(GString *out, char format, void *server, const char *channel, int level)
{
static const char *backs = "01234567";
static const char *fores = "krgybmcw";
static const char *boldfores = "KRGYBMCW";
gchar *p;
/* p/P -> m/M */
if (format == 'p')
format = 'm';
else if (format == 'P')
format = 'M';
switch (format)
{
case 'U':
/* Underline on/off */
g_string_append_c(out, 4);
g_string_append_c(out, -1);
g_string_append_c(out, 2);
break;
case '9':
case '_':
/* bold on/off */
g_string_append_c(out, 4);
g_string_append_c(out, -1);
g_string_append_c(out, 1);
break;
case '8':
/* reverse */
g_string_append_c(out, 4);
g_string_append_c(out, -1);
g_string_append_c(out, 3);
break;
case '%':
g_string_append_c(out, '%');
break;
case ':':
/* Newline */
printtext(server, channel, level, out->str);
g_string_truncate(out, 0);
break;
case '|':
/* Indent here mark */
g_string_append_c(out, 4);
g_string_append_c(out, -1);
g_string_append_c(out, 4);
break;
case 'F':
/* flashing - ignore */
break;
case 'N':
/* don't put clear-color tag at the end of the output - ignore */
break;
case 'n':
/* default color */
g_string_append_c(out, 4);
g_string_append_c(out, -1);
g_string_append_c(out, -1);
break;
default:
/* check if it's a background color */
p = strchr(backs, format);
if (p != NULL)
{
g_string_append_c(out, 4);
g_string_append_c(out, -2);
g_string_append_c(out, ansitab[(gint) (p-backs)]+1);
break;
}
/* check if it's a foreground color */
p = strchr(fores, format);
if (p != NULL)
{
g_string_append_c(out, 4);
g_string_append_c(out, ansitab[(gint) (p-fores)]+1);
g_string_append_c(out, -2);
break;
}
/* check if it's a bold foreground color */
p = strchr(boldfores, format);
if (p != NULL)
{
g_string_append_c(out, 4);
g_string_append_c(out, 8+ansitab[(gint) (p-boldfores)]+1);
g_string_append_c(out, -2);
break;
}
return FALSE;
}
return TRUE;
}
static void read_arglist(va_list va, FORMAT_REC *format,
char **arglist, int arglist_size,
char *buffer, int buffer_size)
{
int num, len, bufpos;
bufpos = 0;
for (num = 0; num < format->params && num < arglist_size; num++) {
switch (format->paramtypes[num]) {
case FORMAT_STRING:
arglist[num] = (char *) va_arg(va, char *);
if (arglist[num] == NULL) {
g_warning("output_format_text_args() : parameter %d is NULL", num);
arglist[num] = "";
}
break;
case FORMAT_INT: {
int d = (int) va_arg(va, int);
if (bufpos >= buffer_size) {
arglist[num] = "";
break;
}
arglist[num] = buffer+bufpos;
len = g_snprintf(buffer+bufpos, buffer_size-bufpos,
"%d", d);
bufpos += len+1;
break;
}
case FORMAT_LONG: {
long l = (long) va_arg(va, long);
if (bufpos >= buffer_size) {
arglist[num] = "";
break;
}
arglist[num] = buffer+bufpos;
len = g_snprintf(buffer+bufpos, buffer_size-bufpos,
"%ld", l);
bufpos += len+1;
break;
}
case FORMAT_FLOAT: {
double f = (double) va_arg(va, double);
if (bufpos >= buffer_size) {
arglist[num] = "";
break;
}
arglist[num] = buffer+bufpos;
len = g_snprintf(buffer+bufpos, buffer_size-bufpos,
"%0.2f", f);
bufpos += len+1;
break;
}
}
}
}
static void output_format_text_args(GString *out, void *server, const char *channel, int level, FORMAT_REC *format, const char *text, va_list args)
{
char *arglist[10];
char buffer[200]; /* should be enough? (won't overflow even if it isn't) */
const char *str;
char code;
int need_free;
str = current_theme != NULL && text != NULL ? text : format->def;
/* read all optional arguments to arglist[] list
so they can be used in any order.. */
read_arglist(args, format,
arglist, sizeof(arglist)/sizeof(void*),
buffer, sizeof(buffer));
code = 0;
while (*str != '\0') {
if (code == '%') {
/* color code */
if (!expand_styles(out, *str, server, channel, level)) {
g_string_append_c(out, '%');
g_string_append_c(out, '%');
g_string_append_c(out, *str);
}
code = 0;
} else if (code == '$') {
/* argument */
char *ret;
ret = parse_special((char **) &str, active_win->active_server, active_win->active, arglist, &need_free, NULL);
if (ret != NULL) {
g_string_append(out, ret);
if (need_free) g_free(ret);
}
code = 0;
} else {
if (*str == '%' || *str == '$')
code = *str;
else
g_string_append_c(out, *str);
}
str++;
}
}
static void output_format_text(GString *out, void *server, const char *channel, int level, int formatnum, ...)
{
MODULE_THEME_REC *theme;
va_list args;
theme = g_hash_table_lookup(current_theme->modules, MODULE_FORMATS->tag);
va_start(args, formatnum);
output_format_text_args(out, server, channel, level,
&MODULE_FORMATS[formatnum],
theme == NULL ? NULL : theme->format[formatnum], args);
va_end(args);
}
static void add_timestamp(WINDOW_REC *window, GString *out, void *server, const char *channel, int level)
{
time_t t;
struct tm *tm;
GString *tmp;
if (!(level != MSGLEVEL_NEVER && (toggle_show_timestamps || (toggle_show_msgs_timestamps && (level & MSGLEVEL_MSGS) != 0))))
return;
t = time(NULL);
if ((t - window->last_timestamp) < settings_get_int("timestamp_timeout")) {
window->last_timestamp = t;
return;
}
window->last_timestamp = t;
tmp = g_string_new(NULL);
tm = localtime(&t);
output_format_text(tmp, server, channel, level, IRCTXT_TIMESTAMP,
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
/* insert the timestamp right after \n */
g_string_prepend(out, tmp->str);
g_string_free(tmp, TRUE);
}
static void new_line_stuff(GString *out, void *server, const char *channel, int level)
{
if ((level & (MSGLEVEL_CLIENTERROR|MSGLEVEL_CLIENTNOTICE)) != 0)
output_format_text(out, server, channel, level, IRCTXT_LINE_START_IRSSI);
else if ((level & (MSGLEVEL_MSGS|MSGLEVEL_PUBLIC|MSGLEVEL_NOTICES|MSGLEVEL_SNOTES|MSGLEVEL_CTCPS|MSGLEVEL_ACTIONS|MSGLEVEL_DCC|MSGLEVEL_CLIENTCRAP)) == 0 && level != MSGLEVEL_NEVER)
output_format_text(out, server, channel, level, IRCTXT_LINE_START);
}
/* Write text to channel - convert color codes */
void printtext(void *server, const char *channel, int level, const char *str, ...)
{
va_list args;
GString *out;
gchar *tmpstr;
gint pros;
g_return_if_fail(str != NULL);
va_start(args, str);
pros = 0;
out = g_string_new(NULL);
new_line_stuff(out, server, channel, level);
for (; *str != '\0'; str++)
{
if (*str != '%')
{
g_string_append_c(out, *str);
continue;
}
if (*++str == '\0') break;
switch (*str)
{
/* standard parameters */
case 's':
{
gchar *s = (gchar *) va_arg(args, gchar *);
if (s && *s) g_string_append(out, s);
break;
}
case 'd':
{
gint d = (gint) va_arg(args, gint);
g_string_sprintfa(out, "%d", d);
break;
}
case 'f':
{
gdouble f = (gdouble) va_arg(args, gdouble);
g_string_sprintfa(out, "%0.2f", f);
break;
}
case 'u':
{
guint d = (guint) va_arg(args, guint);
g_string_sprintfa(out, "%u", d);
break;
}
case 'l':
{
gulong d = (gulong) va_arg(args, gulong);
if (*++str != 'd' && *str != 'u')
{
g_string_sprintfa(out, "%ld", d);
str--;
}
else
{
if (*str == 'd')
g_string_sprintfa(out, "%ld", d);
else
g_string_sprintfa(out, "%lu", d);
}
break;
}
default:
if (!expand_styles(out, *str, server, channel, level))
{
g_string_append_c(out, '%');
g_string_append_c(out, *str);
}
break;
}
}
va_end(args);
/* send the plain text version for logging.. */
tmpstr = strip_codes(out->str);
signal_emit_id(signal_print_text_stripped, 4, server, channel, GINT_TO_POINTER(level), tmpstr);
g_free(tmpstr);
signal_emit_id(signal_print_text, 4, server, channel, GINT_TO_POINTER(level), out->str);
g_string_free(out, TRUE);
}
void printformat_format(FORMAT_REC *formats, void *server, const char *channel, int level, int formatnum, ...)
{
MODULE_THEME_REC *theme;
GString *out;
va_list args;
va_start(args, formatnum);
out = g_string_new(NULL);
theme = g_hash_table_lookup(current_theme->modules, formats->tag);
output_format_text_args(out, server, channel, level,
&formats[formatnum],
theme == NULL ? NULL : theme->format[formatnum], args);
if (out->len > 0) printtext(server, channel, level, "%s", out->str);
g_string_free(out, TRUE);
va_end(args);
}
static void newline(WINDOW_REC *window)
{
window->lines++;
if (window->lines != 1) {
signal_emit_id(signal_gui_print_text, 6, window,
GINT_TO_POINTER(-1), GINT_TO_POINTER(-1),
GINT_TO_POINTER(0), "\n", GINT_TO_POINTER(-1));
}
}
static void sig_print_text(void *server, const char *target, gpointer level, const char *text)
{
WINDOW_REC *window;
GString *out;
gchar *dup, *ptr, type, *str;
gint fgcolor, bgcolor;
gint flags;
g_return_if_fail(text != NULL);
window = window_find_closest(server, target, GPOINTER_TO_INT(level));
g_return_if_fail(window != NULL);
flags = 0; fgcolor = -1; bgcolor = -1; type = '\0';
newline(window);
out = g_string_new(text);
if (server != NULL && servers != NULL && servers->next != NULL &&
(window->active == NULL || window->active->server != server))
{
/* connected to more than one server and active server isn't the
same where the message came or we're in status/msgs/empty window -
prefix with a [server tag] */
gchar *str;
str = g_strdup_printf("[%s] ", ((SERVER_REC *) server)->tag);
g_string_prepend(out, str);
g_free(str);
}
add_timestamp(window, out, server, target, GPOINTER_TO_INT(level));
dup = str = out->str;
g_string_free(out, FALSE);
while (*str != '\0')
{
for (ptr = str; *ptr != '\0'; ptr++)
{
if (*ptr == 2 || *ptr == 3 || *ptr == 4 || *ptr == 6 || *ptr == 7 || *ptr == 15 || *ptr == 22 || *ptr == 27 || *ptr == 31)
{
type = *ptr;
*ptr++ = '\0';
break;
}
*ptr = (gchar) translation_in[(gint) (guchar) *ptr];
}
if (type == 7)
{
/* bell */
if (settings_get_bool("toggle_bell_beeps"))
flags |= PRINTFLAG_BEEP;
}
if (*str != '\0' || flags & PRINTFLAG_BEEP)
{
signal_emit_id(signal_gui_print_text, 6, window,
GINT_TO_POINTER(fgcolor), GINT_TO_POINTER(bgcolor),
GINT_TO_POINTER(flags), str, level);
flags &= ~(PRINTFLAG_BEEP|PRINTFLAG_INDENT);
}
if (*ptr == '\0') break;
switch (type)
{
case 2:
/* bold */
if (!toggle_hide_text_style)
flags ^= PRINTFLAG_BOLD;
break;
case 6:
/* blink */
if (!toggle_hide_text_style)
flags ^= PRINTFLAG_BLINK;
break;
case 15:
/* remove all styling */
flags &= PRINTFLAG_BEEP;
fgcolor = bgcolor = -1;
break;
case 22:
/* reverse */
if (!toggle_hide_text_style)
flags ^= PRINTFLAG_REVERSE;
break;
case 31:
/* underline */
if (!toggle_hide_text_style)
flags ^= PRINTFLAG_UNDERLINE;
case 27:
/* ansi color code */
ptr = convert_ansi(ptr, &fgcolor, &bgcolor, &flags);
break;
case 4:
/* user specific colors */
flags &= ~PRINTFLAG_MIRC_COLOR;
if ((signed char) *ptr == -1)
{
ptr++;
if ((signed char) *ptr == -1)
{
fgcolor = bgcolor = -1;
flags &= PRINTFLAG_INDENT;
}
else if (*ptr == 1)
flags ^= PRINTFLAG_BOLD;
else if (*ptr == 2)
flags ^= PRINTFLAG_UNDERLINE;
else if (*ptr == 3)
flags ^= PRINTFLAG_REVERSE;
else if (*ptr == 4)
flags |= PRINTFLAG_INDENT;
}
else
{
if ((signed char) *ptr != -2)
{
fgcolor = (guchar) *ptr-1;
if (fgcolor <= 7)
flags &= ~PRINTFLAG_BOLD;
else
{
/* bold */
if (fgcolor != 8) fgcolor -= 8;
flags |= PRINTFLAG_BOLD;
}
}
ptr++;
if ((signed char) *ptr != -2)
bgcolor = (signed char) *ptr == -1 ? -1 : *ptr-1;
}
ptr++;
break;
case 3:
if (*ptr < 17)
{
/* mostly just for irssi's internal use.. */
fgcolor = (*ptr++)-1;
if (*ptr == 0 || *ptr >= 17)
bgcolor = -1;
else
bgcolor = (*ptr++)-1;
if (fgcolor & 8)
flags |= PRINTFLAG_BOLD;
else
flags &= ~PRINTFLAG_BOLD;
break;
}
/* MIRC color */
if (toggle_hide_text_style)
{
/* don't show them. */
if (isdigit((gint) *ptr))
{
ptr++;
if (isdigit((gint) *ptr)) ptr++;
if (*ptr == ',')
{
ptr++;
if (isdigit((gint) *ptr))
{
ptr++;
if (isdigit((gint) *ptr)) ptr++;
}
}
}
break;
}
flags |= PRINTFLAG_MIRC_COLOR;
if (!isdigit((gint) *ptr) && *ptr != ',')
{
fgcolor = -1;
bgcolor = -1;
}
else
{
/* foreground color */
if (*ptr != ',')
{
fgcolor = *ptr++-'0';
if (isdigit((gint) *ptr))
fgcolor = fgcolor*10 + (*ptr++-'0');
}
if (*ptr == ',')
{
/* back color */
bgcolor = 0;
if (!isdigit((gint) *++ptr))
bgcolor = -1;
else
{
bgcolor = *ptr++-'0';
if (isdigit((gint) *ptr))
bgcolor = bgcolor*10 + (*ptr++-'0');
}
}
}
break;
}
str = ptr;
}
g_free(dup);
signal_emit_id(signal_print_text_finished, 1, window);
}
static int sig_check_daychange(void)
{
static gint lastday = -1;
GSList *tmp;
time_t t;
struct tm *tm;
if (!toggle_show_timestamps)
{
/* display day change notice only when using timestamps */
return TRUE;
}
t = time(NULL);
tm = localtime(&t);
if (lastday == -1)
{
/* First check, don't display. */
lastday = tm->tm_mday;
return TRUE;
}
if (tm->tm_mday == lastday)
return TRUE;
/* day changed, print notice about it to every window */
for (tmp = windows; tmp != NULL; tmp = tmp->next)
{
WINDOW_REC *win = tmp->data;
printformat(win->active->server, win->active->name, MSGLEVEL_NEVER,
IRCTXT_DAYCHANGE, tm->tm_mday, tm->tm_mon+1, 1900+tm->tm_year);
}
lastday = tm->tm_mday;
return TRUE;
}
static void sig_gui_dialog(const char *type, const char *text)
{
char **lines, **tmp;
if (g_strcasecmp(type, "warning") == 0)
type = _("%_Warning:%_ %s");
else if (g_strcasecmp(type, "error") == 0)
type = _("%_Error:%_ %s");
else
type = "%s";
lines = g_strsplit(text, "\n", -1);
for (tmp = lines; *tmp != NULL; tmp++)
printtext(NULL, NULL, MSGLEVEL_NEVER, type, *tmp);
g_strfreev(lines);
}
static void read_settings(void)
{
toggle_show_timestamps = settings_get_bool("toggle_show_timestamps");
toggle_show_msgs_timestamps = settings_get_bool("toggle_show_msgs_timestamps");
toggle_hide_text_style = settings_get_bool("toggle_hide_text_style");
}
void printtext_init(void)
{
settings_add_int("misc", "timestamp_timeout", 0);
signal_gui_print_text = module_get_uniq_id_str("signals", "gui print text");
signal_print_text_stripped = module_get_uniq_id_str("signals", "print text stripped");
signal_print_text = module_get_uniq_id_str("signals", "print text");
signal_print_text_finished = module_get_uniq_id_str("signals", "print text finished");
read_settings();
printtag = g_timeout_add(30000, (GSourceFunc) sig_check_daychange, NULL);
signal_add("print text", (SIGNAL_FUNC) sig_print_text);
signal_add("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
command_bind("beep", NULL, (SIGNAL_FUNC) printbeep);
}
void printtext_deinit(void)
{
g_source_remove(printtag);
signal_remove("print text", (SIGNAL_FUNC) sig_print_text);
signal_remove("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
command_unbind("beep", (SIGNAL_FUNC) printbeep);
}

View file

@ -0,0 +1,61 @@
#ifndef __PRINTTEXT_H
#define __PRINTTEXT_H
enum {
FORMAT_STRING,
FORMAT_INT,
FORMAT_LONG,
FORMAT_FLOAT
};
typedef struct {
char *tag;
char *def;
int params;
int paramtypes[10];
} FORMAT_REC;
#define PRINTFLAG_BOLD 0x01
#define PRINTFLAG_REVERSE 0x02
#define PRINTFLAG_UNDERLINE 0x04
#define PRINTFLAG_BEEP 0x08
#define PRINTFLAG_BLINK 0x10
#define PRINTFLAG_MIRC_COLOR 0x20
#define PRINTFLAG_INDENT 0x40
/* printformat(...) = printformat_format(module_formats, ...)
Could this be any harder? :) With GNU C compiler and C99 compilers,
use #define. With others use either inline functions if they are
supported or static functions if they are not..
*/
#ifdef __GNUC__
/* GCC */
# define printformat(server, channel, level, formatnum...) \
printformat_format(MODULE_FORMATS, server, channel, level, ##formatnum)
#elif defined (_ISOC99_SOURCE)
/* C99 */
# define printformat(server, channel, level, formatnum, ...) \
printformat_format(MODULE_FORMATS, server, channel, level, formatnum, __VA_ARGS__)
#else
/* inline/static */
#ifdef G_CAN_INLINE
inline
#else
static
#endif
void printformat(void *server, const char *channel, int level, int formatnum, ...)
{
printformat_format(MODULE_FORMATS, server, channel, level, ##formatnum);
}
#endif
void printformat_format(FORMAT_REC *formats, void *server, const char *channel, int level, int formatnum, ...);
void printtext(void *server, const char *channel, int level, const char *str, ...);
void printbeep(void);
void printtext_init(void);
void printtext_deinit(void);
#endif

278
src/fe-common/core/themes.c Normal file
View file

@ -0,0 +1,278 @@
/*
themes.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "signals.h"
#include "misc.h"
#include "lib-config/iconfig.h"
#include "settings.h"
#include "printtext.h"
#include "themes.h"
GSList *themes;
THEME_REC *current_theme;
THEME_REC *theme_create(const char *path, const char *name)
{
THEME_REC *rec;
g_return_val_if_fail(path != NULL, NULL);
g_return_val_if_fail(name != NULL, NULL);
rec = g_new0(THEME_REC, 1);
rec->path = g_strdup(path);
rec->name = g_strdup(name);
rec->modules = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal);
signal_emit("theme created", 1, rec);
return rec;
}
static void theme_destroy_hash(const char *key, MODULE_THEME_REC *rec)
{
int n, max;
max = strarray_length(rec->formatlist);
for (n = 0; n < max; n++)
if (rec->format[n] != NULL)
g_free(rec->format[n]);
g_free(rec->format);
g_strfreev(rec->formatlist);
g_free(rec->name);
g_free(rec);
}
void theme_destroy(THEME_REC *rec)
{
signal_emit("theme destroyed", 1, rec);
g_hash_table_foreach(rec->modules, (GHFunc) theme_destroy_hash, NULL);
g_hash_table_destroy(rec->modules);
if (rec->bg_pixmap != NULL) g_free(rec->bg_pixmap);
if (rec->font != NULL) g_free(rec->font);
g_free(rec->path);
g_free(rec->name);
g_free(rec);
}
static THEME_REC *theme_find(const char *name)
{
GSList *tmp;
for (tmp = themes; tmp != NULL; tmp = tmp->next) {
THEME_REC *rec = tmp->data;
if (g_strcasecmp(rec->name, name) == 0)
return rec;
}
return NULL;
}
/* Add all *.theme files from directory to themes */
static void find_themes(gchar *path)
{
DIR *dirp;
struct dirent *dp;
char *fname, *name;
int len;
dirp = opendir(path);
if (dirp == NULL) return;
while ((dp = readdir(dirp)) != NULL) {
len = strlen(dp->d_name);
if (len <= 6 || strcmp(dp->d_name+len-6, ".theme") != 0)
continue;
name = g_strndup(dp->d_name, strlen(dp->d_name)-6);
if (!theme_find(name)) {
fname = g_strdup_printf("%s/%s", path, dp->d_name);
themes = g_slist_append(themes, theme_create(fname, name));
g_free(fname);
}
g_free(name);
}
closedir(dirp);
}
/* Read module texts into theme */
static void theme_read_module_texts(const char *hashkey, MODULE_THEME_REC *rec, CONFIG_REC *config)
{
CONFIG_NODE *formats;
GSList *tmp;
char **flist;
int n;
formats = config_node_traverse(config, "moduleformats", FALSE);
if (formats == NULL) return;
for (tmp = formats->value; tmp != NULL; tmp = tmp->next) {
CONFIG_NODE *node = tmp->data;
if (node->key == NULL || node->value == NULL)
continue;
for (n = 0, flist = rec->formatlist; *flist != NULL; flist++, n++) {
if (g_strcasecmp(*flist, node->key) == 0) {
rec->format[n] = g_strdup(node->value);
break;
}
}
}
}
static int theme_read(THEME_REC *theme, const char *path)
{
MODULE_THEME_REC *mrec;
CONFIG_REC *config;
CONFIG_NODE *formats;
GSList *tmp;
char *value;
int errors;
config = config_open(path, -1);
if (config == NULL) {
/* didn't exist or no access? */
theme->default_color = 15;
return FALSE;
}
errors = config_parse(config) == -1;
/* default color */
theme->default_color = config_get_int(config, NULL, "default_color", 15);
/* get font */
value = config_get_str(config, NULL, "font", NULL);
theme->font = (value == NULL || *value == '\0') ? NULL : g_strdup(value);
/* get background pixmap */
value = config_get_str(config, NULL, "bg_pixmap", NULL);
theme->bg_pixmap = (value == NULL || *value == '\0') ? NULL : g_strdup(value);
/* get background pixmap properties */
if (config_get_bool(config, NULL, "bg_scrollable", FALSE))
theme->flags |= THEME_FLAG_BG_SCROLLABLE;
if (config_get_bool(config, NULL, "bg_scaled", TRUE))
theme->flags |= THEME_FLAG_BG_SCALED;
if (config_get_bool(config, NULL, "bg_shaded", FALSE))
theme->flags |= THEME_FLAG_BG_SHADED;
/* Read modules that are defined in this theme. */
formats = config_node_traverse(config, "modules", FALSE);
if (formats != NULL) {
for (tmp = formats->value; tmp != NULL; tmp = tmp->next) {
CONFIG_NODE *node = tmp->data;
if (node->key == NULL || node->value == NULL)
continue;
mrec = g_new0(MODULE_THEME_REC, 1);
mrec->name = g_strdup(node->key);
mrec->formatlist = g_strsplit(node->value, " ", -1);
mrec->format = g_new0(char*, strarray_length(mrec->formatlist));
g_hash_table_insert(theme->modules, mrec->name, mrec);
}
}
/* Read the texts inside the plugin */
g_hash_table_foreach(theme->modules, (GHFunc) theme_read_module_texts, config);
if (errors) {
/* errors fixed - save the theme */
if (config_write(config, NULL, 0660) == -1) {
/* we probably tried to save to global directory
where we didn't have access.. try saving it to
home dir instead. */
char *str;
/* check that we really didn't try to save
it to home dir.. */
str = g_strdup_printf("%s/.irssi/", g_get_home_dir());
if (strncmp(path, str, strlen(str)) != 0) {
g_free(str);
str = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(), g_basename(path));
config_write(config, str, 0660);
}
g_free(str);
}
}
config_close(config);
return errors;
}
static void sig_formats_error(void)
{
signal_emit("gui dialog", 2, "warning",
"Your theme(s) had some old format strings, "
"these have been changed back to their default values.");
signal_remove("irssi init finished", (SIGNAL_FUNC) sig_formats_error);
}
void themes_init(void)
{
THEME_REC *rec;
GSList *tmp;
const char *value;
char *str;
int errors;
/* first there's default theme.. */
str = g_strdup_printf("%s/.irssi/default.theme", g_get_home_dir());
current_theme = theme_create(str, "default");
current_theme->default_color = 15;
themes = g_slist_append(NULL, current_theme);
g_free(str);
/* read list of themes */
str = g_strdup_printf("%s/.irssi", g_get_home_dir());
find_themes(str);
g_free(str);
find_themes(SYSCONFDIR"/irssi");
/* read formats for all themes */
errors = FALSE;
for (tmp = themes; tmp != NULL; tmp = tmp->next) {
rec = tmp->data;
if (theme_read(rec, rec->path))
errors = TRUE;
}
if (errors)
signal_add("irssi init finished", (SIGNAL_FUNC) sig_formats_error);
/* find the current theme to use */
value = settings_get_str("current_theme");
rec = theme_find(value);
if (rec != NULL) current_theme = rec;
}
void themes_deinit(void)
{
/* free memory used by themes */
g_slist_foreach(themes, (GFunc) theme_destroy, NULL);
g_slist_free(themes);
themes = NULL;
}

View file

@ -0,0 +1,40 @@
#ifndef __THEMES_H
#define __THEMES_H
#define THEME_FLAG_BG_SCROLLABLE 0x0001
#define THEME_FLAG_BG_SCALED 0x0002
#define THEME_FLAG_BG_SHADED 0x0004
typedef struct
{
char *name;
char **formatlist;
char **format;
}
MODULE_THEME_REC;
typedef struct {
char *path;
char *name;
int default_color;
char *bg_pixmap;
char *font;
int flags;
GHashTable *modules;
gpointer gui_data;
} THEME_REC;
extern GSList *themes;
extern THEME_REC *current_theme;
THEME_REC *theme_create(const char *path, const char *name);
void theme_destroy(THEME_REC *rec);
void themes_init(void);
void themes_deinit(void);
#endif

View file

@ -0,0 +1,122 @@
/*
translation.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "signals.h"
#include "line-split.h"
#include "misc.h"
#include "settings.h"
unsigned char translation_in[256], translation_out[256];
void translation_reset(void)
{
int n;
for (n = 0; n < 256; n++)
translation_in[n] = (unsigned char) n;
for (n = 0; n < 256; n++)
translation_out[n] = (unsigned char) n;
}
void translate_output(char *text)
{
while (*text != '\0') {
*text = (char) translation_out[(int) (unsigned char) *text];
text++;
}
}
#define gethex(a) \
(isdigit(a) ? ((a)-'0') : (toupper(a)-'A'+10))
void translation_parse_line(const char *str, int *pos)
{
const char *ptr;
int value;
for (ptr = str; *ptr != '\0'; ptr++) {
if (ptr[0] != '0' || ptr[1] != 'x')
break;
ptr += 2;
value = (gethex(ptr[0]) << 4) + gethex(ptr[1]);
if (*pos < 256)
translation_in[*pos] = (unsigned char) value;
else
translation_out[*pos-256] = (unsigned char) value;
(*pos)++;
ptr += 2;
if (*ptr != ',') break;
}
}
int translation_read(const char *file)
{
char tmpbuf[1024], *str, *path;
LINEBUF_REC *buffer;
int f, pos, ret, recvlen;
g_return_val_if_fail(file != NULL, FALSE);
path = convert_home(file);
f = open(file, O_RDONLY);
g_free(path);
if (f == -1) return FALSE;
pos = 0; buffer = NULL;
while (pos < 512) {
recvlen = read(f, tmpbuf, sizeof(tmpbuf));
ret = line_split(tmpbuf, recvlen, &str, &buffer);
if (ret <= 0) break;
translation_parse_line(str, &pos);
}
line_split_free(buffer);
close(f);
if (pos != 512)
translation_reset();
return pos == 512;
}
static void read_settings(void)
{
translation_read(settings_get_str("translation"));
}
void translation_init(void)
{
translation_reset();
settings_add_str("misc", "translation", "");
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
read_settings();
}
void translation_deinit(void)
{
read_settings();
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
}

View file

@ -0,0 +1,12 @@
#ifndef __TRANSLATION_H
#define __TRANSLATION_H
extern unsigned char translation_in[256], translation_out[256];
int translation_read(const char *file);
void translate_output(char *text);
void translation_init(void);
void translation_deinit(void);
#endif

View file

@ -0,0 +1,224 @@
/*
window-items.c : irssi
Copyright (C) 2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "modules.h"
#include "signals.h"
#include "server.h"
#include "settings.h"
#include "levels.h"
#include "printtext.h"
#include "windows.h"
#include "window-items.h"
void window_add_item(WINDOW_REC *window, WI_ITEM_REC *item, int automatic)
{
g_return_if_fail(window != NULL);
g_return_if_fail(item != NULL);
MODULE_DATA_SET(item, window);
if (window->items == NULL) {
window->active = item;
window->active_server = item->server;
}
signal_emit("gui window item init", 1, item);
if (!automatic || settings_get_bool("window_auto_change")) {
if (automatic)
signal_emit("window changed automatic", 1, window);
window_set_active(window);
}
window->items = g_slist_append(window->items, item);
signal_emit("window item new", 2, window, item);
if (!automatic || g_slist_length(window->items) == 1) {
window->active = NULL;
window_item_set_active(window, item);
}
}
void window_remove_item(WINDOW_REC *window, WI_ITEM_REC *item)
{
g_return_if_fail(window != NULL);
g_return_if_fail(item != NULL);
if (g_slist_find(window->items, item) == NULL)
return;
MODULE_DATA_SET(item, NULL);
window->items = g_slist_remove(window->items, item);
if (window->active == item) {
window->active = window->items == NULL ? NULL :
window->items->data;
}
signal_emit("window item remove", 2, window, item);
}
WINDOW_REC *window_item_window(WI_ITEM_REC *item)
{
g_return_val_if_fail(item != NULL, NULL);
return MODULE_DATA(item);
}
void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item)
{
g_return_if_fail(window != NULL);
if (window->active != item) {
window->active = item;
if (item != NULL) window_change_server(window, window->active_server);
signal_emit("window item changed", 2, window, item);
}
}
void window_item_change_server(WI_ITEM_REC *item, void *server)
{
WINDOW_REC *window;
g_return_if_fail(item != NULL);
window = MODULE_DATA(item);
item->server = server;
signal_emit("window item server changed", 2, window, item);
if (window->active == item) window_change_server(window, item->server);
}
static WI_ITEM_REC *window_item_find_window(WINDOW_REC *window, void *server, const char *name)
{
GSList *tmp;
for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
WI_ITEM_REC *rec = tmp->data;
if ((server == NULL || rec->server == server) &&
g_strcasecmp(name, rec->name) == 0) return rec;
}
return NULL;
}
/* Find wanted window item by name. `server' can be NULL. */
WI_ITEM_REC *window_item_find(void *server, const char *name)
{
WI_ITEM_REC *item;
GSList *tmp;
g_return_val_if_fail(name != NULL, NULL);
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
item = window_item_find_window(rec, server, name);
if (item != NULL) return item;
}
return NULL;
}
static int waiting_channels_get(WINDOW_REC *window, const char *tag)
{
GSList *tmp;
g_return_val_if_fail(window != NULL, FALSE);
g_return_val_if_fail(tag != NULL, FALSE);
for (tmp = window->waiting_channels; tmp != NULL; tmp = tmp->next) {
if (g_strcasecmp(tmp->data, tag) == 0) {
g_free(tmp->data);
window->waiting_channels = g_slist_remove(window->waiting_channels, tmp->data);
return TRUE;
}
}
return FALSE;
}
void window_item_create(WI_ITEM_REC *item, int automatic)
{
WINDOW_REC *window;
GSList *tmp;
char *str;
g_return_if_fail(item != NULL);
str = item->server == NULL ? NULL :
g_strdup_printf("%s %s", ((SERVER_REC *) item->server)->tag, item->name);
window = NULL;
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
if (rec->items == NULL && rec->level == 0 &&
(window == NULL || rec == active_win)) {
/* no items in this window, we should probably use it.. */
window = rec;
}
if (rec->waiting_channels != NULL && str != NULL) {
/* right name/server tag combination in
some waiting list? */
if (waiting_channels_get(rec, str)) {
window = rec;
break;
}
}
}
g_free_not_null(str);
if (window == NULL) {
/* create new window to use */
window = window_create(item, automatic);
} else {
/* use existing window */
window_add_item(window, item, automatic);
}
}
static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item)
{
g_return_if_fail(window != NULL);
if (g_slist_length(window->items) > 1) {
/* default to printing "talking with ...",
you can override it it you wish */
printformat(item->server, item->name, MSGLEVEL_CLIENTNOTICE,
IRCTXT_TALKING_WITH, item->name);
}
}
void window_items_init(void)
{
signal_add_last("window item changed", (SIGNAL_FUNC) signal_window_item_changed);
}
void window_items_deinit(void)
{
signal_remove("window item changed", (SIGNAL_FUNC) signal_window_item_changed);
}

View file

@ -0,0 +1,22 @@
#ifndef __WINDOW_ITEMS_H
#define __WINDOW_ITEMS_H
#include "windows.h"
/* Add/remove window item from `window' */
void window_add_item(WINDOW_REC *window, WI_ITEM_REC *item, int automatic);
void window_remove_item(WINDOW_REC *window, WI_ITEM_REC *item);
/* Find a window for `item' and call window_add_item(). */
void window_item_create(WI_ITEM_REC *item, int automatic);
WINDOW_REC *window_item_window(WI_ITEM_REC *item);
void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item);
void window_item_change_server(WI_ITEM_REC *item, void *server);
/* Find wanted window item by name. `server' can be NULL. */
WI_ITEM_REC *window_item_find(void *server, const char *name);
void window_items_init(void);
void window_items_deinit(void);
#endif

View file

@ -0,0 +1,466 @@
/*
windows.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "modules.h"
#include "signals.h"
#include "commands.h"
#include "server.h"
#include "settings.h"
#include "levels.h"
#include "printtext.h"
#include "windows.h"
#include "window-items.h"
GSList *windows;
WINDOW_REC *active_win;
static int window_get_new_refnum(void)
{
WINDOW_REC *win;
GSList *tmp;
int refnum;
refnum = 1;
tmp = windows;
while (tmp != NULL) {
win = tmp->data;
if (refnum != win->refnum) {
tmp = tmp->next;
continue;
}
refnum++;
tmp = windows;
}
return refnum;
}
WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic)
{
WINDOW_REC *rec;
rec = g_new0(WINDOW_REC, 1);
rec->refnum = window_get_new_refnum();
windows = g_slist_append(windows, rec);
signal_emit("window created", 2, rec, GINT_TO_POINTER(automatic));
if (item != NULL) window_add_item(rec, item, automatic);
if (windows->next == NULL || !automatic || settings_get_bool("window_auto_change")) {
if (automatic && windows->next != NULL)
signal_emit("window changed automatic", 1, rec);
window_set_active(rec);
}
return rec;
}
void window_destroy(WINDOW_REC *window)
{
g_return_if_fail(window != NULL);
if (window->destroying) return;
window->destroying = TRUE;
while (window->items != NULL)
window_remove_item(window, window->items->data);
windows = g_slist_remove(windows, window);
signal_emit("window destroyed", 1, window);
g_slist_foreach(window->waiting_channels, (GFunc) g_free, NULL);
g_slist_free(window->waiting_channels);
g_free_not_null(window->name);
g_free(window);
}
void window_set_active_num(int number)
{
GSList *win;
win = g_slist_nth(windows, number);
if (win == NULL) return;
active_win = win->data;
signal_emit("window changed", 1, active_win);
}
void window_set_active(WINDOW_REC *window)
{
int number;
number = g_slist_index(windows, window);
if (number == -1) return;
active_win = window;
signal_emit("window changed", 1, active_win);
}
void window_change_server(WINDOW_REC *window, void *server)
{
window->active_server = server;
signal_emit("window server changed", 2, window, server);
}
void window_set_name(WINDOW_REC *window, const char *name)
{
g_free_not_null(window->name);
window->name = g_strdup(name);
signal_emit("window name changed", 1, window);
}
void window_set_level(WINDOW_REC *window, int level)
{
g_return_if_fail(window != NULL);
window->level = level;
signal_emit("window level changed", 1, window);
}
WINDOW_REC *window_find_level(void *server, int level)
{
WINDOW_REC *match;
GSList *tmp;
match = NULL;
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
if ((server == NULL || rec->active_server == server) &&
(rec->level & level)) {
if (server == NULL || rec->active_server == server)
return rec;
match = rec;
}
}
return match;
}
WINDOW_REC *window_find_closest(void *server, const char *name, int level)
{
WINDOW_REC *window;
WI_ITEM_REC *item;
/* match by name */
item = name == NULL ? NULL :
window_item_find(server, name);
if (item != NULL)
return window_item_window(item);
/* match by level */
if (level != MSGLEVEL_HILIGHT)
level &= ~(MSGLEVEL_HILIGHT | MSGLEVEL_NOHILIGHT);
window = window_find_level(server, level);
if (window != NULL) return window;
/* fallback to active */
return active_win;
}
static void cmd_window(const char *data, void *server, WI_ITEM_REC *item)
{
command_runsub("window", data, server, item);
}
static void cmd_window_new(const char *data, void *server, WI_ITEM_REC *item)
{
WINDOW_REC *window;
int type;
g_return_if_fail(data != NULL);
type = (g_strcasecmp(data, "hide") == 0 || g_strcasecmp(data, "tab") == 0) ? 1 :
(g_strcasecmp(data, "split") == 0 ? 2 : 0);
signal_emit("gui window create override", 1, GINT_TO_POINTER(type));
window = window_create(NULL, FALSE);
window_change_server(window, server);
}
static void cmd_window_close(const char *data)
{
/* destroy window unless it's the last one */
if (windows->next != NULL)
window_destroy(active_win);
}
/* return the first window number with the highest activity */
static int window_highest_activity(WINDOW_REC *window)
{
WINDOW_REC *rec;
GSList *tmp;
int max_num, max_act, through;
max_num = 0; max_act = 0; through = FALSE;
tmp = g_slist_find(windows, window);
for (;; tmp = tmp->next) {
if (tmp == NULL) {
tmp = windows;
through = TRUE;
}
if (through && tmp->data == window)
break;
rec = tmp->data;
if (rec->new_data && max_act < rec->new_data) {
max_act = rec->new_data;
max_num = g_slist_index(windows, rec)+1;
}
}
return max_num;
}
/* channel name - first try channel from same server */
static int window_find_name(WINDOW_REC *window, const char *name)
{
WI_ITEM_REC *item;
int num;
item = window_item_find(window->active_server, name);
if (item == NULL && window->active_server != NULL) {
/* not found from the active server - any server? */
item = window_item_find(NULL, name);
}
if (item == NULL) {
char *chan;
/* still nothing? maybe user just left the # in front of
channel, try again with it.. */
chan = g_strdup_printf("#%s", name);
item = window_item_find(window->active_server, chan);
if (item == NULL) item = window_item_find(NULL, chan);
g_free(chan);
}
if (item == NULL)
return 0;
/* get the window number */
window = MODULE_DATA(item);
if (window == NULL) return 0;
num = g_slist_index(windows, window);
return num < 0 ? 0 : num+1;
}
static void cmd_window_goto(const char *data)
{
int num;
g_return_if_fail(data != NULL);
num = 0;
if (g_strcasecmp(data, "active") == 0)
num = window_highest_activity(active_win);
else if (isdigit(*data))
num = atol(data);
else
num = window_find_name(active_win, data);
if (num > 0)
window_set_active_num(num-1);
}
static void cmd_window_next(const char *data)
{
int num;
num = g_slist_index(windows, active_win)+1;
if (num >= g_slist_length(windows)) num = 0;
window_set_active_num(num);
}
static void cmd_window_prev(const char *data)
{
int num;
num = g_slist_index(windows, active_win)-1;
if (num < 0) num = g_slist_length(windows)-1;
window_set_active_num(num);
}
static void cmd_window_level(const char *data)
{
g_return_if_fail(data != NULL);
window_set_level(active_win, combine_level(active_win->level, data));
printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "Window level is now %s",
bits2level(active_win->level));
}
static void cmd_window_server(const char *data)
{
SERVER_REC *server;
g_return_if_fail(data != NULL);
server = server_find_tag(data);
if (server == NULL)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_UNKNOWN_SERVER_TAG, data);
else if (active_win->active == NULL) {
window_change_server(active_win, server);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_SERVER_CHANGED, server->tag, server->connrec->address,
server->connrec->ircnet == NULL ? "" : server->connrec->ircnet);
}
}
static void cmd_window_item_prev(const char *data, void *server, WI_ITEM_REC *item)
{
WINDOW_REC *window;
WI_ITEM_REC *last;
GSList *tmp;
window = item == NULL ? NULL : MODULE_DATA(item);
if (window == NULL) return;
last = NULL;
for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
WI_ITEM_REC *rec = tmp->data;
if (rec != item)
last = rec;
else {
/* current channel. did we find anything?
if not, go to the last channel */
if (last != NULL) break;
}
}
if (last != NULL)
window_item_set_active(window, last);
}
static void cmd_window_item_next(const char *data, void *server, WI_ITEM_REC *item)
{
WINDOW_REC *window;
WI_ITEM_REC *next;
GSList *tmp;
int gone;
window = item == NULL ? NULL : MODULE_DATA(item);
if (window == NULL) return;
next = NULL; gone = FALSE;
for (tmp = window->items; tmp != NULL; tmp = tmp->next) {
WI_ITEM_REC *rec = tmp->data;
if (rec == item)
gone = TRUE;
else {
if (gone) {
/* found the next channel */
next = rec;
break;
}
if (next == NULL)
next = rec; /* fallback to first channel */
}
}
if (next != NULL)
window_item_set_active(window, next);
}
static void cmd_window_name(const char *data)
{
window_set_name(active_win, data);
}
static void sig_server_looking(void *server)
{
GSList *tmp;
g_return_if_fail(server != NULL);
/* try to keep some server assigned to windows.. */
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
if (rec->active_server == NULL)
window_change_server(rec, server);
}
}
static void sig_server_disconnected(void *server)
{
GSList *tmp;
g_return_if_fail(server != NULL);
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
if (rec->active_server == server)
window_change_server(rec, NULL);
}
}
void windows_init(void)
{
active_win = NULL;
settings_add_bool("lookandfeel", "window_auto_change", FALSE);
command_bind("window", NULL, (SIGNAL_FUNC) cmd_window);
command_bind("window new", NULL, (SIGNAL_FUNC) cmd_window_new);
command_bind("window close", NULL, (SIGNAL_FUNC) cmd_window_close);
command_bind("window server", NULL, (SIGNAL_FUNC) cmd_window_server);
command_bind("window goto", NULL, (SIGNAL_FUNC) cmd_window_goto);
command_bind("window prev", NULL, (SIGNAL_FUNC) cmd_window_prev);
command_bind("window next", NULL, (SIGNAL_FUNC) cmd_window_next);
command_bind("window level", NULL, (SIGNAL_FUNC) cmd_window_level);
command_bind("window item prev", NULL, (SIGNAL_FUNC) cmd_window_item_prev);
command_bind("window item next", NULL, (SIGNAL_FUNC) cmd_window_item_next);
command_bind("window name", NULL, (SIGNAL_FUNC) cmd_window_name);
signal_add("server looking", (SIGNAL_FUNC) sig_server_looking);
signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
signal_add("server connect failed", (SIGNAL_FUNC) sig_server_disconnected);
}
void windows_deinit(void)
{
command_unbind("window", (SIGNAL_FUNC) cmd_window);
command_unbind("window new", (SIGNAL_FUNC) cmd_window_new);
command_unbind("window close", (SIGNAL_FUNC) cmd_window_close);
command_unbind("window server", (SIGNAL_FUNC) cmd_window_server);
command_unbind("window goto", (SIGNAL_FUNC) cmd_window_goto);
command_unbind("window prev", (SIGNAL_FUNC) cmd_window_prev);
command_unbind("window next", (SIGNAL_FUNC) cmd_window_next);
command_unbind("window level", (SIGNAL_FUNC) cmd_window_level);
command_unbind("window item prev", (SIGNAL_FUNC) cmd_window_item_prev);
command_unbind("window item next", (SIGNAL_FUNC) cmd_window_item_next);
command_unbind("window name", (SIGNAL_FUNC) cmd_window_name);
signal_remove("server looking", (SIGNAL_FUNC) sig_server_looking);
signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
signal_remove("server connect failed", (SIGNAL_FUNC) sig_server_disconnected);
}

View file

@ -0,0 +1,67 @@
#ifndef __WINDOWS_H
#define __WINDOWS_H
enum {
NEWDATA_TEXT = 1,
NEWDATA_MSG,
NEWDATA_MSG_FORYOU,
NEWDATA_CUSTOM
};
/* All window items *MUST* have these variables in same order
at the start of the structure - the server's type can of course be
replaced with the preferred record type. */
typedef struct {
int type;
GHashTable *module_data;
void *server;
char *name;
int new_data;
} WI_ITEM_REC;
typedef struct {
int refnum;
char *name;
GSList *items;
WI_ITEM_REC *active;
void *active_server;
GSList *waiting_channels; /* list of "<server tag> <channel>" */
int lines;
int destroying:1;
/* window-specific command line history */
GList *cmdhist, *histpos;
int histlines;
int level;
int new_data;
time_t last_timestamp; /* When was last timestamp printed */
gpointer gui_data;
} WINDOW_REC;
extern GSList *windows;
extern WINDOW_REC *active_win;
WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic);
void window_destroy(WINDOW_REC *window);
void window_set_active_num(int number);
void window_set_active(WINDOW_REC *window);
void window_change_server(WINDOW_REC *window, void *server);
void window_set_name(WINDOW_REC *window, const char *name);
void window_set_level(WINDOW_REC *window, int level);
WINDOW_REC *window_find_level(void *server, int level);
WINDOW_REC *window_find_closest(void *server, const char *name, int level);
void windows_init(void);
void windows_deinit(void);
#endif

View file

@ -0,0 +1,32 @@
SUBDIRS = dcc flood notifylist
noinst_LTLIBRARIES = libfe_common_irc.la
INCLUDES = \
$(GLIB_CFLAGS) \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core/ \
-I$(top_srcdir)/src/irc/core/ \
-I$(top_srcdir)/src/fe-common/core/ \
-DHELPDIR=\""$(datadir)/irssi/help"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\"
libfe_common_irc_la_SOURCES = \
completion.c \
fe-channels.c \
fe-irc-commands.c \
fe-ctcp.c \
fe-events.c \
fe-events-numeric.c \
fe-ignore.c \
fe-query.c \
fe-common-irc.c \
irc-nick-hilight.c \
irc-hilight-text.c \
module-formats.c
noinst_HEADERS = \
completion.h \
fe-common-irc.h \
irc-hilight-text.h \
module-formats.h

View file

@ -0,0 +1,628 @@
/*
completion.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "signals.h"
#include "commands.h"
#include "misc.h"
#include "lib-config/iconfig.h"
#include "settings.h"
#include "irc.h"
#include "server.h"
#include "channels.h"
#include "nicklist.h"
#include "completion.h"
#include "window-items.h"
typedef struct {
time_t time;
char *nick;
} COMPLETION_REC;
#define replace_find(replace) \
iconfig_list_find("replaces", "text", replace, "replace")
#define completion_find(completion) \
iconfig_list_find("completions", "short", completion, "long")
static gint comptag;
static GList *complist;
static COMPLETION_REC *nick_completion_find(GSList *list, gchar *nick)
{
GSList *tmp;
for (tmp = list; tmp != NULL; tmp = tmp->next)
{
COMPLETION_REC *rec = tmp->data;
if (g_strcasecmp(rec->nick, nick) == 0) return rec;
}
return NULL;
}
static void completion_destroy(GSList **list, COMPLETION_REC *rec)
{
*list = g_slist_remove(*list, rec);
g_free(rec->nick);
g_free(rec);
}
static COMPLETION_REC *nick_completion_create(GSList **list, time_t time, gchar *nick)
{
COMPLETION_REC *rec;
rec = nick_completion_find(*list, nick);
if (rec != NULL)
{
/* remove the old one */
completion_destroy(list, rec);
}
rec = g_new(COMPLETION_REC, 1);
*list = g_slist_prepend(*list, rec);
rec->time = time;
rec->nick = g_strdup(nick);
return rec;
}
static void completion_checklist(GSList **list, gint timeout, time_t t)
{
GSList *tmp, *next;
for (tmp = *list; tmp != NULL; tmp = next)
{
COMPLETION_REC *rec = tmp->data;
next = tmp->next;
if (t-rec->time > timeout)
completion_destroy(list, rec);
}
}
static gint completion_timeout(void)
{
GSList *tmp, *link;
time_t t;
gint len;
t = time(NULL);
for (tmp = servers; tmp != NULL; tmp = tmp->next)
{
IRC_SERVER_REC *rec = tmp->data;
len = g_slist_length(rec->lastmsgs);
if (len > 0 && len >= settings_get_int("completion_keep_privates"))
{
link = g_slist_last(rec->lastmsgs);
g_free(link->data);
rec->lastmsgs = g_slist_remove_link(rec->lastmsgs, link);
g_slist_free_1(link);
}
}
for (tmp = channels; tmp != NULL; tmp = tmp->next)
{
CHANNEL_REC *rec = tmp->data;
completion_checklist(&rec->lastownmsgs, settings_get_int("completion_keep_ownpublics"), t);
completion_checklist(&rec->lastmsgs, settings_get_int("completion_keep_publics"), t);
}
return 1;
}
static void add_private_msg(IRC_SERVER_REC *server, gchar *nick)
{
GSList *link;
link = gslist_find_icase_string(server->lastmsgs, nick);
if (link != NULL)
{
g_free(link->data);
server->lastmsgs = g_slist_remove_link(server->lastmsgs, link);
g_slist_free_1(link);
}
server->lastmsgs = g_slist_prepend(server->lastmsgs, g_strdup(nick));
}
static void event_privmsg(gchar *data, IRC_SERVER_REC *server, gchar *nick)
{
gchar *params, *target, *msg;
GSList **list;
g_return_if_fail(server != NULL);
if (nick == NULL) return; /* from server */
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
if (*msg == 1)
{
/* ignore ctcp messages */
g_free(params);
return;
}
if (ischannel(*target))
{
/* channel message */
CHANNEL_REC *channel;
channel = channel_find(server, target);
if (channel == NULL)
{
g_free(params);
return;
}
list = completion_msgtoyou((SERVER_REC *) server, msg) ?
&channel->lastownmsgs :
&channel->lastmsgs;
nick_completion_create(list, time(NULL), nick);
}
else
{
/* private message */
add_private_msg(server, nick);
}
g_free(params);
}
static void cmd_msg(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *target, *msg;
g_return_if_fail(data != NULL);
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
if (*target != '\0' && *msg != '\0')
{
if (!ischannel(*target) && *target != '=' && server != NULL)
add_private_msg(server, target);
}
g_free(params);
}
int completion_msgtoyou(SERVER_REC *server, const char *msg)
{
gchar *stripped, *nick;
gboolean ret;
gint len;
g_return_val_if_fail(msg != NULL, FALSE);
if (g_strncasecmp(msg, server->nick, strlen(server->nick)) == 0 &&
!isalnum((gint) msg[strlen(server->nick)])) return TRUE;
stripped = nick_strip(server->nick);
nick = nick_strip(msg);
len = strlen(stripped);
ret = *stripped != '\0' &&
g_strncasecmp(nick, stripped, len) == 0 &&
!isalnum((gint) nick[len]) &&
(guchar) nick[len] < 128;
g_free(nick);
g_free(stripped);
return ret;
}
static void complete_list(GList **outlist, GSList *list, gchar *nick)
{
GSList *tmp;
gint len;
len = strlen(nick);
for (tmp = list; tmp != NULL; tmp = tmp->next)
{
COMPLETION_REC *rec = tmp->data;
if (g_strncasecmp(rec->nick, nick, len) == 0 &&
glist_find_icase_string(*outlist, rec->nick) == NULL)
*outlist = g_list_append(*outlist, g_strdup(rec->nick));
}
}
static GList *completion_getlist(CHANNEL_REC *channel, gchar *nick)
{
GSList *nicks, *tmp;
GList *list;
gint len;
g_return_val_if_fail(channel != NULL, NULL);
g_return_val_if_fail(nick != NULL, NULL);
if (*nick == '\0') return NULL;
list = NULL;
complete_list(&list, channel->lastownmsgs, nick);
complete_list(&list, channel->lastmsgs, nick);
len = strlen(nick);
nicks = nicklist_getnicks(channel);
for (tmp = nicks; tmp != NULL; tmp = tmp->next)
{
NICK_REC *rec = tmp->data;
if (g_strncasecmp(rec->nick, nick, len) == 0 &&
glist_find_icase_string(list, rec->nick) == NULL &&
g_strcasecmp(rec->nick, channel->server->nick) != 0)
list = g_list_append(list, g_strdup(rec->nick));
}
g_slist_free(nicks);
return list;
}
static GList *completion_getmsglist(IRC_SERVER_REC *server, gchar *nick)
{
GSList *tmp;
GList *list;
gint len;
list = NULL; len = strlen(nick);
for (tmp = server->lastmsgs; tmp != NULL; tmp = tmp->next)
{
if (len == 0 || g_strncasecmp(tmp->data, nick, len) == 0)
list = g_list_append(list, g_strdup(tmp->data));
}
return list;
}
static void event_command(gchar *line, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
CHANNEL_REC *channel;
GList *comp;
gchar *str, *ptr;
g_return_if_fail(line != NULL);
if (!irc_item_check(item))
return;
if (strchr(settings_get_str("cmdchars"), *line) != NULL)
return;
line = g_strdup(line);
/* check for nick completion */
if (settings_get_bool("completion_disable_auto") || *settings_get_str("completion_char") == '\0')
{
ptr = NULL;
comp = NULL;
}
else
{
ptr = strchr(line, *settings_get_str("completion_char"));
if (ptr != NULL) *ptr++ = '\0';
channel = irc_item_channel(item);
comp = ptr == NULL || channel == NULL ||
nicklist_find(channel, line) != NULL ? NULL :
completion_getlist(channel, line);
}
/* message to channel */
if (ptr == NULL)
str = g_strdup_printf("%s %s", item->name, line);
else
{
str = g_strdup_printf("%s %s%s%s", item->name,
comp != NULL ? (gchar *) comp->data : line,
settings_get_str("completion_char"), ptr);
}
signal_emit("command msg", 3, str, server, item);
g_free(str);
g_free(line);
if (comp != NULL)
{
g_list_foreach(comp, (GFunc) g_free, NULL);
g_list_free(comp);
}
signal_stop();
}
static GList *completion_joinlist(GList *list1, GList *list2)
{
while (list2 != NULL)
{
if (!glist_find_icase_string(list1, list2->data))
list1 = g_list_append(list1, list2->data);
else
g_free(list2->data);
list2 = list2->next;
}
g_list_free(list2);
return list1;
}
char *auto_completion(const char *line, int *pos)
{
const char *replace;
gchar *word, *ret;
gint spos, epos, n, wordpos;
GString *result;
g_return_val_if_fail(line != NULL, NULL);
g_return_val_if_fail(pos != NULL, NULL);
spos = *pos;
/* get the word we are completing.. */
while (spos > 0 && isspace((gint) line[spos-1])) spos--;
epos = spos;
while (spos > 0 && !isspace((gint) line[spos-1])) spos--;
while (line[epos] != '\0' && !isspace((gint) line[epos])) epos++;
word = g_strdup(line+spos);
word[epos-spos] = '\0';
/* word position in line */
wordpos = 0;
for (n = 0; n < spos; )
{
while (n < spos && isspace((gint) line[n])) n++;
while (n < spos && !isspace((gint) line[n])) n++;
if (n < spos) wordpos++;
}
result = g_string_new(line);
g_string_erase(result, spos, epos-spos);
/* check for words in autocompletion list */
replace = replace_find(word); g_free(word);
if (replace != NULL)
{
*pos = spos+strlen(replace);
g_string_insert(result, spos, replace);
ret = result->str;
g_string_free(result, FALSE);
return ret;
}
g_string_free(result, TRUE);
return NULL;
}
#define issplit(a) ((a) == ',' || (a) == ' ')
char *completion_line(WINDOW_REC *window, const char *line, int *pos)
{
static gboolean msgcomp = FALSE;
const char *completion;
CHANNEL_REC *channel;
SERVER_REC *server;
gchar *word, *ret;
gint spos, epos, len, n, wordpos;
gboolean msgcompletion;
GString *result;
g_return_val_if_fail(window != NULL, NULL);
g_return_val_if_fail(line != NULL, NULL);
g_return_val_if_fail(pos != NULL, NULL);
spos = *pos;
/* get the word we are completing.. */
while (spos > 0 && issplit((gint) line[spos-1])) spos--;
epos = spos;
if (line[epos] == ',') epos++;
while (spos > 0 && !issplit((gint) line[spos-1])) spos--;
while (line[epos] != '\0' && !issplit((gint) line[epos])) epos++;
word = g_strdup(line+spos);
word[epos-spos] = '\0';
/* word position in line */
wordpos = 0;
for (n = 0; n < spos; )
{
while (n < spos && issplit((gint) line[n])) n++;
while (n < spos && !issplit((gint) line[n])) n++;
if (n < spos) wordpos++;
}
server = window->active == NULL ? window->active_server : window->active->server;
msgcompletion = server != NULL &&
(*line == '\0' || ((wordpos == 0 || wordpos == 1) && g_strncasecmp(line, "/msg ", 5) == 0));
if (msgcompletion && wordpos == 0 && issplit((gint) line[epos]))
{
/* /msg <tab> */
*word = '\0'; epos++; spos = epos; wordpos = 1;
}
/* are we completing the same nick as last time?
if not, forget the old completion.. */
len = strlen(word)-(msgcomp == FALSE && word[strlen(word)-1] == *settings_get_str("completion_char"));
if (complist != NULL && (strlen(complist->data) != len || g_strncasecmp(complist->data, word, len) != 0))
{
g_list_foreach(complist, (GFunc) g_free, NULL);
g_list_free(complist);
complist = NULL;
}
result = g_string_new(line);
g_string_erase(result, spos, epos-spos);
/* check for words in completion list */
completion = completion_find(word);
if (completion != NULL)
{
g_free(word);
*pos = spos+strlen(completion);
g_string_insert(result, spos, completion);
ret = result->str;
g_string_free(result, FALSE);
return ret;
}
channel = irc_item_channel(window->active);
if (complist == NULL && !msgcompletion && channel == NULL)
{
/* don't try nick completion */
g_free(word);
g_string_free(result, TRUE);
return NULL;
}
if (complist == NULL)
{
/* start new nick completion */
complist = channel == NULL ? NULL : completion_getlist(channel, word);
if (!msgcompletion)
{
/* nick completion in channel */
msgcomp = FALSE;
}
else
{
GList *tmpcomp;
/* /msg completion */
msgcomp = TRUE;
/* first get the list of msg nicks and then nicks from current
channel. */
tmpcomp = complist;
complist = completion_getmsglist((IRC_SERVER_REC *) server, word);
complist = completion_joinlist(complist, tmpcomp);
if (*line == '\0')
{
/* completion in empty line -> /msg <nick> */
g_free(word);
g_string_free(result, TRUE);
if (complist == NULL)
ret = g_strdup("/msg ");
else
ret = g_strdup_printf("/msg %s ", (gchar *) complist->data);
*pos = strlen(ret);
return ret;
}
}
if (complist == NULL)
{
g_free(word);
g_string_free(result, TRUE);
return NULL;
}
}
else
{
/* continue the last completion */
complist = complist->next == NULL ? g_list_first(complist) : complist->next;
}
g_free(word);
/* insert the nick.. */
g_string_insert(result, spos, complist->data);
*pos = spos+strlen(complist->data);
if (!msgcomp && wordpos == 0)
{
/* insert completion character */
g_string_insert(result, *pos, settings_get_str("completion_char"));
*pos += strlen(settings_get_str("completion_char"));
}
if (msgcomp || wordpos == 0)
{
if (!issplit((gint) result->str[*pos]))
{
/* insert space */
g_string_insert(result, *pos, " ");
}
(*pos)++;
}
ret = result->str;
g_string_free(result, FALSE);
return ret;
}
static void completion_deinit_server(IRC_SERVER_REC *server)
{
g_return_if_fail(server != NULL);
g_slist_foreach(server->lastmsgs, (GFunc) g_free, NULL);
g_slist_free(server->lastmsgs);
}
static void completion_deinit_channel(CHANNEL_REC *channel)
{
g_return_if_fail(channel != NULL);
while (channel->lastmsgs != NULL)
completion_destroy(&channel->lastmsgs, channel->lastmsgs->data);
while (channel->lastownmsgs != NULL)
completion_destroy(&channel->lastownmsgs, channel->lastownmsgs->data);
g_slist_free(channel->lastmsgs);
g_slist_free(channel->lastownmsgs);
}
void completion_init(void)
{
settings_add_str("completion", "completion_char", ":");
settings_add_bool("completion", "completion_disable_auto", FALSE);
settings_add_int("completion", "completion_keep_publics", 180);
settings_add_int("completion", "completion_keep_ownpublics", 360);
settings_add_int("completion", "completion_keep_privates", 10);
signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg);
signal_add("send command", (SIGNAL_FUNC) event_command);
signal_add("server disconnected", (SIGNAL_FUNC) completion_deinit_server);
signal_add("channel destroyed", (SIGNAL_FUNC) completion_deinit_channel);
command_bind("msg", NULL, (SIGNAL_FUNC) cmd_msg);
comptag = g_timeout_add(1000, (GSourceFunc) completion_timeout, NULL);
complist = NULL;
}
void completion_deinit(void)
{
g_list_foreach(complist, (GFunc) g_free, NULL);
g_list_free(complist);
g_source_remove(comptag);
signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg);
signal_remove("send command", (SIGNAL_FUNC) event_command);
signal_remove("server disconnected", (SIGNAL_FUNC) completion_deinit_server);
signal_remove("channel destroyed", (SIGNAL_FUNC) completion_deinit_channel);
command_unbind("msg", (SIGNAL_FUNC) cmd_msg);
}

View file

@ -0,0 +1,13 @@
#ifndef __COMPLETION_H
#define __COMPLETION_H
#include "window-items.h"
int completion_msgtoyou(SERVER_REC *server, const char *msg);
char *completion_line(WINDOW_REC *window, const char *line, int *pos);
char *auto_completion(const char *line, int *pos);
void completion_init(void);
void completion_deinit(void);
#endif

View file

@ -0,0 +1,17 @@
noinst_LTLIBRARIES = libfe_common_irc_dcc.la
INCLUDES = \
$(GLIB_CFLAGS) \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core/ \
-I$(top_srcdir)/src/irc/core/ \
-I$(top_srcdir)/src/fe-common/core/ \
-DHELPDIR=\""$(datadir)/irssi/help"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\"
libfe_common_irc_dcc_la_SOURCES = \
fe-dcc.c \
module-formats.c
noinst_HEADERS = \
module-formats.h

View file

@ -0,0 +1,457 @@
/*
fe-dcc.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "commands.h"
#include "network.h"
#include "levels.h"
#include "irc.h"
#include "channels.h"
#include "irc/dcc/dcc.h"
#include "windows.h"
static void dcc_connected(DCC_REC *dcc)
{
gchar *str;
g_return_if_fail(dcc != NULL);
switch (dcc->dcc_type)
{
case DCC_TYPE_CHAT:
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CHAT_CONNECTED,
dcc->nick, dcc->addrstr, dcc->port);
str = g_strconcat("=", dcc->nick, NULL);
/*FIXME: dcc_chat_create(dcc->server, str, FALSE);*/
g_free(str);
break;
case DCC_TYPE_SEND:
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_CONNECTED,
dcc->arg, dcc->nick, dcc->addrstr, dcc->port);
break;
case DCC_TYPE_GET:
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_CONNECTED,
dcc->arg, dcc->nick, dcc->addrstr, dcc->port);
break;
}
}
static void dcc_rejected(DCC_REC *dcc)
{
g_return_if_fail(dcc != NULL);
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CLOSE,
dcc_type2str(dcc->dcc_type), dcc->nick, dcc->arg);
}
static void dcc_closed(DCC_REC *dcc)
{
time_t secs;
gdouble kbs;
g_return_if_fail(dcc != NULL);
secs = dcc->starttime == 0 ? -1 : time(NULL)-dcc->starttime;
kbs = (gdouble) (dcc->transfd-dcc->skipped) / (secs == 0 ? 1 : secs) / 1024.0;
switch (dcc->dcc_type)
{
case DCC_TYPE_CHAT:
{
/* nice kludge :) if connection was lost, close the channel.
after closed channel (can be done with /unquery too)
prints the disconnected-text.. */
CHANNEL_REC *channel;
gchar *str;
str = g_strdup_printf("=%s", dcc->nick);
printformat(dcc->server, str, MSGLEVEL_DCC,
IRCTXT_DCC_CHAT_DISCONNECTED, dcc->nick);
channel = channel_find(dcc->server, str);
if (channel != NULL)
channel_destroy(channel);
g_free(str);
}
break;
case DCC_TYPE_SEND:
if (secs == -1)
{
/* aborted */
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_ABORTED,
dcc->arg, dcc->nick);
}
else
{
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_COMPLETE,
dcc->arg, dcc->transfd/1024, dcc->nick, (glong) secs, kbs);
}
break;
case DCC_TYPE_GET:
if (secs == -1)
{
/* aborted */
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_ABORTED,
dcc->arg, dcc->nick);
}
else
{
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_COMPLETE,
dcc->arg, dcc->transfd/1024, dcc->nick, (glong) secs, kbs);
}
break;
}
}
static void dcc_chat_in_action(gchar *msg, DCC_REC *dcc)
{
gchar *sender;
g_return_if_fail(dcc != NULL);
g_return_if_fail(msg != NULL);
sender = g_strconcat("=", dcc->nick, NULL);
printformat(NULL, sender, MSGLEVEL_DCC,
IRCTXT_ACTION_DCC, dcc->nick, msg);
g_free(sender);
}
static void dcc_chat_ctcp(gchar *msg, DCC_REC *dcc)
{
gchar *sender;
g_return_if_fail(dcc != NULL);
g_return_if_fail(msg != NULL);
sender = g_strconcat("=", dcc->nick, NULL);
printformat(NULL, sender, MSGLEVEL_DCC, IRCTXT_DCC_CTCP, dcc->nick, msg);
g_free(sender);
}
static void dcc_chat_msg(DCC_REC *dcc, gchar *msg)
{
gchar *nick;
g_return_if_fail(dcc != NULL);
g_return_if_fail(msg != NULL);
nick = g_strconcat("=", dcc->nick, NULL);
printformat(NULL, nick, MSGLEVEL_DCC, IRCTXT_DCC_MSG, dcc->nick, msg);
g_free(nick);
}
static void dcc_request(DCC_REC *dcc)
{
g_return_if_fail(dcc != NULL);
switch (dcc->dcc_type)
{
case DCC_TYPE_CHAT:
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CHAT,
dcc->nick, dcc->addrstr, dcc->port);
break;
case DCC_TYPE_GET:
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND,
dcc->nick, dcc->addrstr, dcc->port, dcc->arg, dcc->size);
break;
}
}
static void dcc_error_connect(DCC_REC *dcc)
{
g_return_if_fail(dcc != NULL);
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CONNECT_ERROR, dcc->addrstr, dcc->port);
}
static void dcc_error_file_create(DCC_REC *dcc, gchar *fname)
{
g_return_if_fail(dcc != NULL);
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CANT_CREATE, fname);
}
static void dcc_error_file_not_found(gchar *nick, gchar *fname)
{
g_return_if_fail(nick != NULL);
g_return_if_fail(fname != NULL);
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_FILE_NOT_FOUND, fname);
}
static void dcc_error_get_not_found(gchar *nick)
{
g_return_if_fail(nick != NULL);
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_NOT_FOUND, nick);
}
static void dcc_error_send_exists(gchar *nick, gchar *fname)
{
g_return_if_fail(nick != NULL);
g_return_if_fail(fname != NULL);
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_EXISTS, fname, nick);
}
static void dcc_error_unknown_type(gchar *type)
{
g_return_if_fail(type != NULL);
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_TYPE, type);
}
static void dcc_error_close_not_found(gchar *type, gchar *nick, gchar *fname)
{
g_return_if_fail(type != NULL);
g_return_if_fail(nick != NULL);
g_return_if_fail(fname != NULL);
if (fname == '\0') fname = "(ANY)";
switch (dcc_str2type(type))
{
case DCC_TYPE_CHAT:
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_CHAT_NOT_FOUND, nick);
break;
case DCC_TYPE_SEND:
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SEND_NOT_FOUND, nick, fname);
break;
case DCC_TYPE_GET:
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_GET_NOT_FOUND, nick, fname);
break;
}
}
static void dcc_unknown_ctcp(gchar *data, gchar *sender)
{
gchar *params, *type, *args;
g_return_if_fail(data != NULL);
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &type, &args);
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_CTCP, type, sender, args);
g_free(params);
}
static void dcc_unknown_reply(gchar *data, gchar *sender)
{
gchar *params, *type, *args;
g_return_if_fail(data != NULL);
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &type, &args);
printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_UNKNOWN_REPLY, type, sender, args);
g_free(params);
}
static void dcc_chat_write(gchar *data)
{
DCC_REC *dcc;
gchar *params, *text, *target;
g_return_if_fail(data != NULL);
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &text);
if (*target == '=')
{
/* dcc msg */
dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL);
if (dcc == NULL)
{
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
IRCTXT_DCC_CHAT_NOT_FOUND, target+1);
return;
}
printformat(NULL, target, MSGLEVEL_DCC, IRCTXT_OWN_DCC, target+1, text);
}
g_free(params);
}
static void dcc_chat_out_me(gchar *data, SERVER_REC *server, WI_IRC_REC *item)
{
DCC_REC *dcc;
g_return_if_fail(data != NULL);
dcc = irc_item_dcc_chat(item);
if (dcc == NULL) return;
printformat(NULL, item->name, MSGLEVEL_DCC,
IRCTXT_OWN_ME, dcc->mynick, data);
}
static void dcc_chat_out_action(const char *data, SERVER_REC *server, WI_IRC_REC *item)
{
char *params, *target, *text;
DCC_REC *dcc;
g_return_if_fail(data != NULL);
if (*data != '=') {
/* handle only DCC actions */
return;
}
params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text);
if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL);
if (dcc == NULL){
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
IRCTXT_DCC_CHAT_NOT_FOUND, target+1);
} else {
printformat(NULL, item->name, MSGLEVEL_DCC,
IRCTXT_OWN_ME, dcc->mynick, text);
}
g_free(params);
}
static void dcc_chat_out_ctcp(gchar *data, SERVER_REC *server)
{
char *params, *target, *ctcpcmd, *ctcpdata;
DCC_REC *dcc;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata);
if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target != '=') {
/* handle only DCC CTCPs */
g_free(params);
return;
}
dcc = dcc_find_item(DCC_TYPE_CHAT, target+1, NULL);
if (dcc == NULL) {
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
IRCTXT_DCC_CHAT_NOT_FOUND, target+1);
} else {
g_strup(ctcpcmd);
printformat(server, target, MSGLEVEL_DCC, IRCTXT_OWN_CTCP,
target, ctcpcmd, ctcpdata);
}
g_free(params);
}
static void cmd_dcc_list(gchar *data)
{
GSList *tmp;
time_t going;
g_return_if_fail(data != NULL);
printtext(NULL, NULL, MSGLEVEL_DCC, "%gDCC connections");
for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next)
{
DCC_REC *dcc = tmp->data;
going = time(NULL) - dcc->starttime;
if (going == 0) going = 1; /* no division by zeros :) */
if (dcc->dcc_type == DCC_TYPE_CHAT)
printtext(NULL, NULL, MSGLEVEL_DCC, "%g %s %s", dcc->nick, dcc_type2str(dcc->dcc_type));
else
printtext(NULL, NULL, MSGLEVEL_DCC, "%g %s %s: %luk of %luk (%d%%) - %fkB/s - %s",
dcc->nick, dcc_type2str(dcc->dcc_type), dcc->transfd/1024, dcc->size/1024,
dcc->size == 0 ? 0 : (100*dcc->transfd/dcc->size),
(gdouble) (dcc->transfd-dcc->skipped)/going/1024, dcc->arg);
}
}
static void dcc_chat_closed(WINDOW_REC *window, WI_IRC_REC *item)
{
DCC_REC *dcc;
dcc = irc_item_dcc_chat(item);
if (dcc == NULL) return;
/* check that we haven't got here from dcc_destroy() so we won't try to
close the dcc again.. */
if (!dcc->destroyed) {
/* DCC query window closed, close the dcc chat too. */
dcc_destroy(dcc);
}
}
void fe_dcc_init(void)
{
signal_add("dcc connected", (SIGNAL_FUNC) dcc_connected);
signal_add("dcc rejected", (SIGNAL_FUNC) dcc_rejected);
signal_add("dcc closed", (SIGNAL_FUNC) dcc_closed);
signal_add("dcc chat message", (SIGNAL_FUNC) dcc_chat_msg);
signal_add("dcc ctcp action", (SIGNAL_FUNC) dcc_chat_in_action);
signal_add("default dcc ctcp", (SIGNAL_FUNC) dcc_chat_ctcp);
signal_add("dcc request", (SIGNAL_FUNC) dcc_request);
signal_add("dcc error connect", (SIGNAL_FUNC) dcc_error_connect);
signal_add("dcc error file create", (SIGNAL_FUNC) dcc_error_file_create);
signal_add("dcc error file not found", (SIGNAL_FUNC) dcc_error_file_not_found);
signal_add("dcc error get not found", (SIGNAL_FUNC) dcc_error_get_not_found);
signal_add("dcc error send exists", (SIGNAL_FUNC) dcc_error_send_exists);
signal_add("dcc error unknown type", (SIGNAL_FUNC) dcc_error_unknown_type);
signal_add("dcc error close not found", (SIGNAL_FUNC) dcc_error_close_not_found);
signal_add("dcc unknown ctcp", (SIGNAL_FUNC) dcc_unknown_ctcp);
signal_add("dcc unknown reply", (SIGNAL_FUNC) dcc_unknown_reply);
command_bind("msg", NULL, (SIGNAL_FUNC) dcc_chat_write);
command_bind("me", NULL, (SIGNAL_FUNC) dcc_chat_out_me);
command_bind("action", NULL, (SIGNAL_FUNC) dcc_chat_out_action);
command_bind("ctcp", NULL, (SIGNAL_FUNC) dcc_chat_out_ctcp);
command_bind("dcc ", NULL, (SIGNAL_FUNC) cmd_dcc_list);
command_bind("dcc list", NULL, (SIGNAL_FUNC) cmd_dcc_list);
signal_add("window item remove", (SIGNAL_FUNC) dcc_chat_closed);
}
void fe_dcc_deinit(void)
{
signal_remove("dcc connected", (SIGNAL_FUNC) dcc_connected);
signal_remove("dcc rejected", (SIGNAL_FUNC) dcc_rejected);
signal_remove("dcc closed", (SIGNAL_FUNC) dcc_closed);
signal_remove("dcc chat message", (SIGNAL_FUNC) dcc_chat_msg);
signal_remove("dcc ctcp action", (SIGNAL_FUNC) dcc_chat_in_action);
signal_remove("default dcc ctcp", (SIGNAL_FUNC) dcc_chat_ctcp);
signal_remove("dcc request", (SIGNAL_FUNC) dcc_request);
signal_remove("dcc error connect", (SIGNAL_FUNC) dcc_error_connect);
signal_remove("dcc error file create", (SIGNAL_FUNC) dcc_error_file_create);
signal_remove("dcc error file not found", (SIGNAL_FUNC) dcc_error_file_not_found);
signal_remove("dcc error get not found", (SIGNAL_FUNC) dcc_error_get_not_found);
signal_remove("dcc error send exists", (SIGNAL_FUNC) dcc_error_send_exists);
signal_remove("dcc error unknown type", (SIGNAL_FUNC) dcc_error_unknown_type);
signal_remove("dcc error close not found", (SIGNAL_FUNC) dcc_error_close_not_found);
signal_remove("dcc unknown ctcp", (SIGNAL_FUNC) dcc_unknown_ctcp);
signal_remove("dcc unknown reply", (SIGNAL_FUNC) dcc_unknown_reply);
command_unbind("msg", (SIGNAL_FUNC) dcc_chat_write);
command_unbind("me", (SIGNAL_FUNC) dcc_chat_out_me);
command_unbind("action", (SIGNAL_FUNC) dcc_chat_out_action);
command_unbind("ctcp", (SIGNAL_FUNC) dcc_chat_out_ctcp);
command_unbind("dcc ", (SIGNAL_FUNC) cmd_dcc_list);
command_unbind("dcc list", (SIGNAL_FUNC) cmd_dcc_list);
signal_remove("window item remove", (SIGNAL_FUNC) dcc_chat_closed);
}

View file

@ -0,0 +1,57 @@
/*
module-formats.c : irssi
Copyright (C) 2000 Timo Sirainen
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 "module.h"
#include "printtext.h"
FORMAT_REC fecommon_irc_dcc_formats[] =
{
{ MODULE_NAME, N_("IRC"), 0 },
/* ---- */
{ NULL, N_("DCC"), 0 },
{ "own_dcc", N_("%K[%rdcc%K(%R$0%K)]%n $1"), 2, { 0, 0 } },
{ "dcc_msg", N_("%K[%G$0%K(%gdcc%K)]%n $1"), 2, { 0, 0 } },
{ "action_dcc", N_("%W (*dcc*) $0%n $1"), 2, { 0, 0 } },
{ "dcc_ctcp", N_("%g>>> DCC CTCP received from %_$0%_%K: %g$1"), 2, { 0, 0 } },
{ "dcc_chat", N_("%gDCC CHAT from %_$0%_ %K[%g$1 port $2%K]"), 3, { 0, 0, 1 } },
{ "dcc_chat_not_found", N_("%gNo DCC CHAT connection open to %_$0"), 1, { 0 } },
{ "dcc_chat_connected", N_("%gDCC %_CHAT%_ connection with %_$0%_ %K%K[%g$1 port $2%K]%g established"), 3, { 0, 0, 1 } },
{ "dcc_chat_disconnected", N_("%gDCC lost chat to %_$0"), 1, { 0 } },
{ "dcc_send", N_("%gDCC SEND from %_$0%_ %K[%g$1 port $2%K]: %g$3 %K[%g$4 bytes%K]"), 5, { 0, 0, 1, 0, 2 } },
{ "dcc_send_exists", N_("%gDCC already sending file %G$0%g for %_$1%_"), 2, { 0, 0 } },
{ "dcc_send_not_found", N_("%gDCC not sending file %G$1%g to %_$0"), 2, { 0, 0 } },
{ "dcc_send_file_not_found", N_("%gDCC file not found: %G$0%g"), 1, { 0 } },
{ "dcc_send_connected", N_("%gDCC sending file %G$0%g for %_$1%_ %K[%g$2 port $3%K]"), 4, { 0, 0, 0, 1 } },
{ "dcc_send_complete", N_("%gDCC sent file $0 %K[%g%_$1%_kb%K]%g for %_$2%_ in %_$3%_ secs %K[%g%_$4kb/s%_%K]"), 5, { 0, 2, 0, 2, 3 } },
{ "dcc_send_aborted", N_("%gDCC aborted sending file $0 for %_$1%_"), 2, { 0, 0 } },
{ "dcc_get_not_found", N_("%gDCC no file offered by %_$0"), 1, { 0 } },
{ "dcc_get_connected", N_("%gDCC receiving file %G$0%g from %_$1%_ %K[%g$2 port $3%K]"), 4, { 0, 0, 0, 1 } },
{ "dcc_get_complete", N_("%gDCC received file %G$0%g %K[%g$1kb%K]%g from %_$2%_ in %_$3%_ secs %K[%g$4kb/s%K]"), 5, { 0, 2, 0, 2, 3 } },
{ "dcc_get_aborted", N_("%gDCC aborted receiving file $0 from %_$1%_"), 2, { 0, 0 } },
{ "dcc_unknown_ctcp", N_("%gDCC unknown ctcp %G$0%g from %_$1%_ %K[%g$2%K]"), 3, { 0, 0, 0 } },
{ "dcc_unknown_reply", N_("%gDCC unknown reply %G$0%g from %_$1%_ %K[%g$2%K]"), 3, { 0, 0, 0 } },
{ "dcc_unknown_type", N_("%gDCC unknown type %_$0"), 1, { 0 } },
{ "dcc_connect_error", N_("%gDCC can't connect to %_$0%_ port %_$1"), 2, { 0, 1 } },
{ "dcc_cant_create", N_("%gDCC can't create file %G$0%g"), 1, { 0 } },
{ "dcc_rejected", N_("%gDCC %G$0%g was rejected by %_$1%_ %K[%G$2%K]"), 3, { 0, 0, 0 } },
{ "dcc_close", N_("%gDCC %G$0%g close for %_$1%_ %K[%G$2%K]"), 3, { 0, 0, 0 } }
};

View file

@ -0,0 +1,37 @@
#include "printtext.h"
enum {
IRCTXT_MODULE_NAME,
IRCTXT_FILL_1,
IRCTXT_OWN_DCC,
IRCTXT_DCC_MSG,
IRCTXT_ACTION_DCC,
IRCTXT_DCC_CTCP,
IRCTXT_DCC_CHAT,
IRCTXT_DCC_CHAT_NOT_FOUND,
IRCTXT_DCC_CHAT_CONNECTED,
IRCTXT_DCC_CHAT_DISCONNECTED,
IRCTXT_DCC_SEND,
IRCTXT_DCC_SEND_EXISTS,
IRCTXT_DCC_SEND_NOT_FOUND,
IRCTXT_DCC_SEND_FILE_NOT_FOUND,
IRCTXT_DCC_SEND_CONNECTED,
IRCTXT_DCC_SEND_COMPLETE,
IRCTXT_DCC_SEND_ABORTED,
IRCTXT_DCC_GET_NOT_FOUND,
IRCTXT_DCC_GET_CONNECTED,
IRCTXT_DCC_GET_COMPLETE,
IRCTXT_DCC_GET_ABORTED,
IRCTXT_DCC_UNKNOWN_CTCP,
IRCTXT_DCC_UNKNOWN_REPLY,
IRCTXT_DCC_UNKNOWN_TYPE,
IRCTXT_DCC_CONNECT_ERROR,
IRCTXT_DCC_CANT_CREATE,
IRCTXT_DCC_REJECTED,
IRCTXT_DCC_CLOSE,
};
extern FORMAT_REC fecommon_irc_dcc_formats[];
#define MODULE_FORMATS fecommon_irc_dcc_formats

View file

@ -0,0 +1,123 @@
/*
fe-channels.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "modules.h"
#include "signals.h"
#include "commands.h"
#include "levels.h"
#include "irc.h"
#include "channels.h"
#include "windows.h"
#include "window-items.h"
static void signal_channel_created(CHANNEL_REC *channel, gpointer automatic)
{
window_item_create((WI_ITEM_REC *) channel, GPOINTER_TO_INT(automatic));
}
static void signal_channel_created_curwin(CHANNEL_REC *channel)
{
g_return_if_fail(channel != NULL);
window_add_item(active_win, (WI_ITEM_REC *) channel, FALSE);
signal_stop();
}
static void signal_channel_destroyed(CHANNEL_REC *channel)
{
WINDOW_REC *window;
g_return_if_fail(channel != NULL);
window = window_item_window((WI_ITEM_REC *) channel);
if (window != NULL) window_remove_item(window, (WI_ITEM_REC *) channel);
}
static void signal_window_item_removed(WINDOW_REC *window, WI_ITEM_REC *item)
{
CHANNEL_REC *channel;
g_return_if_fail(window != NULL);
channel = irc_item_channel(item);
if (channel != NULL) channel_destroy(channel);
}
static void sig_disconnected(IRC_SERVER_REC *server)
{
WINDOW_REC *window;
GSList *tmp;
g_return_if_fail(server != NULL);
if (!irc_server_check(server))
return;
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *channel = tmp->data;
window = window_item_window((WI_ITEM_REC *) channel);
window->waiting_channels =
g_slist_append(window->waiting_channels, g_strdup_printf("%s %s", server->tag, channel->name));
}
}
static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item)
{
g_return_if_fail(item != NULL);
if (g_slist_length(window->items) > 1 && irc_item_channel(item)) {
printformat(item->server, item->name, MSGLEVEL_CLIENTNOTICE,
IRCTXT_TALKING_IN, item->name);
signal_stop();
}
}
static void cmd_wjoin(const char *data, void *server, WI_ITEM_REC *item)
{
signal_add("channel created", (SIGNAL_FUNC) signal_channel_created_curwin);
signal_emit("command join", 3, data, server, item);
signal_remove("channel created", (SIGNAL_FUNC) signal_channel_created_curwin);
}
void fe_channels_init(void)
{
signal_add("channel created", (SIGNAL_FUNC) signal_channel_created);
signal_add("channel destroyed", (SIGNAL_FUNC) signal_channel_destroyed);
signal_add("window item remove", (SIGNAL_FUNC) signal_window_item_removed);
signal_add_last("window item changed", (SIGNAL_FUNC) signal_window_item_changed);
signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected);
command_bind("wjoin", NULL, (SIGNAL_FUNC) cmd_wjoin);
}
void fe_channels_deinit(void)
{
signal_remove("channel created", (SIGNAL_FUNC) signal_channel_created);
signal_remove("channel destroyed", (SIGNAL_FUNC) signal_channel_destroyed);
signal_remove("window item remove", (SIGNAL_FUNC) signal_window_item_removed);
signal_remove("window item changed", (SIGNAL_FUNC) signal_window_item_changed);
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
command_unbind("wjoin", (SIGNAL_FUNC) cmd_wjoin);
}

View file

@ -0,0 +1,172 @@
/*
fe-common-irc.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "signals.h"
#include "args.h"
#include "misc.h"
#include "lib-config/iconfig.h"
#include "settings.h"
#include "server-setup.h"
#include "completion.h"
void fe_channels_init(void);
void fe_channels_deinit(void);
void fe_irc_commands_init(void);
void fe_irc_commands_deinit(void);
void fe_ctcp_init(void);
void fe_ctcp_deinit(void);
void fe_dcc_init(void);
void fe_dcc_deinit(void);
void fe_events_init(void);
void fe_events_deinit(void);
void fe_events_numeric_init(void);
void fe_events_numeric_deinit(void);
void fe_ignore_init(void);
void fe_ignore_deinit(void);
void fe_query_init(void);
void fe_query_deinit(void);
void irc_nick_hilight_init(void);
void irc_nick_hilight_deinit(void);
void fe_notifylist_init(void);
void fe_notifylist_deinit(void);
void fe_flood_init(void);
void fe_flood_deinit(void);
static char *autocon_server;
static char *autocon_password;
static int autocon_port;
static int no_autoconnect;
static char *cmdline_nick;
static char *cmdline_hostname;
void fe_common_irc_init(void)
{
static struct poptOption options[] = {
{ "connect", 'c', POPT_ARG_STRING, &autocon_server, 0, N_("Automatically connect to server/ircnet"), N_("SERVER") },
{ "password", 'w', POPT_ARG_STRING, &autocon_password, 0, N_("Autoconnect password"), N_("SERVER") },
{ "port", 'p', POPT_ARG_INT, &autocon_port, 0, N_("Autoconnect port"), N_("PORT") },
{ "noconnect", '!', POPT_ARG_NONE, &no_autoconnect, 0, N_("Disable autoconnecting"), NULL },
{ "nick", 'n', POPT_ARG_STRING, &cmdline_nick, 0, N_("Specify nick to use"), NULL },
{ "hostname", 'h', POPT_ARG_STRING, &cmdline_hostname, 0, N_("Specify host name to use"), NULL },
{ NULL, '\0', 0, NULL }
};
autocon_server = NULL;
autocon_password = NULL;
autocon_port = 6667;
no_autoconnect = FALSE;
cmdline_nick = NULL;
cmdline_hostname = NULL;
args_register(options);
settings_add_str("lookandfeel", "beep_on_msg", "");
settings_add_bool("lookandfeel", "beep_when_away", TRUE);
settings_add_bool("lookandfeel", "show_away_once", TRUE);
settings_add_bool("lookandfeel", "show_quit_once", FALSE);
fe_channels_init();
fe_irc_commands_init();
fe_ctcp_init();
fe_dcc_init();
fe_events_init();
fe_events_numeric_init();
fe_ignore_init();
fe_notifylist_init();
fe_flood_init();
fe_query_init();
completion_init();
irc_nick_hilight_init();
}
void fe_common_irc_deinit(void)
{
fe_channels_deinit();
fe_irc_commands_deinit();
fe_ctcp_deinit();
fe_dcc_deinit();
fe_events_deinit();
fe_events_numeric_deinit();
fe_ignore_deinit();
fe_notifylist_deinit();
fe_flood_deinit();
fe_query_deinit();
completion_deinit();
irc_nick_hilight_deinit();
}
void fe_common_irc_finish_init(void)
{
GSList *tmp, *ircnets;
char *str;
if (cmdline_nick != NULL) {
/* override nick found from setup */
iconfig_set_str("settings", "default_nick", cmdline_nick);
}
if (cmdline_hostname != NULL) {
/* override host name found from setup */
iconfig_set_str("settings", "hostname", cmdline_hostname);
}
if (autocon_server != NULL) {
/* connect to specified server */
str = g_strdup_printf(autocon_password == NULL ? "%s %d" : "%s %d %s",
autocon_server, autocon_port, autocon_password);
signal_emit("command connect", 1, str);
g_free(str);
return;
}
if (no_autoconnect) {
/* don't autoconnect */
return;
}
/* connect to autoconnect servers */
ircnets = NULL;
for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
SETUP_SERVER_REC *rec = tmp->data;
if (rec->autoconnect && (*rec->ircnet == '\0' || gslist_find_icase_string(ircnets, rec->ircnet) == NULL)) {
if (*rec->ircnet != '\0')
ircnets = g_slist_append(ircnets, rec->ircnet);
str = g_strdup_printf("%s %d", rec->server, rec->port);
signal_emit("command connect", 1, str);
g_free(str);
}
}
g_slist_free(ircnets);
}

View file

@ -0,0 +1,8 @@
#ifndef __FE_COMMON_IRC_H
#define __FE_COMMON_IRC_H
void fe_common_irc_init(void);
void fe_common_irc_deinit(void);
void fe_common_irc_finish_init(void);
#endif

110
src/fe-common/irc/fe-ctcp.c Normal file
View file

@ -0,0 +1,110 @@
/*
fe-ctcp.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "misc.h"
#include "settings.h"
#include "irc.h"
#include "levels.h"
#include "server.h"
#include "channels.h"
#include "query.h"
#include "ignore.h"
#include "windows.h"
#include "window-items.h"
static void ctcp_print(const char *pre, const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target)
{
char *str;
g_return_if_fail(data != NULL);
str = g_strconcat(pre, " ", data, NULL);
printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
IRCTXT_CTCP_REQUESTED, nick, addr, str, target);
g_free(str);
}
static void ctcp_default_msg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target)
{
return ctcp_print("unknown CTCP", data, server, nick, addr, target);
}
static void ctcp_ping_msg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target)
{
return ctcp_print("CTCP PING", data, server, nick, addr, target);
}
static void ctcp_version_msg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target)
{
return ctcp_print("CTCP VERSION", data, server, nick, addr, target);
}
static void ctcp_default_reply(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target)
{
char *ptr, *str;
g_return_if_fail(data != NULL);
str = g_strdup(data);
ptr = strchr(str, ' ');
if (ptr != NULL) *ptr++ = '\0'; else ptr = "";
printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
IRCTXT_CTCP_REPLY, str, nick, ptr);
g_free(str);
}
static void ctcp_ping_reply(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target)
{
GTimeVal tv, tv2;
long usecs;
g_return_if_fail(data != NULL);
if (sscanf(data, "%ld %ld", &tv2.tv_sec, &tv2.tv_usec) != 2)
return;
g_get_current_time(&tv);
usecs = get_timeval_diff(&tv, &tv2);
printformat(server, ischannel(*target) ? target : nick, MSGLEVEL_CTCPS,
IRCTXT_CTCP_PING_REPLY, nick, usecs/1000, usecs%1000);
}
void fe_ctcp_init(void)
{
signal_add("default ctcp msg", (SIGNAL_FUNC) ctcp_default_msg);
signal_add("ctcp msg ping", (SIGNAL_FUNC) ctcp_ping_msg);
signal_add("ctcp msg version", (SIGNAL_FUNC) ctcp_version_msg);
signal_add("default ctcp reply", (SIGNAL_FUNC) ctcp_default_reply);
signal_add("ctcp reply ping", (SIGNAL_FUNC) ctcp_ping_reply);
}
void fe_ctcp_deinit(void)
{
signal_remove("default ctcp msg", (SIGNAL_FUNC) ctcp_default_msg);
signal_remove("ctcp msg ping", (SIGNAL_FUNC) ctcp_ping_msg);
signal_remove("ctcp msg version", (SIGNAL_FUNC) ctcp_version_msg);
signal_remove("default ctcp reply", (SIGNAL_FUNC) ctcp_default_reply);
signal_remove("ctcp reply ping", (SIGNAL_FUNC) ctcp_ping_reply);
}

View file

@ -0,0 +1,707 @@
/*
fe-events-numeric.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "settings.h"
#include "irc.h"
#include "levels.h"
#include "server.h"
#include "channels.h"
#include "nicklist.h"
static char *last_away_nick = NULL;
static char *last_away_msg = NULL;
static void event_user_mode(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *mode;
g_return_if_fail(data != NULL);
g_return_if_fail(server != NULL);
params = event_get_params(data, 2, NULL, &mode);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_USER_MODE, mode);
g_free(params);
}
static void event_ison(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *online;
g_return_if_fail(data != NULL);
g_return_if_fail(server != NULL);
params = event_get_params(data, 2, NULL, &online);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_ONLINE, online);
g_free(params);
}
static void event_names_list(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel, *names;
g_return_if_fail(data != NULL);
params = event_get_params(data, 4, NULL, NULL, &channel, &names);
if (channel_find(server, channel) == NULL)
printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_NAMES, channel, names);
g_free(params);
}
static void display_sorted_nicks(CHANNEL_REC *channel, GSList *nicklist, gint items, gint max)
{
NICK_REC *rec, *last;
GString *str;
GSList *tmp;
gint lines, cols, line, col, skip;
gchar *linebuf;
max++; /* op/voice */
str = g_string_new(NULL);
cols = max > 65 ? 1 : (65 / (max+3)); /* "[] " */
lines = items <= cols ? 1 : items / cols+1;
last = NULL; linebuf = g_malloc(max+1); linebuf[max] = '\0';
for (line = 0, col = 0, skip = 1, tmp = nicklist; line < lines; last = rec, tmp = tmp->next)
{
rec = tmp->data;
if (--skip == 0)
{
skip = lines;
memset(linebuf, ' ', max);
linebuf[0] = rec->op ? '@' : rec->voice ? '+' : ' ';
memcpy(linebuf+1, rec->nick, strlen(rec->nick));
g_string_sprintfa(str, "%%K[%%n%%_%c%%_%s%%K] ", linebuf[0], linebuf+1);
cols++;
}
if (col == cols || tmp->next == NULL)
{
printtext(channel->server, channel->name, MSGLEVEL_CLIENTCRAP, str->str);
g_string_truncate(str, 0);
col = 0; line++;
tmp = g_slist_nth(nicklist, line-1); skip = 1;
}
}
if (str->len != 0)
printtext(channel->server, channel->name, MSGLEVEL_CLIENTCRAP, str->str);
g_string_free(str, TRUE);
g_free(linebuf);
}
static void display_nicks(CHANNEL_REC *channel)
{
NICK_REC *nick;
GSList *tmp, *nicklist, *sorted;
gint nicks, normal, voices, ops, len, max;
nicks = normal = voices = ops = 0;
nicklist = nicklist_getnicks(channel);
sorted = NULL;
/* sort the nicklist */
max = 0;
for (tmp = nicklist; tmp != NULL; tmp = tmp->next)
{
nick = tmp->data;
sorted = g_slist_insert_sorted(sorted, nick, (GCompareFunc) nicklist_compare);
if (nick->op)
ops++;
else if (nick->voice)
voices++;
else
normal++;
nicks++;
len = strlen(nick->nick);
if (len > max) max = len;
}
g_slist_free(nicklist);
/* display the nicks */
printformat(channel->server, channel->name, MSGLEVEL_CRAP, IRCTXT_NAMES, channel->name, "");
display_sorted_nicks(channel, sorted, nicks, max);
g_slist_free(sorted);
printformat(channel->server, channel->name, MSGLEVEL_CRAP, IRCTXT_ENDOFNAMES,
channel->name, nicks, ops, voices, normal);
}
static void event_end_of_names(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel;
CHANNEL_REC *chanrec;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &channel);
chanrec = channel_find(server, channel);
if (chanrec == NULL)
printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_ENDOFNAMES, channel, 0, 0, 0, 0);
else
display_nicks(chanrec);
g_free(params);
}
static void event_who(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick, *channel, *user, *host, *stat, *realname, *hops;
g_return_if_fail(data != NULL);
params = event_get_params(data, 8, NULL, &channel, &user, &host, NULL, &nick, &stat, &realname);
/* split hops/realname */
hops = realname;
while (*realname != '\0' && *realname != ' ') realname++;
while (*realname == ' ') realname++;
if (realname > hops) realname[-1] = '\0';
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHO,
channel, nick, stat, hops, user, host, realname);
g_free(params);
}
static void event_end_of_who(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &channel);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_END_OF_WHO, channel);
g_free(params);
}
static void event_ban_list(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel, *ban, *setby, *tims;
glong secs, tim;
g_return_if_fail(data != NULL);
params = event_get_params(data, 5, NULL, &channel, &ban, &setby, &tims);
if (sscanf(tims, "%ld", &tim) != 1) tim = (glong) time(NULL);
secs = (glong) time(NULL)-tim;
printformat(server, channel, MSGLEVEL_CRAP,
*setby == '\0' ? IRCTXT_BANLIST : IRCTXT_BANLIST_LONG,
channel, ban, setby, secs);
g_free(params);
}
static void event_eban_list(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel, *ban, *setby, *tims;
glong secs, tim;
g_return_if_fail(data != NULL);
params = event_get_params(data, 5, NULL, &channel, &ban, &setby, &tims);
if (sscanf(tims, "%ld", &tim) != 1) tim = (glong) time(NULL);
secs = (glong) time(NULL)-tim;
printformat(server, channel, MSGLEVEL_CRAP,
*setby == '\0' ? IRCTXT_EBANLIST : IRCTXT_EBANLIST_LONG,
channel, ban, setby, secs);
g_free(params);
}
static void event_invite_list(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel, *invite;
g_return_if_fail(data != NULL);
params = event_get_params(data, 3, NULL, &channel, &invite);
printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_INVITELIST, channel, invite);
g_free(params);
}
static void event_nick_in_use(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &nick);
if (server->connected)
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NICK_IN_USE, nick);
g_free(params);
}
static void event_topic_get(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel, *topic;
g_return_if_fail(data != NULL);
params = event_get_params(data, 3, NULL, &channel, &topic);
printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_TOPIC, channel, topic);
g_free(params);
}
static void event_topic_info(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *timestr, *channel, *topicby, *topictime;
glong ltime;
time_t t;
struct tm *tim;
g_return_if_fail(data != NULL);
params = event_get_params(data, 4, NULL, &channel, &topicby, &topictime);
if (sscanf(topictime, "%lu", &ltime) != 1) ltime = 0; /* topic set date */
t = (time_t) ltime;
tim = localtime(&t);
timestr = g_strdup(asctime(tim));
if (timestr[strlen(timestr)-1] == '\n') timestr[strlen(timestr)-1] = '\0';
printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_TOPIC_INFO, topicby, timestr);
g_free(timestr);
g_free(params);
}
static void event_channel_mode(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel, *mode;
g_return_if_fail(data != NULL);
params = event_get_params(data, 3 | PARAM_FLAG_GETREST, NULL, &channel, &mode);
printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_CHANNEL_MODE, channel, mode);
g_free(params);
}
static void event_channel_created(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel, *times, *timestr;
glong timeval;
time_t t;
struct tm *tim;
g_return_if_fail(data != NULL);
params = event_get_params(data, 3, NULL, &channel, &times);
if (sscanf(times, "%ld", &timeval) != 1) timeval = 0;
t = (time_t) timeval;
tim = localtime(&t);
timestr = g_strdup(asctime(tim));
if (timestr[strlen(timestr)-1] == '\n') timestr[strlen(timestr)-1] = '\0';
printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_CHANNEL_CREATED, channel, timestr);
g_free(timestr);
g_free(params);
}
static void event_away(gchar *data, IRC_SERVER_REC *server)
{
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_AWAY);
}
static void event_unaway(gchar *data, IRC_SERVER_REC *server)
{
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_UNAWAY);
}
static void event_userhost(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *hosts;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &hosts);
printtext(server, NULL, MSGLEVEL_CRAP, "%s", hosts);
g_free(params);
}
static void event_whois(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick, *user, *host, *realname;
g_return_if_fail(data != NULL);
params = event_get_params(data, 6, NULL, &nick, &user, &host, NULL, &realname);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS, nick, user, host, realname);
g_free(params);
}
static void event_whois_idle(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick, *secstr, *signon, *rest;
glong secs, lsignon;
gint h, m, s;
g_return_if_fail(data != NULL);
params = event_get_params(data, 5 | PARAM_FLAG_GETREST, NULL, &nick, &secstr, &signon, &rest);
if (sscanf(secstr, "%ld", &secs) == 0) secs = 0;
lsignon = 0;
if (strstr(rest, ", signon time") != NULL)
sscanf(signon, "%ld", &lsignon);
h = secs/3600; m = (secs%3600)/60; s = secs%60;
if (lsignon == 0)
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_IDLE, nick, h, m, s);
else
{
gchar *timestr;
struct tm *tim;
time_t t;
t = (time_t) lsignon;
tim = localtime(&t);
timestr = g_strdup(asctime(tim));
if (timestr[strlen(timestr)-1] == '\n') timestr[strlen(timestr)-1] = '\0';
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_IDLE_SIGNON, nick, h, m, s, timestr);
g_free(timestr);
}
g_free(params);
}
static void event_whois_server(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick, *whoserver, *desc;
g_return_if_fail(data != NULL);
params = event_get_params(data, 4, NULL, &nick, &whoserver, &desc);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_SERVER, nick, whoserver, desc);
g_free(params);
}
static void event_whois_oper(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &nick);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_OPER, nick);
g_free(params);
}
static void event_whois_channels(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick, *chans;
GString *str;
g_return_if_fail(data != NULL);
params = event_get_params(data, 3, NULL, &nick, &chans);
str = g_string_new(NULL);
for (; *chans != '\0'; chans++)
{
if ((unsigned char) *chans >= 32)
g_string_append_c(str, *chans);
else
{
g_string_append_c(str, '^');
g_string_append_c(str, *chans+'A'-1);
}
}
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_WHOIS_CHANNELS, nick, str->str);
g_free(params);
g_string_free(str, TRUE);
}
static void event_whois_away(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick, *awaymsg;
g_return_if_fail(data != NULL);
params = event_get_params(data, 3, NULL, &nick, &awaymsg);
if (server->whois_coming || !settings_get_bool("show_away_once") ||
last_away_nick == NULL || g_strcasecmp(last_away_nick, nick) != 0 ||
last_away_msg == NULL || g_strcasecmp(last_away_msg, awaymsg) != 0) {
/* don't show the same away message from the same nick all the time */
g_free_not_null(last_away_nick);
g_free_not_null(last_away_msg);
last_away_nick = g_strdup(nick);
last_away_msg = g_strdup(awaymsg);
printformat(server, NULL, MSGLEVEL_CRAP, server->whois_coming ?
IRCTXT_WHOIS_AWAY : IRCTXT_NICK_AWAY, nick, awaymsg);
}
g_free(params);
}
static void event_end_of_whois(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &nick);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_END_OF_WHOIS, nick);
g_free(params);
}
static void event_target_unavailable(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &channel);
if (!ischannel(*channel))
{
/* nick unavailable */
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NICK_UNAVAILABLE, channel);
}
else
{
/* channel is unavailable. */
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_JOINERROR_UNAVAIL, channel);
}
g_free(params);
}
static void event_no_such_nick(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &nick);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NO_SUCH_NICK, nick);
g_free(params);
}
static void event_no_such_channel(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &channel);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NO_SUCH_CHANNEL, channel);
g_free(params);
}
static void cannot_join(gchar *data, IRC_SERVER_REC *server, gint format)
{
gchar *params, *channel;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &channel);
printformat(server, NULL, MSGLEVEL_CRAP, format, channel);
g_free(params);
}
static void event_too_many_channels(gchar *data, IRC_SERVER_REC *server)
{
cannot_join(data, server, IRCTXT_JOINERROR_TOOMANY);
}
static void event_channel_is_full(gchar *data, IRC_SERVER_REC *server)
{
cannot_join(data, server, IRCTXT_JOINERROR_FULL);
}
static void event_invite_only(gchar *data, IRC_SERVER_REC *server)
{
cannot_join(data, server, IRCTXT_JOINERROR_INVITE);
}
static void event_banned(gchar *data, IRC_SERVER_REC *server)
{
cannot_join(data, server, IRCTXT_JOINERROR_BANNED);
}
static void event_bad_channel_key(gchar *data, IRC_SERVER_REC *server)
{
cannot_join(data, server, IRCTXT_JOINERROR_BAD_KEY);
}
static void event_bad_channel_mask(gchar *data, IRC_SERVER_REC *server)
{
cannot_join(data, server, IRCTXT_JOINERROR_BAD_MASK);
}
static void event_unknown_mode(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *mode;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &mode);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_UNKNOWN_MODE, mode);
g_free(params);
}
static void event_not_chanop(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *channel;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &channel);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_NOT_CHANOP, channel);
g_free(params);
}
static void event_received(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr)
{
gchar *params, *args, *ptr;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, NULL, &args);
ptr = strstr(args, " :");
if (ptr != NULL) *(ptr+1) = ' ';
printtext(server, NULL, MSGLEVEL_CRAP, "%s", args);
g_free(params);
}
static void event_motd(gchar *data, SERVER_REC *server, gchar *nick, gchar *addr)
{
/* numeric event. */
gchar *params, *args, *ptr;
if (settings_get_bool("toggle_skip_motd"))
return;
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, NULL, &args);
ptr = strstr(args, " :");
if (ptr != NULL) *(ptr+1) = ' ';
printtext(server, NULL, MSGLEVEL_CRAP, "%s", args);
g_free(params);
}
void fe_events_numeric_init(void)
{
last_away_nick = NULL;
last_away_msg = NULL;
signal_add("event 221", (SIGNAL_FUNC) event_user_mode);
signal_add("event 303", (SIGNAL_FUNC) event_ison);
signal_add("event 353", (SIGNAL_FUNC) event_names_list);
signal_add("event 366", (SIGNAL_FUNC) event_end_of_names);
signal_add("event 352", (SIGNAL_FUNC) event_who);
signal_add("event 315", (SIGNAL_FUNC) event_end_of_who);
signal_add("event 367", (SIGNAL_FUNC) event_ban_list);
signal_add("event 348", (SIGNAL_FUNC) event_eban_list);
signal_add("event 346", (SIGNAL_FUNC) event_invite_list);
signal_add("event 433", (SIGNAL_FUNC) event_nick_in_use);
signal_add("event 332", (SIGNAL_FUNC) event_topic_get);
signal_add("event 333", (SIGNAL_FUNC) event_topic_info);
signal_add("event 324", (SIGNAL_FUNC) event_channel_mode);
signal_add("event 329", (SIGNAL_FUNC) event_channel_created);
signal_add("event 306", (SIGNAL_FUNC) event_away);
signal_add("event 305", (SIGNAL_FUNC) event_unaway);
signal_add("event 311", (SIGNAL_FUNC) event_whois);
signal_add("event 301", (SIGNAL_FUNC) event_whois_away);
signal_add("event 312", (SIGNAL_FUNC) event_whois_server);
signal_add("event 313", (SIGNAL_FUNC) event_whois_oper);
signal_add("event 317", (SIGNAL_FUNC) event_whois_idle);
signal_add("event 318", (SIGNAL_FUNC) event_end_of_whois);
signal_add("event 319", (SIGNAL_FUNC) event_whois_channels);
signal_add("event 302", (SIGNAL_FUNC) event_userhost);
signal_add("event 437", (SIGNAL_FUNC) event_target_unavailable);
signal_add("event 401", (SIGNAL_FUNC) event_no_such_nick);
signal_add("event 403", (SIGNAL_FUNC) event_no_such_channel);
signal_add("event 405", (SIGNAL_FUNC) event_too_many_channels);
signal_add("event 471", (SIGNAL_FUNC) event_channel_is_full);
signal_add("event 472", (SIGNAL_FUNC) event_unknown_mode);
signal_add("event 473", (SIGNAL_FUNC) event_invite_only);
signal_add("event 474", (SIGNAL_FUNC) event_banned);
signal_add("event 475", (SIGNAL_FUNC) event_bad_channel_key);
signal_add("event 476", (SIGNAL_FUNC) event_bad_channel_mask);
signal_add("event 482", (SIGNAL_FUNC) event_not_chanop);
signal_add("event 375", (SIGNAL_FUNC) event_motd);
signal_add("event 376", (SIGNAL_FUNC) event_motd);
signal_add("event 372", (SIGNAL_FUNC) event_motd);
signal_add("event 004", (SIGNAL_FUNC) event_received);
signal_add("event 364", (SIGNAL_FUNC) event_received);
signal_add("event 365", (SIGNAL_FUNC) event_received);
}
void fe_events_numeric_deinit(void)
{
g_free_not_null(last_away_nick);
g_free_not_null(last_away_msg);
signal_remove("event 221", (SIGNAL_FUNC) event_user_mode);
signal_remove("event 303", (SIGNAL_FUNC) event_ison);
signal_remove("event 353", (SIGNAL_FUNC) event_names_list);
signal_remove("event 366", (SIGNAL_FUNC) event_end_of_names);
signal_remove("event 352", (SIGNAL_FUNC) event_who);
signal_remove("event 315", (SIGNAL_FUNC) event_end_of_who);
signal_remove("event 367", (SIGNAL_FUNC) event_ban_list);
signal_remove("event 348", (SIGNAL_FUNC) event_eban_list);
signal_remove("event 346", (SIGNAL_FUNC) event_invite_list);
signal_remove("event 433", (SIGNAL_FUNC) event_nick_in_use);
signal_remove("event 332", (SIGNAL_FUNC) event_topic_get);
signal_remove("event 333", (SIGNAL_FUNC) event_topic_info);
signal_remove("event 324", (SIGNAL_FUNC) event_channel_mode);
signal_remove("event 329", (SIGNAL_FUNC) event_channel_created);
signal_remove("event 306", (SIGNAL_FUNC) event_away);
signal_remove("event 305", (SIGNAL_FUNC) event_unaway);
signal_remove("event 311", (SIGNAL_FUNC) event_whois);
signal_remove("event 301", (SIGNAL_FUNC) event_whois_away);
signal_remove("event 312", (SIGNAL_FUNC) event_whois_server);
signal_remove("event 313", (SIGNAL_FUNC) event_whois_oper);
signal_remove("event 317", (SIGNAL_FUNC) event_whois_idle);
signal_remove("event 318", (SIGNAL_FUNC) event_end_of_whois);
signal_remove("event 319", (SIGNAL_FUNC) event_whois_channels);
signal_remove("event 302", (SIGNAL_FUNC) event_userhost);
signal_remove("event 437", (SIGNAL_FUNC) event_target_unavailable);
signal_remove("event 401", (SIGNAL_FUNC) event_no_such_nick);
signal_remove("event 403", (SIGNAL_FUNC) event_no_such_channel);
signal_remove("event 405", (SIGNAL_FUNC) event_too_many_channels);
signal_remove("event 471", (SIGNAL_FUNC) event_channel_is_full);
signal_remove("event 472", (SIGNAL_FUNC) event_unknown_mode);
signal_remove("event 473", (SIGNAL_FUNC) event_invite_only);
signal_remove("event 474", (SIGNAL_FUNC) event_banned);
signal_remove("event 475", (SIGNAL_FUNC) event_bad_channel_key);
signal_remove("event 476", (SIGNAL_FUNC) event_bad_channel_mask);
signal_remove("event 482", (SIGNAL_FUNC) event_not_chanop);
signal_remove("event 375", (SIGNAL_FUNC) event_motd);
signal_remove("event 376", (SIGNAL_FUNC) event_motd);
signal_remove("event 372", (SIGNAL_FUNC) event_motd);
signal_remove("event 004", (SIGNAL_FUNC) event_received);
signal_remove("event 364", (SIGNAL_FUNC) event_received);
signal_remove("event 365", (SIGNAL_FUNC) event_received);
}

View file

@ -0,0 +1,682 @@
/*
fe-events.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "settings.h"
#include "irc.h"
#include "levels.h"
#include "server.h"
#include "server-redirect.h"
#include "server-reconnect.h"
#include "channels.h"
#include "query.h"
#include "nicklist.h"
#include "ignore.h"
#include "irc-hilight-text.h"
#include "windows.h"
#include "completion.h"
static int beep_msg_level, beep_when_away;
static void msg_beep_check(IRC_SERVER_REC *server, int level)
{
if (level != 0 && (beep_msg_level & level) &&
(!server->usermode_away || beep_when_away)) {
printbeep();
}
}
static void event_privmsg(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr)
{
CHANNEL_REC *chanrec;
WI_ITEM_REC *item;
gchar *params, *target, *msg, *nickmode;
int level;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
if (nick == NULL) nick = server->real_address;
level = 0;
if (*msg == 1)
{
/* ctcp message, handled in fe-ctcp.c */
}
else if (ignore_check(server, nick, addr, target, msg,
ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS))
{
/* ignored */
}
else if (ischannel(*target))
{
/* message to some channel */
WINDOW_REC *window;
NICK_REC *nickrec;
gboolean toyou;
gchar *color;
chanrec = channel_find(server, target);
toyou = completion_msgtoyou((SERVER_REC *) server, msg);
color = irc_hilight_find_nick(target, nick, addr);
nickrec = chanrec == NULL ? NULL : nicklist_find(chanrec, nick);
nickmode = !settings_get_bool("toggle_show_nickmode") || nickrec == NULL ? "" :
nickrec->op ? "@" : nickrec->voice ? "+" : " ";
window = chanrec == NULL ? NULL : window_item_window((WI_ITEM_REC *) chanrec);
if (window != NULL && window->active == (WI_ITEM_REC *) chanrec)
{
/* message to active channel in window */
if (color != NULL)
{
/* highlighted nick */
printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT,
IRCTXT_PUBMSG_HILIGHT, color, nick, msg, nickmode);
}
else
{
printformat(server, target, MSGLEVEL_PUBLIC | (toyou ? MSGLEVEL_NOHILIGHT : 0),
toyou ? IRCTXT_PUBMSG_ME : IRCTXT_PUBMSG, nick, msg, nickmode);
}
}
else
{
/* message to not existing/active channel */
if (color != NULL)
{
/* highlighted nick */
printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT,
IRCTXT_PUBMSG_HILIGHT_CHANNEL, color, nick, target, msg, nickmode);
}
else
{
printformat(server, target, MSGLEVEL_PUBLIC | (toyou ? MSGLEVEL_NOHILIGHT : 0),
toyou ? IRCTXT_PUBMSG_ME_CHANNEL : IRCTXT_PUBMSG_CHANNEL,
nick, target, msg, nickmode);
}
}
g_free_not_null(color);
level = MSGLEVEL_PUBLIC;
}
else
{
/* private message */
if (settings_get_bool("toggle_autocreate_query") && query_find(server, nick) == NULL)
item = (WI_ITEM_REC *) query_create(server, nick, TRUE);
else
item = (WI_ITEM_REC *) query_find(server, nick);
printformat(server, nick, MSGLEVEL_MSGS,
item == NULL ? IRCTXT_MSG_PRIVATE : IRCTXT_MSG_PRIVATE_QUERY, nick, addr == NULL ? "" : addr, msg);
level = MSGLEVEL_MSGS;
}
msg_beep_check(server, level);
g_free(params);
}
/* we use "ctcp msg" here because "ctcp msg action" can be ignored with
/IGNORE * CTCPS */
static void ctcp_action_msg(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr, gchar *target)
{
WINDOW_REC *window;
CHANNEL_REC *channel;
WI_ITEM_REC *item;
int level;
g_return_if_fail(data != NULL);
if (g_strncasecmp(data, "ACTION ", 7) != 0)
return;
data += 7;
level = 0;
if (ignore_check(server, nick, addr, target, data, MSGLEVEL_ACTIONS))
{
/* ignored */
}
else if (ischannel(*target))
{
/* channel action */
channel = channel_find(server, target);
window = channel == NULL ? NULL : window_item_window((WI_ITEM_REC *) channel);
if (window != NULL && window->active == (WI_ITEM_REC *) channel)
{
/* message to active channel in window */
printformat(server, target, MSGLEVEL_ACTIONS,
IRCTXT_ACTION_PUBLIC, nick, data);
}
else
{
/* message to not existing/active channel */
printformat(server, target, MSGLEVEL_ACTIONS,
IRCTXT_ACTION_PUBLIC_CHANNEL, nick, target, data);
}
level = MSGLEVEL_PUBLIC;
}
else
{
/* private action */
if (settings_get_bool("toggle_autocreate_query") && query_find(server, nick) == NULL)
item = (WI_ITEM_REC *) query_create(server, nick, TRUE);
else
item = (WI_ITEM_REC *) channel_find(server, nick);
printformat(server, nick, MSGLEVEL_ACTIONS,
item == NULL ? IRCTXT_ACTION_PRIVATE : IRCTXT_ACTION_PRIVATE_QUERY, nick, addr == NULL ? "" : addr, data);
level = MSGLEVEL_MSGS;
}
msg_beep_check(server, level);
}
static void event_notice(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr)
{
char *params, *target, *msg;
int level;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
if (nick == NULL) nick = server->real_address;
level = 0;
if (*msg == 1)
{
/* ctcp reply */
}
else if (addr == NULL)
{
/* notice from server */
if (nick == NULL || !ignore_check(server, nick, "", target, msg, MSGLEVEL_SNOTES))
printformat(server, target, MSGLEVEL_SNOTES, IRCTXT_NOTICE_SERVER, nick == NULL ? "" : nick, msg);
}
else if (ischannel(*target) || (*target == '@' && ischannel(target[1])))
{
/* notice in some channel */
if (!ignore_check(server, nick, addr, target, msg, MSGLEVEL_NOTICES))
printformat(server, target, MSGLEVEL_NOTICES,
*target == '@' ? IRCTXT_NOTICE_PUBLIC_OPS : IRCTXT_NOTICE_PUBLIC,
nick, *target == '@' ? target+1 : target, msg);
level = MSGLEVEL_NOTICES;
}
else
{
/* private notice */
if (!ignore_check(server, nick, addr, NULL, msg, MSGLEVEL_NOTICES))
printformat(server, nick, MSGLEVEL_NOTICES, IRCTXT_NOTICE_PRIVATE, nick, addr, msg);
level = MSGLEVEL_NOTICES;
}
msg_beep_check(server, level);
g_free(params);
}
static void event_join(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr)
{
gchar *params, *channel, *tmp;
g_return_if_fail(data != NULL);
params = event_get_params(data, 1, &channel);
tmp = strchr(channel, 7); /* ^G does something weird.. */
if (tmp != NULL) *tmp = '\0';
if (!ignore_check(server, nick, addr, channel, NULL, MSGLEVEL_JOINS))
printformat(server, channel, MSGLEVEL_JOINS, IRCTXT_JOIN, nick, addr, channel);
g_free(params);
}
static void event_part(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr)
{
gchar *params, *channel, *reason;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &reason);
if (!ignore_check(server, nick, addr, channel, NULL, MSGLEVEL_PARTS))
printformat(server, channel, MSGLEVEL_PARTS, IRCTXT_PART, nick, addr, channel, reason);
g_free(params);
}
static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr)
{
GString *chans;
GSList *tmp;
int once;
g_return_if_fail(data != NULL);
if (ignore_check(server, nick, addr, NULL, NULL, MSGLEVEL_QUITS))
return;
if (*data == ':') data++; /* quit message */
once = settings_get_bool("show_quit_once");
chans = !once ? NULL : g_string_new(NULL);
for (tmp = channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *rec = tmp->data;
if (rec->server == server && nicklist_find(rec, nick) &&
!ignore_check(server, nick, addr, rec->name, data, MSGLEVEL_QUITS)) {
if (once)
g_string_sprintfa(chans, "%s,", rec->name);
else
printformat(server, rec->name, MSGLEVEL_QUITS, IRCTXT_QUIT, nick, addr, data);
}
}
if (once) {
g_string_truncate(chans, chans->len-1);
printformat(server, NULL, MSGLEVEL_QUITS,
chans->len == 0 ? IRCTXT_QUIT : IRCTXT_QUIT_ONCE,
nick, addr, data, chans->str);
g_string_free(chans, TRUE);
}
}
static void event_kick(gchar *data, IRC_SERVER_REC *server, gchar *kicker, gchar *addr)
{
gchar *params, *channel, *nick, *reason;
g_return_if_fail(data != NULL);
params = event_get_params(data, 3 | PARAM_FLAG_GETREST, &channel, &nick, &reason);
if (!ignore_check(server, kicker, addr, channel, reason, MSGLEVEL_KICKS))
{
printformat(server, channel, MSGLEVEL_KICKS,
IRCTXT_KICK, nick, channel, kicker, reason);
}
g_free(params);
}
static void print_nick_change(IRC_SERVER_REC *server, const char *target, const char *newnick, const char *oldnick, const char *addr, int ownnick)
{
if (ignore_check(server, oldnick, addr, target, newnick, MSGLEVEL_NICKS))
return;
if (ownnick)
printformat(server, target, MSGLEVEL_NICKS, IRCTXT_YOUR_NICK_CHANGED, newnick);
else
printformat(server, target, MSGLEVEL_NICKS, IRCTXT_NICK_CHANGED, oldnick, newnick);
}
static void event_nick(gchar *data, IRC_SERVER_REC *server, gchar *sender, gchar *addr)
{
GSList *tmp;
char *params, *newnick;
int ownnick, msgprint;
g_return_if_fail(data != NULL);
if (ignore_check(server, sender, addr, NULL, NULL, MSGLEVEL_NICKS))
return;
params = event_get_params(data, 1, &newnick);
msgprint = FALSE;
ownnick = g_strcasecmp(sender, server->nick) == 0;
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *channel = tmp->data;
if (nicklist_find(channel, sender)) {
print_nick_change(server, channel->name, newnick, sender, addr, ownnick);
msgprint = TRUE;
}
}
for (tmp = server->queries; tmp != NULL; tmp = tmp->next) {
QUERY_REC *query = tmp->data;
if (g_strcasecmp(query->nick, sender) == 0) {
print_nick_change(server, query->nick, newnick, sender, addr, ownnick);
msgprint = TRUE;
}
}
if (!msgprint && ownnick)
printformat(server, NULL, MSGLEVEL_NICKS, IRCTXT_YOUR_NICK_CHANGED, newnick);
g_free(params);
}
static void event_mode(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr)
{
char *params, *channel, *mode;
g_return_if_fail(data != NULL);
if (nick == NULL) nick = server->real_address;
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &mode);
if (ignore_check(server, nick, addr, channel, mode, MSGLEVEL_MODES)) {
g_free(params);
return;
}
if (!ischannel(*channel)) {
/* user mode change */
printformat(server, NULL, MSGLEVEL_MODES, IRCTXT_USERMODE_CHANGE, mode, channel);
} else if (addr == NULL) {
/* channel mode changed by server */
printformat(server, channel, MSGLEVEL_MODES,
IRCTXT_SERVER_CHANMODE_CHANGE, channel, mode, nick);
} else {
/* channel mode changed by normal user */
printformat(server, channel, MSGLEVEL_MODES,
IRCTXT_CHANMODE_CHANGE, channel, mode, nick);
}
g_free(params);
}
static void event_pong(const char *data, IRC_SERVER_REC *server, const char *nick)
{
char *params, *host, *reply;
g_return_if_fail(data != NULL);
if (nick == NULL) nick = server->real_address;
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &host, &reply);
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_PONG, host, reply);
g_free(params);
}
static void event_invite(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr)
{
gchar *params, *channel;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2, NULL, &channel);
if (*channel != '\0' && !ignore_check(server, nick, addr, channel, NULL, MSGLEVEL_INVITES))
printformat(server, NULL, MSGLEVEL_INVITES, IRCTXT_INVITE, nick, channel);
g_free(params);
}
static void event_topic(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr)
{
gchar *params, *channel, *topic;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &topic);
if (!ignore_check(server, nick, addr, channel, topic, MSGLEVEL_TOPICS))
printformat(server, channel, MSGLEVEL_TOPICS,
*topic != '\0' ? IRCTXT_NEW_TOPIC : IRCTXT_TOPIC_UNSET,
nick, channel, topic);
g_free(params);
}
static void event_error(gchar *data, IRC_SERVER_REC *server)
{
g_return_if_fail(data != NULL);
if (*data == ':') data++;
printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_ERROR, data);
}
static void event_wallops(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr)
{
g_return_if_fail(data != NULL);
if (*data == ':') data++;
if (!ignore_check(server, nick, addr, NULL, data, MSGLEVEL_WALLOPS))
{
if (g_strncasecmp(data, "\001ACTION", 7) != 0)
printformat(server, NULL, MSGLEVEL_WALLOPS, IRCTXT_WALLOPS, nick, data);
else
{
/* Action in WALLOP */
gint len;
data = g_strdup(data);
len = strlen(data);
if (data[len-1] == 1) data[len-1] = '\0';
printformat(server, NULL, MSGLEVEL_WALLOPS, IRCTXT_ACTION_WALLOPS, nick, data);
g_free(data);
}
msg_beep_check(server, MSGLEVEL_WALLOPS);
}
}
static void channel_sync(CHANNEL_REC *channel)
{
g_return_if_fail(channel != NULL);
printformat(channel->server, channel->name, MSGLEVEL_CLIENTNOTICE|MSGLEVEL_NO_ACT, IRCTXT_CHANNEL_SYNCED,
channel->name, (glong) (time(NULL)-channel->createtime));
}
static void event_connected(IRC_SERVER_REC *server)
{
gchar *str;
g_return_if_fail(server != NULL);
if (*settings_get_str("default_nick") == '\0' ||
g_strcasecmp(server->nick, settings_get_str("default_nick")) == 0)
return;
/* someone has our nick, find out who. */
str = g_strdup_printf("WHOIS %s", settings_get_str("default_nick"));
irc_send_cmd(server, str);
g_free(str);
server_redirect_event((SERVER_REC *) server, settings_get_str("default_nick"), 1,
"event 318", "event empty", 1,
"event 401", "event empty", 1,
"event 311", "nickfind event whois", 1,
"event 301", "event empty", 1,
"event 312", "event empty", 1,
"event 313", "event empty", 1,
"event 317", "event empty", 1,
"event 319", "event empty", 1, NULL);
}
static void event_nickfind_whois(gchar *data, IRC_SERVER_REC *server)
{
gchar *params, *nick, *user, *host, *realname;
g_return_if_fail(data != NULL);
params = event_get_params(data, 6, NULL, &nick, &user, &host, NULL, &realname);
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_YOUR_NICK_OWNED, nick, user, host, realname);
g_free(params);
}
static void event_ban_type_changed(gchar *bantype)
{
GString *str;
g_return_if_fail(bantype != NULL);
if (strcmp(bantype, "UD") == 0)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_BANTYPE, "Normal");
else if (strcmp(bantype, "HD") == 0 || strcmp(bantype, "H") == 0)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_BANTYPE, "Host");
else if (strcmp(bantype, "D") == 0)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_BANTYPE, "Domain");
else
{
str = g_string_new("Custom:");
if (*bantype == 'N')
{
g_string_append(str, " Nick");
bantype++;
}
if (*bantype == 'U')
{
g_string_append(str, " User");
bantype++;
}
if (*bantype == 'H')
{
g_string_append(str, " Host");
bantype++;
}
if (*bantype == 'D')
g_string_append(str, " Domain");
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_BANTYPE, str->str);
g_string_free(str, TRUE);
}
}
/*FIXME: move to core
static void event_perl_error(gchar *text)
{
printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_PERL_ERROR, text);
}*/
static void sig_server_lag_disconnected(IRC_SERVER_REC *server)
{
g_return_if_fail(server != NULL);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
IRCTXT_LAG_DISCONNECTED, server->connrec->address, time(NULL)-server->lag_sent);
}
static void sig_server_reconnect_removed(RECONNECT_REC *reconnect)
{
g_return_if_fail(reconnect != NULL);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
IRCTXT_RECONNECT_REMOVED, reconnect->conn->address, reconnect->conn->port,
reconnect->conn->ircnet == NULL ? "" : reconnect->conn->ircnet);
}
static void sig_server_reconnect_not_found(gchar *tag)
{
g_return_if_fail(tag != NULL);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
IRCTXT_RECONNECT_NOT_FOUND, tag);
}
static void event_received(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *addr)
{
g_return_if_fail(data != NULL);
if (!isdigit((gint) *data))
printtext(server, NULL, MSGLEVEL_CRAP, "%s", data);
else
{
/* numeric event. */
gchar *params, *cmd, *args, *ptr;
params = event_get_params(data, 3 | PARAM_FLAG_GETREST, &cmd, NULL, &args);
ptr = strstr(args, " :");
if (ptr != NULL) *(ptr+1) = ' ';
printtext(server, NULL, MSGLEVEL_CRAP, "%s", args);
g_free(params);
}
}
static void sig_empty(void)
{
}
static void read_settings(void)
{
beep_msg_level = level2bits(settings_get_str("beep_on_msg"));
beep_when_away = settings_get_bool("beep_when_away");
}
void fe_events_init(void)
{
beep_msg_level = 0;
read_settings();
signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg);
signal_add("ctcp msg", (SIGNAL_FUNC) ctcp_action_msg);
signal_add("ctcp msg action", (SIGNAL_FUNC) sig_empty);
signal_add("event notice", (SIGNAL_FUNC) event_notice);
signal_add("event join", (SIGNAL_FUNC) event_join);
signal_add("event part", (SIGNAL_FUNC) event_part);
signal_add("event quit", (SIGNAL_FUNC) event_quit);
signal_add("event kick", (SIGNAL_FUNC) event_kick);
signal_add("event nick", (SIGNAL_FUNC) event_nick);
signal_add("event mode", (SIGNAL_FUNC) event_mode);
signal_add("event pong", (SIGNAL_FUNC) event_pong);
signal_add("event invite", (SIGNAL_FUNC) event_invite);
signal_add("event topic", (SIGNAL_FUNC) event_topic);
signal_add("event error", (SIGNAL_FUNC) event_error);
signal_add("event wallops", (SIGNAL_FUNC) event_wallops);
signal_add("default event", (SIGNAL_FUNC) event_received);
signal_add("channel sync", (SIGNAL_FUNC) channel_sync);
signal_add("event connected", (SIGNAL_FUNC) event_connected);
signal_add("nickfind event whois", (SIGNAL_FUNC) event_nickfind_whois);
signal_add("ban type changed", (SIGNAL_FUNC) event_ban_type_changed);
//signal_add("perl error", (SIGNAL_FUNC) event_perl_error);
signal_add("server lag disconnect", (SIGNAL_FUNC) sig_server_lag_disconnected);
signal_add("server reconnect remove", (SIGNAL_FUNC) sig_server_reconnect_removed);
signal_add("server reconnect not found", (SIGNAL_FUNC) sig_server_reconnect_not_found);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
}
void fe_events_deinit(void)
{
signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg);
signal_remove("ctcp msg", (SIGNAL_FUNC) ctcp_action_msg);
signal_remove("ctcp msg action", (SIGNAL_FUNC) sig_empty);
signal_remove("event notice", (SIGNAL_FUNC) event_notice);
signal_remove("event join", (SIGNAL_FUNC) event_join);
signal_remove("event part", (SIGNAL_FUNC) event_part);
signal_remove("event quit", (SIGNAL_FUNC) event_quit);
signal_remove("event kick", (SIGNAL_FUNC) event_kick);
signal_remove("event nick", (SIGNAL_FUNC) event_nick);
signal_remove("event mode", (SIGNAL_FUNC) event_mode);
signal_remove("event pong", (SIGNAL_FUNC) event_pong);
signal_remove("event invite", (SIGNAL_FUNC) event_invite);
signal_remove("event topic", (SIGNAL_FUNC) event_topic);
signal_remove("event error", (SIGNAL_FUNC) event_error);
signal_remove("event wallops", (SIGNAL_FUNC) event_wallops);
signal_remove("default event", (SIGNAL_FUNC) event_received);
signal_remove("channel sync", (SIGNAL_FUNC) channel_sync);
signal_remove("event connected", (SIGNAL_FUNC) event_connected);
signal_remove("nickfind event whois", (SIGNAL_FUNC) event_nickfind_whois);
signal_remove("ban type changed", (SIGNAL_FUNC) event_ban_type_changed);
//signal_remove("perl error", (SIGNAL_FUNC) event_perl_error);
signal_remove("server lag disconnect", (SIGNAL_FUNC) sig_server_lag_disconnected);
signal_remove("server reconnect remove", (SIGNAL_FUNC) sig_server_reconnect_removed);
signal_remove("server reconnect not found", (SIGNAL_FUNC) sig_server_reconnect_not_found);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
}

View file

@ -0,0 +1,248 @@
/*
fe-ignore.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "commands.h"
#include "levels.h"
#include "misc.h"
#include "irc.h"
#include "irc-server.h"
#include "ignore.h"
static char *ignore_get_key(IGNORE_REC *rec)
{
char *chans, *ret;
if (rec->channels == NULL)
return rec->mask != NULL ? g_strdup(rec->mask) : NULL;
chans = g_strjoinv(",", rec->channels);
if (rec->mask == NULL) return chans;
ret = g_strdup_printf("%s %s", rec->mask, chans);
g_free(chans);
return ret;
}
static char *ignore_get_levels(int level, int xlevel)
{
GString *str;
char *levelstr, *p, *ret;
str = g_string_new(NULL);
if (level != 0) {
levelstr = bits2level(level);
g_string_append(str, levelstr);
g_free(levelstr);
}
if (xlevel != 0) {
if (str->len > 0) g_string_append_c(str, ' ');
levelstr = bits2level(xlevel);
for (p = levelstr; *p != '\0'; p++) {
if (!isspace(*p) && (p == levelstr || isspace(p[-1])))
g_string_append_c(str, '^');
g_string_append_c(str, *p);
}
g_free(levelstr);
}
ret = str->str;
g_string_free(str, FALSE);
return ret;
}
/* msgs ^notices : level=msgs, xlevel=notices */
static void ignore_split_levels(const char *levels, int *level, int *xlevel)
{
GString *slevel, *sxlevel;
char **levellist, **tmp;
if (*levels == '\0') return;
slevel = g_string_new(NULL);
sxlevel = g_string_new(NULL);
levellist = g_strsplit(levels, " ", -1);
for (tmp = levellist; *tmp != NULL; tmp++) {
if (**tmp == '^')
g_string_sprintfa(sxlevel, "%s ", (*tmp)+1);
else if (**tmp == '-' && (*tmp)[1] == '^')
g_string_sprintfa(sxlevel, "-%s ", (*tmp)+2);
else
g_string_sprintfa(slevel, "%s ", *tmp);
}
g_strfreev(levellist);
*level = combine_level(*level, slevel->str);
*xlevel = combine_level(*xlevel, sxlevel->str);
g_string_free(slevel, TRUE);
g_string_free(sxlevel, TRUE);
}
static void ignore_print(int index, IGNORE_REC *rec)
{
char *key, *levels;
key = ignore_get_key(rec);
levels = ignore_get_levels(rec->level, rec->except_level);
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
IRCTXT_IGNORE_LINE, index,
key != NULL ? key : "",
levels != NULL ? levels : "",
rec->fullword ? " -word" : "",
rec->regexp ? " -regexp" : "");
g_free(key);
g_free(levels);
}
static void cmd_ignore_show(void)
{
GSList *tmp;
int index;
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_IGNORE_HEADER);
index = 1;
for (tmp = ignores; tmp != NULL; tmp = tmp->next, index++) {
IGNORE_REC *rec = tmp->data;
ignore_print(index, rec);
}
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_IGNORE_FOOTER);
}
static void cmd_ignore(const char *data)
{
/* /IGNORE [-regexp | -word] [-pattern <pattern>] [-except]
[-channels <channel>] <mask> <levels>
OR
/IGNORE [-regexp | -word] [-pattern <pattern>] [-except]
<channels> <levels> */
char *params, *args, *patternarg, *chanarg, *mask, *levels, *key;
char **channels;
IGNORE_REC *rec;
int new_ignore;
if (*data == '\0') {
cmd_ignore_show();
return;
}
args = "pattern channels";
params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST,
&args, &patternarg, &chanarg, &mask, &levels);
if (levels == 0) cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (ischannel(*mask)) {
chanarg = mask;
mask = "";
}
channels = *chanarg == '\0' ? NULL :
g_strsplit(replace_chars(chanarg, ',', ' '), " ", -1);
rec = ignore_find(NULL, mask, channels);
new_ignore = rec == NULL;
if (rec == NULL) {
rec = g_new0(IGNORE_REC, 1);
rec->mask = *mask == '\0' ? NULL : g_strdup(mask);
rec->channels = channels;
} else {
g_free_and_null(rec->pattern);
g_strfreev(channels);
}
if (stristr(args, "-except") != NULL) {
rec->except_level = combine_level(rec->except_level, levels);
} else {
ignore_split_levels(levels, &rec->level, &rec->except_level);
}
rec->pattern = *patternarg == '\0' ? NULL : g_strdup(patternarg);
rec->fullword = stristr(args, "-word") != NULL;
rec->regexp = stristr(args, "-regexp") != NULL;
if (rec->level == 0 && rec->except_level == 0)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_UNIGNORED, rec->mask);
else {
key = ignore_get_key(rec);
levels = ignore_get_levels(rec->level, rec->except_level);
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_IGNORED, key, levels);
g_free(key);
g_free(levels);
}
if (new_ignore)
ignore_add_rec(rec);
else
ignore_update_rec(rec);
g_free(params);
}
static void cmd_unignore(const char *data)
{
IGNORE_REC *rec;
GSList *tmp;
char *key;
if (is_numeric(data, ' ')) {
/* with index number */
tmp = g_slist_nth(ignores, atol(data)-1);
rec = tmp == NULL ? NULL : tmp->data;
} else {
/* with mask */
char *chans[2] = { "*", NULL };
if (ischannel(*data)) chans[0] = (char *) data;
rec = ignore_find("*", ischannel(*data) ? NULL : data, chans);
}
if (rec == NULL)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_IGNORE_NOT_FOUND, data);
else {
key = ignore_get_key(rec);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_UNIGNORED, key);
g_free(key);
rec->level = 0;
rec->except_level = 0;
ignore_update_rec(rec);
}
}
void fe_ignore_init(void)
{
command_bind("ignore", NULL, (SIGNAL_FUNC) cmd_ignore);
command_bind("unignore", NULL, (SIGNAL_FUNC) cmd_unignore);
}
void fe_ignore_deinit(void)
{
command_unbind("ignore", (SIGNAL_FUNC) cmd_ignore);
command_unbind("unignore", (SIGNAL_FUNC) cmd_unignore);
}

View file

@ -0,0 +1,541 @@
/*
fe-irc-commands.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "commands.h"
#include "special-vars.h"
#include "settings.h"
#include "levels.h"
#include "irc.h"
#include "server.h"
#include "server-reconnect.h"
#include "mode-lists.h"
#include "nicklist.h"
#include "channels.h"
#include "query.h"
#include "windows.h"
#include "window-items.h"
static void cmd_server(const char *data)
{
if (*data == '+' && data[1] != '\0')
window_create(NULL, FALSE);
}
static void print_servers(void)
{
GSList *tmp;
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
IRC_SERVER_REC *rec = tmp->data;
printformat(NULL, NULL, MSGLEVEL_CRAP, IRCTXT_SERVER_LIST,
rec->tag, rec->connrec->address, rec->connrec->port,
rec->connrec->ircnet == NULL ? "" : rec->connrec->ircnet, rec->connrec->nick);
}
}
static void print_lookup_servers(void)
{
GSList *tmp;
for (tmp = lookup_servers; tmp != NULL; tmp = tmp->next) {
IRC_SERVER_REC *rec = tmp->data;
printformat(NULL, NULL, MSGLEVEL_CRAP, IRCTXT_SERVER_LOOKUP_LIST,
rec->tag, rec->connrec->address, rec->connrec->port,
rec->connrec->ircnet == NULL ? "" : rec->connrec->ircnet, rec->connrec->nick);
}
}
static void print_reconnects(void)
{
GSList *tmp;
char *tag, *next_connect;
int left;
for (tmp = reconnects; tmp != NULL; tmp = tmp->next) {
RECONNECT_REC *rec = tmp->data;
IRC_SERVER_CONNECT_REC *conn = rec->conn;
tag = g_strdup_printf("RECON-%d", rec->tag);
left = rec->next_connect-time(NULL);
next_connect = g_strdup_printf("%02d:%02d", left/60, left%60);
printformat(NULL, NULL, MSGLEVEL_CRAP, IRCTXT_SERVER_RECONNECT_LIST,
tag, conn->address, conn->port,
conn->ircnet == NULL ? "" : conn->ircnet,
conn->nick, next_connect);
g_free(next_connect);
g_free(tag);
}
}
static void cmd_servers(void)
{
print_servers();
print_lookup_servers();
print_reconnects();
}
static void cmd_unquery(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
QUERY_REC *query;
g_return_if_fail(data != NULL);
if (*data == '\0') {
/* remove current query */
query = irc_item_query(item);
if (query == NULL) return;
} else {
query = query_find(server, data);
if (query == NULL) {
printformat(server, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_NO_QUERY, data);
return;
}
}
query_destroy(query);
}
static void cmd_query(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
WINDOW_REC *window;
QUERY_REC *query;
g_return_if_fail(data != NULL);
if (*data == '\0') {
/* remove current query */
cmd_unquery("", server, item);
return;
}
if (*data != '=' && (server == NULL || !server->connected))
cmd_return_error(CMDERR_NOT_CONNECTED);
query = query_find(server, data);
if (query != NULL) {
/* query already existed - change to query window */
window = window_item_window((WI_ITEM_REC *) query);
g_return_if_fail(window != NULL);
window_set_active(window);
window_item_set_active(window, (WI_ITEM_REC *) query);
return;
}
query_create(server, data, FALSE);
}
static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item)
{
WINDOW_REC *window;
CHANNEL_REC *channel;
NICK_REC *nickrec;
char *params, *target, *msg, *nickmode, *freestr, *newtarget;
int free_ret;
g_return_if_fail(data != NULL);
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target == '=')
{
/* dcc msg - handled in fe-dcc.c */
g_free(params);
return;
}
free_ret = FALSE;
if (strcmp(target, ",") == 0 || strcmp(target, ".") == 0)
newtarget = parse_special(&target, server, item, NULL, &free_ret, NULL);
else if (strcmp(target, "*") == 0 &&
(irc_item_channel(item) || irc_item_query(item)))
newtarget = item->name;
else newtarget = target;
if (newtarget == NULL) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, *target == ',' ?
IRCTXT_NO_MSGS_GOT : IRCTXT_NO_MSGS_SENT);
g_free(params);
signal_stop();
return;
}
target = newtarget;
if (server == NULL || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED);
channel = channel_find(server, target);
freestr = !free_ret ? NULL : target;
if (*target == '@' && ischannel(target[1]))
target++; /* Hybrid 6 feature, send msg to all ops in channel */
if (ischannel(*target))
{
/* msg to channel */
nickrec = channel == NULL ? NULL : nicklist_find(channel, server->nick);
nickmode = !settings_get_bool("toggle_show_nickmode") || nickrec == NULL ? "" :
nickrec->op ? "@" : nickrec->voice ? "+" : " ";
window = channel == NULL ? NULL : window_item_window((WI_ITEM_REC *) channel);
if (window != NULL && window->active == (WI_ITEM_REC *) channel)
{
printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT,
IRCTXT_OWN_MSG, server->nick, msg, nickmode);
}
else
{
printformat(server, target, MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT,
IRCTXT_OWN_MSG_CHANNEL, server->nick, target, msg, nickmode);
}
}
else
{
/* private message */
printformat(server, target, MSGLEVEL_MSGS | MSGLEVEL_NOHILIGHT,
channel == NULL ? IRCTXT_OWN_MSG_PRIVATE : IRCTXT_OWN_MSG_PRIVATE_QUERY, target, msg, server->nick);
}
g_free_not_null(freestr);
g_free(params);
}
static void cmd_notice(gchar *data, IRC_SERVER_REC *server)
{
char *params, *target, *msg;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target == '@' && ischannel(target[1]))
target++; /* Hybrid 6 feature, send notice to all ops in channel */
printformat(server, target, MSGLEVEL_NOTICES | MSGLEVEL_NOHILIGHT,
IRCTXT_OWN_NOTICE, target, msg);
g_free(params);
}
static void cmd_me(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
g_return_if_fail(data != NULL);
if (!irc_item_check(item))
return;
if (irc_item_dcc_chat(item)) {
/* DCC action - handled by fe-dcc.c */
return;
}
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
printformat(server, item->name, MSGLEVEL_ACTIONS,
IRCTXT_OWN_ME, server->nick, data);
irc_send_cmdv(server, "PRIVMSG %s :\001ACTION %s\001", item->name, data);
}
static void cmd_action(const char *data, IRC_SERVER_REC *server)
{
char *params, *target, *text;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
if (*data == '=') {
/* DCC action - handled by fe-dcc.c */
return;
}
params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &text);
if (*target == '\0' || *text == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
printformat(server, target, MSGLEVEL_ACTIONS, IRCTXT_OWN_ME, server->nick, text);
irc_send_cmdv(server, "PRIVMSG %s :\001ACTION %s\001", target, text);
g_free(params);
}
static void cmd_ctcp(const char *data, IRC_SERVER_REC *server)
{
char *params, *target, *ctcpcmd, *ctcpdata;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata);
if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target == '=') {
/* send CTCP via DCC CHAT */
g_free(params);
return;
}
if (*target == '@' && ischannel(target[1]))
target++; /* Hybrid 6 feature, send ctcp to all ops in channel */
g_strup(ctcpcmd);
printformat(server, target, MSGLEVEL_CTCPS, IRCTXT_OWN_CTCP, target, ctcpcmd, ctcpdata);
g_free(params);
}
static void cmd_nctcp(const char *data, IRC_SERVER_REC *server)
{
gchar *params, *target, *ctcpcmd, *ctcpdata;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata);
if (*target == '\0' || *ctcpcmd == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (*target == '@' && ischannel(target[1]))
target++; /* Hybrid 6 feature, send notice to all ops in channel */
g_strup(ctcpcmd);
printformat(server, target, MSGLEVEL_NOTICES, IRCTXT_OWN_NOTICE, target, ctcpcmd, ctcpdata);
g_free(params);
}
static void cmd_banstat(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
CHANNEL_REC *cur_channel, *channel;
GSList *tmp;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
cur_channel = irc_item_channel(item);
if (cur_channel == NULL) cmd_return_error(CMDERR_NOT_JOINED);
if (strcmp(data, "*") == 0 || *data == '\0')
channel = cur_channel;
else {
channel = channel_find(server, data);
if (channel == NULL) {
/* not joined to such channel, but ask ban lists from server */
GString *str;
str = g_string_new(NULL);
g_string_sprintf(str, "%s b", data);
signal_emit("command mode", 3, str->str, server, cur_channel);
g_string_sprintf(str, "%s e", data);
signal_emit("command mode", 3, str->str, server, cur_channel);
g_string_free(str, TRUE);
return;
}
}
if (channel == NULL) cmd_return_error(CMDERR_CHAN_NOT_FOUND);
/* show bans.. */
for (tmp = channel->banlist; tmp != NULL; tmp = tmp->next) {
BAN_REC *rec;
rec = (BAN_REC *) tmp->data;
if (*rec->setby == '\0')
printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_BANLIST, channel->name, rec->ban);
else
printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_BANLIST,
channel->name, rec->ban, rec->setby, (gint) (time(NULL)-rec->time));
}
/* ..and show ban exceptions.. */
for (tmp = channel->ebanlist; tmp != NULL; tmp = tmp->next) {
BAN_REC *rec;
rec = (BAN_REC *) tmp->data;
if (*rec->setby == '\0')
printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_EBANLIST, channel->name, rec->ban);
else
printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_EBANLIST,
channel->name, rec->ban, rec->setby, (gint) (time(NULL)-rec->time));
}
}
static void cmd_invitelist(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
CHANNEL_REC *channel, *cur_channel;
GSList *tmp;
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED);
cur_channel = irc_item_channel(item);
if (cur_channel == NULL) cmd_return_error(CMDERR_NOT_JOINED);
if (strcmp(data, "*") == 0 || *data == '\0')
channel = cur_channel;
else
channel = channel_find(server, data);
if (channel == NULL) cmd_return_error(CMDERR_CHAN_NOT_FOUND);
for (tmp = channel->invitelist; tmp != NULL; tmp = tmp->next)
printformat(server, channel->name, MSGLEVEL_CRAP, IRCTXT_INVITELIST, channel->name, tmp->data);
}
static void cmd_join(const char *data, IRC_SERVER_REC *server)
{
if ((*data == '\0' || g_strncasecmp(data, "-invite", 7) == 0) &&
server->last_invite == NULL) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOT_INVITED);
signal_stop();
}
}
static void cmd_channel(const char *data, IRC_SERVER_REC *server)
{
CHANNEL_REC *channel;
GString *nicks;
GSList *nicklist, *tmp, *ntmp;
char *mode;
if (*data != '\0') {
cmd_join(data, server);
return;
}
if (channels == NULL) {
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOT_IN_CHANNELS);
return;
}
/* print active channel */
channel = irc_item_channel(active_win->active);
if (channel != NULL)
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CURRENT_CHANNEL, channel->name);
/* print list of all channels, their modes, server tags and nicks */
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CHANLIST_HEADER);
for (tmp = channels; tmp != NULL; tmp = tmp->next) {
channel = tmp->data;
nicklist = nicklist_getnicks(channel);
mode = channel_get_mode(channel);
nicks = g_string_new(NULL);
for (ntmp = nicklist; ntmp != NULL; ntmp = ntmp->next) {
NICK_REC *rec = ntmp->data;
g_string_sprintfa(nicks, "%s ", rec->nick);
}
g_string_truncate(nicks, nicks->len-1);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CHANLIST_LINE,
channel->name, mode, channel->server->tag, nicks->str);
g_free(mode);
g_slist_free(nicklist);
g_string_free(nicks, TRUE);
}
}
static void cmd_nick(const char *data, IRC_SERVER_REC *server)
{
g_return_if_fail(data != NULL);
if (*data != '\0') return;
if (server == NULL || !server->connected)
cmd_return_error(CMDERR_NOT_CONNECTED);
/* display current nick */
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_YOUR_NICK, server->nick);
signal_stop();
}
static void cmd_ver(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item)
{
char *str;
g_return_if_fail(data != NULL);
if (!irc_server_check(server))
cmd_return_error(CMDERR_NOT_CONNECTED);
if (*data == '\0' && !irc_item_check(item))
cmd_return_error(CMDERR_NOT_JOINED);
str = g_strdup_printf("%s VERSION", *data == '\0' ? item->name : data);
signal_emit("command ctcp", 3, str, server, item);
g_free(str);
}
static void cmd_ts(const char *data)
{
GSList *tmp;
g_return_if_fail(data != NULL);
for (tmp = channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *rec = tmp->data;
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_TOPIC,
rec->name, rec->topic == NULL ? "" : rec->topic);
}
}
void fe_irc_commands_init(void)
{
command_bind("server", NULL, (SIGNAL_FUNC) cmd_server);
command_bind("servers", NULL, (SIGNAL_FUNC) cmd_servers);
command_bind("query", NULL, (SIGNAL_FUNC) cmd_query);
command_bind("unquery", NULL, (SIGNAL_FUNC) cmd_unquery);
command_bind("msg", NULL, (SIGNAL_FUNC) cmd_msg);
command_bind("notice", NULL, (SIGNAL_FUNC) cmd_notice);
command_bind("me", NULL, (SIGNAL_FUNC) cmd_me);
command_bind("action", NULL, (SIGNAL_FUNC) cmd_action);
command_bind("ctcp", NULL, (SIGNAL_FUNC) cmd_ctcp);
command_bind("nctcp", NULL, (SIGNAL_FUNC) cmd_nctcp);
command_bind("banstat", NULL, (SIGNAL_FUNC) cmd_banstat);
command_bind("invitelist", NULL, (SIGNAL_FUNC) cmd_invitelist);
command_bind("join", NULL, (SIGNAL_FUNC) cmd_join);
command_bind("channel", NULL, (SIGNAL_FUNC) cmd_channel);
command_bind("nick", NULL, (SIGNAL_FUNC) cmd_nick);
command_bind("ver", NULL, (SIGNAL_FUNC) cmd_ver);
command_bind("ts", NULL, (SIGNAL_FUNC) cmd_ts);
}
void fe_irc_commands_deinit(void)
{
command_unbind("server", (SIGNAL_FUNC) cmd_server);
command_unbind("servers", (SIGNAL_FUNC) cmd_servers);
command_unbind("query", (SIGNAL_FUNC) cmd_query);
command_unbind("unquery", (SIGNAL_FUNC) cmd_unquery);
command_unbind("msg", (SIGNAL_FUNC) cmd_msg);
command_unbind("notice", (SIGNAL_FUNC) cmd_notice);
command_unbind("me", (SIGNAL_FUNC) cmd_me);
command_unbind("action", (SIGNAL_FUNC) cmd_action);
command_unbind("ctcp", (SIGNAL_FUNC) cmd_ctcp);
command_unbind("nctcp", (SIGNAL_FUNC) cmd_nctcp);
command_unbind("banstat", (SIGNAL_FUNC) cmd_banstat);
command_unbind("invitelist", (SIGNAL_FUNC) cmd_invitelist);
command_unbind("join", (SIGNAL_FUNC) cmd_join);
command_unbind("channel", (SIGNAL_FUNC) cmd_channel);
command_unbind("nick", (SIGNAL_FUNC) cmd_nick);
command_unbind("ver", (SIGNAL_FUNC) cmd_ver);
command_unbind("ts", (SIGNAL_FUNC) cmd_ts);
}

View file

@ -0,0 +1,133 @@
/*
fe-query.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "modules.h"
#include "signals.h"
#include "commands.h"
#include "irc.h"
#include "levels.h"
#include "query.h"
#include "windows.h"
#include "window-items.h"
static void signal_query_created(QUERY_REC *query, gpointer automatic)
{
window_item_create((WI_ITEM_REC *) query, GPOINTER_TO_INT(automatic));
}
static void signal_query_created_curwin(QUERY_REC *query)
{
g_return_if_fail(query != NULL);
window_add_item(active_win, (WI_ITEM_REC *) query, FALSE);
signal_stop();
}
static void signal_query_destroyed(QUERY_REC *query)
{
WINDOW_REC *window;
g_return_if_fail(query != NULL);
window = window_item_window((WI_ITEM_REC *) query);
if (window != NULL) window_remove_item(window, (WI_ITEM_REC *) query);
}
static void signal_window_item_removed(WINDOW_REC *window, WI_ITEM_REC *item)
{
QUERY_REC *query;
g_return_if_fail(window != NULL);
query = irc_item_query(item);
if (query != NULL) query_destroy(query);
}
static void sig_server_connected(IRC_SERVER_REC *server)
{
GSList *tmp;
if (!irc_server_check(server))
return;
/* check if there's any queries without server */
for (tmp = queries; tmp != NULL; tmp = tmp->next) {
QUERY_REC *rec = tmp->data;
if (rec->server == NULL &&
g_strcasecmp(rec->server_tag, server->tag) == 0) {
window_item_change_server((WI_ITEM_REC *) rec, server);
server->queries = g_slist_append(server->queries, rec);
}
}
}
static void cmd_window_server(const char *data)
{
SERVER_REC *server;
g_return_if_fail(data != NULL);
server = server_find_tag(data);
if (irc_server_check(server) && irc_item_query(active_win->active)) {
/* /WINDOW SERVER used in a query window */
query_change_server((QUERY_REC *) active_win->active,
(IRC_SERVER_REC *) server);
window_change_server(active_win, server);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_QUERY_SERVER_CHANGED, server->tag, server->connrec->address,
server->connrec->ircnet == NULL ? "" : server->connrec->ircnet);
signal_stop();
}
}
static void cmd_wquery(const char *data, void *server, WI_ITEM_REC *item)
{
signal_add("query created", (SIGNAL_FUNC) signal_query_created_curwin);
signal_emit("command query", 3, data, server, item);
signal_remove("query created", (SIGNAL_FUNC) signal_query_created_curwin);
}
void fe_query_init(void)
{
signal_add("query created", (SIGNAL_FUNC) signal_query_created);
signal_add("query destroyed", (SIGNAL_FUNC) signal_query_destroyed);
signal_add("window item remove", (SIGNAL_FUNC) signal_window_item_removed);
signal_add("server connected", (SIGNAL_FUNC) sig_server_connected);
command_bind("wquery", NULL, (SIGNAL_FUNC) cmd_wquery);
command_bind("window server", NULL, (SIGNAL_FUNC) cmd_window_server);
}
void fe_query_deinit(void)
{
signal_remove("query created", (SIGNAL_FUNC) signal_query_created);
signal_remove("query destroyed", (SIGNAL_FUNC) signal_query_destroyed);
signal_remove("window item remove", (SIGNAL_FUNC) signal_window_item_removed);
signal_remove("server connected", (SIGNAL_FUNC) sig_server_connected);
command_unbind("wquery", (SIGNAL_FUNC) cmd_wquery);
command_unbind("window server", (SIGNAL_FUNC) cmd_window_server);
}

View file

@ -0,0 +1,17 @@
noinst_LTLIBRARIES = libfe_common_irc_flood.la
INCLUDES = \
$(GLIB_CFLAGS) \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core/ \
-I$(top_srcdir)/src/irc/core/ \
-I$(top_srcdir)/src/fe-common/core/ \
-DHELPDIR=\""$(datadir)/irssi/help"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\"
libfe_common_irc_flood_la_SOURCES = \
fe-flood.c \
module-formats.c
noinst_headers = \
module-formats.h

View file

@ -0,0 +1,54 @@
/*
fe-flood.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "levels.h"
#include "irc-server.h"
#include "irc/flood/autoignore.h"
static void event_autoignore_new(IRC_SERVER_REC *server, AUTOIGNORE_REC *ignore)
{
g_return_if_fail(ignore != NULL);
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_AUTOIGNORE,
ignore->nick, (ignore->timeleft+59)/60);
}
static void event_autoignore_remove(IRC_SERVER_REC *server, AUTOIGNORE_REC *ignore)
{
g_return_if_fail(ignore != NULL);
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_AUTOUNIGNORE, ignore->nick);
}
void fe_flood_init(void)
{
signal_add("autoignore new", (SIGNAL_FUNC) event_autoignore_new);
signal_add("autoignore remove", (SIGNAL_FUNC) event_autoignore_remove);
}
void fe_flood_deinit(void)
{
signal_remove("autoignore new", (SIGNAL_FUNC) event_autoignore_new);
signal_remove("autoignore remove", (SIGNAL_FUNC) event_autoignore_remove);
}

View file

@ -0,0 +1,33 @@
/*
module-formats.c : irssi
Copyright (C) 2000 Timo Sirainen
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 "module.h"
#include "printtext.h"
FORMAT_REC fecommon_irc_flood_formats[] =
{
{ MODULE_NAME, N_("Flood"), 0 },
/* ---- */
{ NULL, N_("Autoignore"), 0 },
{ "autoignore", N_("Flood detected from %_$0%_, autoignoring for %_$1%_ minutes"), 2, { 0, 1 } },
{ "autounignore", N_("Unignoring %_$0"), 1, { 0 } }
};

View file

@ -0,0 +1,13 @@
#include "printtext.h"
enum {
IRCTXT_MODULE_NAME,
IRCTXT_FILL_1,
IRCTXT_AUTOIGNORE,
IRCTXT_AUTOUNIGNORE
};
extern FORMAT_REC fecommon_irc_flood_formats[];
#define MODULE_FORMATS fecommon_irc_flood_formats

View file

@ -0,0 +1,54 @@
/*
irc-hilight-text.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "hilight-text.h"
char *irc_hilight_find_nick(const char *channel, const char *nick, const char *address)
{
GSList *tmp;
char *color;
int len, best_match;
g_return_val_if_fail(channel != NULL, NULL);
g_return_val_if_fail(nick != NULL, NULL);
g_return_val_if_fail(address != NULL, NULL);
color = NULL; best_match = 0;
for (tmp = hilights; tmp != NULL; tmp = tmp->next) {
HILIGHT_REC *rec = tmp->data;
if (!rec->nickmask)
continue;
len = strlen(rec->text);
if (best_match < len) {
best_match = len;
color = rec->color;
}
}
if (best_match == 0)
return NULL;
if (color == NULL) color = "\00316";
return g_strconcat(isdigit(*color) ? "\003" : "", color, NULL);
}

View file

@ -0,0 +1,6 @@
#ifndef __IRC_HILIGHT_TEXT_H
#define __IRC_HILIGHT_TEXT_H
char *irc_hilight_find_nick(const char *channel, const char *nick, const char *address);
#endif

View file

@ -0,0 +1,89 @@
/*
irc-nick-hilight.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "signals.h"
#include "levels.h"
#include "irc.h"
#include "ignore.h"
#include "irc-server.h"
#include "completion.h"
#include "windows.h"
#include "window-items.h"
static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr)
{
WINDOW_REC *window;
WI_ITEM_REC *item;
char *params, *target, *msg;
int level;
g_return_if_fail(data != NULL);
params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
if (*msg == 1) {
/* don't hilight CTCPs */
g_free(params);
return;
}
/* get window and window item */
level = ischannel(*target) ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS;
item = window_item_find(server, ischannel(*target) ? target : nick);
window = item == NULL ?
window_find_closest(server, target, GPOINTER_TO_INT(level)) :
window_item_window(item);
/* check that msg wasn't send to current window and
that it didn't get ignored */
if (window != active_win && !ignore_check(server, nick, addr, target, msg, level)) {
/* hilight */
level = !ischannel(*target) ||
completion_msgtoyou((SERVER_REC *) server, msg) ?
NEWDATA_MSG_FORYOU : NEWDATA_MSG;
if (item != NULL && item->new_data < level) {
item->new_data = level;
signal_emit("window item hilight", 1, item);
} else {
int oldlevel = window->new_data;
if (window->new_data < level) {
window->new_data = level;
signal_emit("window hilight", 2, window, GINT_TO_POINTER(oldlevel));
}
signal_emit("window activity", 2, window, GINT_TO_POINTER(oldlevel));
}
}
g_free(params);
}
void irc_nick_hilight_init(void)
{
signal_add_last("event privmsg", (SIGNAL_FUNC) event_privmsg);
}
void irc_nick_hilight_deinit(void)
{
signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg);
}

View file

@ -0,0 +1,174 @@
/*
module-formats.c : irssi
Copyright (C) 2000 Timo Sirainen
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 "module.h"
#include "printtext.h"
FORMAT_REC fecommon_irc_formats[] =
{
{ MODULE_NAME, N_("IRC"), 0 },
/* ---- */
{ NULL, N_("Server"), 0 },
{ "lag_disconnected", N_("No PONG reply from server %_$0%_ in $1 seconds, disconnecting"), 2, { 0, 1 } },
{ "disconnected", N_("Disconnected from %_$0%_ %K[%n$1%K]"), 2, { 0, 0 } },
{ "server_list", N_("%_$0%_: $1:$2 ($3)"), 5, { 0, 0, 1, 0, 0 } },
{ "server_lookup_list", N_("%_$0%_: $1:$2 ($3) (connecting...)"), 5, { 0, 0, 1, 0, 0 } },
{ "server_reconnect_list", N_("%_$0%_: $1:$2 ($3) ($5 left before reconnecting)"), 6, { 0, 0, 1, 0, 0, 0 } },
{ "server_reconnect_removed", N_("Removed reconnection to server %_$0%_ port %_$1%_"), 3, { 0, 1, 0 } },
{ "server_reconnect_not_found", N_("Reconnection tag %_$0%_ not found"), 1, { 0 } },
{ "query_server_changed", N_("Query with %_$2%_ changed to server %_$1%_"), 3, { 0, 0, 0 } },
/* ---- */
{ NULL, N_("Channels"), 0 },
{ "join", N_("%c%_$0%_ %K[%c$1%K]%n has joined %_$2"), 3, { 0, 0, 0 } },
{ "part", N_("%c$0 %K[%n$1%K]%n has left %_$2%_ %K[%n$3%K]"), 4, { 0, 0, 0, 0 } },
{ "joinerror_toomany", N_("Cannot join to channel %_$0%_ %K(%nYou have joined to too many channels%K)"), 1, { 0 } },
{ "joinerror_full", N_("Cannot join to channel %_$0%_ %K(%nChannel is full%K)"), 1, { 0 } },
{ "joinerror_invite", N_("Cannot join to channel %_$0%_ %K(%nYou must be invited%K)"), 1, { 0 } },
{ "joinerror_banned", N_("Cannot join to channel %_$0%_ %K(%nYou are banned%K)"), 1, { 0 } },
{ "joinerror_bad_key", N_("Cannot join to channel %_$0%_ %K(%nBad channel key%K)"), 1, { 0 } },
{ "joinerror_bad_mask", N_("Cannot join to channel %_$0%_ %K(%nBad channel mask%K)"), 1, { 0 } },
{ "joinerror_unavail", N_("Cannot join to channel %_$0%_ %K(%nChannel is temporarily unavailable%K)"), 1, { 0 } },
{ "kick", N_("%c$0%n was kicked from %_$1%_ by %_$2%_ %K[%n$3%K]"), 4, { 0, 0, 0, 0 } },
{ "quit", N_("%c$0 %K[%n$1%K]%n has quit IRC %K[%n$2%K]"), 3, { 0, 0, 0 } },
{ "quit_once", N_("%_$3%_ %c$0 %K[%n$1%K]%n has quit IRC %K[%n$2%K]"), 4, { 0, 0, 0, 0 } },
{ "invite", N_("%_$0%_ invites you to %_$1"), 2, { 0, 0 } },
{ "not_invited", N_("You have not been invited to a channel!"), 0 },
{ "names", N_("%K[%g%_Users%_%K(%g$0%K)]%n $1"), 2, { 0, 0 } },
{ "endofnames", N_("%g%_$0%_%K:%n Total of %_$1%_ nicks %K[%n%_$2%_ ops, %_$3%_ voices, %_$4%_ normal%K]"), 5, { 0, 1, 1, 1, 1 } },
{ "channel_created", N_("Channel %_$0%_ created $1"), 2, { 0, 0 } },
{ "topic", N_("Topic for %c$0%K:%n $1"), 2, { 0, 0 } },
{ "no_topic", N_("No topic set for %c$0"), 1, { 0 } },
{ "new_topic", N_("%_$0%_ changed the topic of %c$1%n to%K:%n $2"), 3, { 0, 0, 0 } },
{ "topic_unset", N_("Topic unset by %_$0%_ on %c$1"), 2, { 0, 0 } },
{ "topic_info", N_("Topic set by %_$0%_ %K[%n$1%K]"), 2, { 0, 0 } },
{ "chanmode_change", N_("mode/%c$0 %K[%n$1%K]%n by %_$2"), 3, { 0, 0, 0 } },
{ "server_chanmode_change", N_("%RServerMode/%c$0 %K[%n$1%K]%n by %_$2"), 3, { 0, 0, 0 } },
{ "channel_mode", N_("mode/%c$0 %K[%n$1%K]"), 2, { 0, 0 } },
{ "bantype", N_("Ban type changed to %_$0"), 1, { 0 } },
{ "banlist", N_("%_$0%_: ban %c$1"), 2, { 0, 0 } },
{ "banlist_long", N_("%_$0%_: ban %c$1 %K[%nby %_$2%_, $3 secs ago%K]"), 4, { 0, 0, 0, 1 } },
{ "ebanlist", N_("%_$0%_: ban exception %c$1"), 2, { 0, 0 } },
{ "ebanlist_long", N_("%_$0%_: ban exception %c$1 %K[%nby %_$2%_, $3 secs ago%K]"), 4, { 0, 0, 0, 1 } },
{ "invitelist", N_("%_$0%_: invite %c$1"), 2, { 0, 0 } },
{ "no_such_channel", N_("$0: No such channel"), 1, { 0 } },
{ "not_in_channels", N_("You are not on any channels"), 0 },
{ "current_channel", N_("Current channel $0"), 1, { 0 } },
{ "chanlist_header", N_("You are on the following channels:"), 0 },
{ "chanlist_line", N_("$[-10]0 %|+$1 ($2): $3"), 4, { 0, 0, 0, 0 } },
{ "channel_synced", N_("Join to %_$0%_ was synced in %_$1%_ secs"), 2, { 0, 2 } },
/* ---- */
{ NULL, N_("Nick"), 0 },
{ "usermode_change", N_("Mode change %K[%n%_$0%_%K]%n for user %c$1"), 2, { 0, 0 } },
{ "user_mode", N_("Your user mode is %K[%n%_$0%_%K]"), 1, { 0 } },
{ "away", N_("You have been marked as being away"), 0 },
{ "unaway", N_("You are no longer marked as being away"), 0 },
{ "nick_away", N_("$0 is away: $1"), 2, { 0, 0 } },
{ "no_such_nick", N_("$0: No such nick/channel"), 1, { 0 } },
{ "your_nick", N_("Your nickname is $0"), 1, { 0 } },
{ "your_nick_changed", N_("You're now known as %c$0"), 1, { 0 } },
{ "nick_changed", N_("%_$0%_ is now known as %c$1"), 2, { 0, 0 } },
{ "nick_in_use", N_("Nick %_$0%_ is already in use"), 1, { 0 } },
{ "nick_unavailable", N_("Nick %_$0%_ is temporarily unavailable"), 1, { 0 } },
{ "your_nick_owned", N_("Your nick is owned by %_$3%_ %K[%n$1@$2%K]"), 4, { 0, 0, 0, 0 } },
/* ---- */
{ NULL, N_("Who queries"), 0 },
{ "whois", N_("%_$0%_ %K[%n$1@$2%K]%n%: ircname : $3"), 4, { 0, 0, 0, 0 } },
{ "whois_idle", N_(" idle : $1 hours $2 mins $3 secs"), 4, { 0, 1, 1, 1 } },
{ "whois_idle_signon", N_(" idle : $1 hours $2 mins $3 secs %K[%nsignon: $4%K]"), 5, { 0, 1, 1, 1, 0 } },
{ "whois_server", N_(" server : $1 %K[%n$2%K]"), 3, { 0, 0, 0 } },
{ "whois_oper", N_(" : %_IRC operator%_"), 1, { 0 } },
{ "whois_channels", N_(" channels : $1"), 2, { 0, 0 } },
{ "whois_away", N_(" away : $1"), 2, { 0, 0 } },
{ "end_of_whois", N_("End of WHOIS"), 1, { 0 } },
{ "who", N_("$[-10]0 %|%_$[!9]1%_ $[!3]2 $[!2]3 $4@$5 %K(%W$6%K)"), 7, { 0, 0, 0, 0, 0, 0, 0 } },
{ "end_of_who", N_("End of /WHO list"), 1, { 0 } },
/* ---- */
{ NULL, N_("Your messages"), 0 },
{ "own_msg", N_("%K<%n$2%W$0%K>%n %|$1"), 3, { 0, 0, 0 } },
{ "own_msg_channel", N_("%K<%n$3%W$0%K:%c$1%K>%n %|$2"), 4, { 0, 0, 0, 0 } },
{ "own_msg_private", N_("%K[%rmsg%K(%R$0%K)]%n $1"), 2, { 0, 0 } },
{ "own_msg_private_query", N_("%K<%W$2%K>%n %|$1"), 3, { 0, 0, 0 } },
{ "own_notice", N_("%K[%rnotice%K(%R$0%K)]%n $1"), 2, { 0, 0 } },
{ "own_me", N_("%W * $0%n $1"), 2, { 0, 0 } },
{ "own_ctcp", N_("%K[%rctcp%K(%R$0%K)]%n $1 $2"), 3, { 0, 0, 0 } },
/* ---- */
{ NULL, N_("Received messages"), 0 },
{ "pubmsg_me", N_("%K<%n$2%Y$0%K>%n %|$1"), 3, { 0, 0, 0 } },
{ "pubmsg_me_channel", N_("%K<%n$3%Y$0%K:%c$1%K>%n %|$2"), 4, { 0, 0, 0, 0 } },
{ "pubmsg_hilight", N_("%K<%n$3$0$1%K>%n %|$2"), 4, { 0, 0, 0, 0 } },
{ "pubmsg_hilight_channel", N_("%K<%n$4$0$1%K:%c$2%K>%n %|$3"), 5, { 0, 0, 0, 0, 0 } },
{ "pubmsg", N_("%K<%n$2$0%K>%n %|$1"), 3, { 0, 0, 0 } },
{ "pubmsg_channel", N_("%K<%n$3$0%K:%c$1%K>%n %|$2"), 4, { 0, 0, 0, 0 } },
{ "msg_private", N_("%K[%R$0%K(%r$1%K)]%n $2"), 3, { 0, 0, 0 } },
{ "msg_private_query", N_("%K<%R$0%K>%n %|$2"), 3, { 0, 0, 0 } },
{ "notice_server", N_("%g!$0%n $1"), 2, { 0, 0 } },
{ "notice_public", N_("%K-%M$0%K:%m$1%K-%n $2"), 3, { 0, 0, 0 } },
{ "notice_public_ops", N_("%K-%M$0%K:%m@$1%K-%n $2"), 3, { 0, 0, 0 } },
{ "notice_private", N_("%K-%M$0%K(%m$1%K)-%n $2"), 3, { 0, 0, 0 } },
{ "action_private", N_("%W (*) $0%n $2"), 3, { 0, 0, 0 } },
{ "action_private_query", N_("%W * $0%n $2"), 3, { 0, 0, 0 } },
{ "action_public", N_("%W * $0%n $1"), 2, { 0, 0 } },
{ "action_public_channel", N_("%W * $0%K:%c$1%n $2"), 3, { 0, 0, 0 } },
/* ---- */
{ NULL, N_("CTCPs"), 0 },
{ "ctcp_reply", N_("CTCP %_$0%_ reply from %_$1%_%K:%n $2"), 3, { 0, 0, 0 } },
{ "ctcp_ping_reply", N_("CTCP %_PING%_ reply from %_$0%_: $1.$2 seconds"), 3, { 0, 2, 2 } },
{ "ctcp_requested", N_("%g>>> %_$0%_ %K[%g$1%K] %grequested %_$2%_ from %_$3"), 4, { 0, 0, 0, 0 } },
/* ---- */
{ NULL, N_("Other server events"), 0 },
{ "online", N_("Users online: %_$0"), 1, { 0 } },
{ "pong", N_("PONG received from $0: $1"), 2, { 0, 0 } },
{ "wallops", N_("%WWALLOP%n $0: $1"), 2, { 0, 0 } },
{ "action_wallops", N_("%WWALLOP * $0%n $1"), 2, { 0, 0 } },
{ "error", N_("%_ERROR%_ $0"), 1, { 0 } },
{ "unknown_mode", N_("Unknown mode character $0"), 1, { 0 } },
{ "not_chanop", N_("You're not channel operator in $0"), 1, { 0 } },
/* ---- */
{ NULL, N_("Misc"), 0 },
{ "ignored", N_("Ignoring %_$1%_ from %_$0%_"), 2, { 0, 0 } },
{ "unignored", N_("Unignored %_$0%_"), 1, { 0 } },
{ "ignore_not_found", N_("%_$0%_ is not being ignored"), 1, { 0 } },
{ "ignore_no_ignores", N_("There are no ignores"), 0 },
{ "ignore_header", N_("Ignorance List:"), 0 },
{ "ignore_line", N_("$[-4]0 $1: $2 $3 $4"), 5, { 1, 0, 0, 0, 0 } },
{ "ignore_footer", N_(""), 0 },
{ "talking_in", N_("You are now talking in %_$0%_"), 1, { 0 } },
{ "no_query", N_("No query with %_$0%_"), 1, { 0 } },
{ "no_msgs_got", N_("You have not received a message from anyone yet"), 0 },
{ "no_msgs_sent", N_("You have not sent a message to anyone yet"), 0 }
};

View file

@ -0,0 +1,146 @@
#include "printtext.h"
enum {
IRCTXT_MODULE_NAME,
IRCTXT_FILL_1,
IRCTXT_LAG_DISCONNECTED,
IRCTXT_DISCONNECTED,
IRCTXT_SERVER_LIST,
IRCTXT_SERVER_LOOKUP_LIST,
IRCTXT_SERVER_RECONNECT_LIST,
IRCTXT_RECONNECT_REMOVED,
IRCTXT_RECONNECT_NOT_FOUND,
IRCTXT_QUERY_SERVER_CHANGED,
IRCTXT_FILL_2,
IRCTXT_JOIN,
IRCTXT_PART,
IRCTXT_JOINERROR_TOOMANY,
IRCTXT_JOINERROR_FULL,
IRCTXT_JOINERROR_INVITE,
IRCTXT_JOINERROR_BANNED,
IRCTXT_JOINERROR_BAD_KEY,
IRCTXT_JOINERROR_BAD_MASK,
IRCTXT_JOINERROR_UNAVAIL,
IRCTXT_KICK,
IRCTXT_QUIT,
IRCTXT_QUIT_ONCE,
IRCTXT_INVITE,
IRCTXT_NOT_INVITED,
IRCTXT_NAMES,
IRCTXT_ENDOFNAMES,
IRCTXT_CHANNEL_CREATED,
IRCTXT_TOPIC,
IRCTXT_NO_TOPIC,
IRCTXT_NEW_TOPIC,
IRCTXT_TOPIC_UNSET,
IRCTXT_TOPIC_INFO,
IRCTXT_CHANMODE_CHANGE,
IRCTXT_SERVER_CHANMODE_CHANGE,
IRCTXT_CHANNEL_MODE,
IRCTXT_BANTYPE,
IRCTXT_BANLIST,
IRCTXT_BANLIST_LONG,
IRCTXT_EBANLIST,
IRCTXT_EBANLIST_LONG,
IRCTXT_INVITELIST,
IRCTXT_NO_SUCH_CHANNEL,
IRCTXT_NOT_IN_CHANNELS,
IRCTXT_CURRENT_CHANNEL,
IRCTXT_CHANLIST_HEADER,
IRCTXT_CHANLIST_LINE,
IRCTXT_CHANNEL_SYNCED,
IRCTXT_FILL_4,
IRCTXT_USERMODE_CHANGE,
IRCTXT_USER_MODE,
IRCTXT_AWAY,
IRCTXT_UNAWAY,
IRCTXT_NICK_AWAY,
IRCTXT_NO_SUCH_NICK,
IRCTXT_YOUR_NICK,
IRCTXT_YOUR_NICK_CHANGED,
IRCTXT_NICK_CHANGED,
IRCTXT_NICK_IN_USE,
IRCTXT_NICK_UNAVAILABLE,
IRCTXT_YOUR_NICK_OWNED,
IRCTXT_FILL_5,
IRCTXT_WHOIS,
IRCTXT_WHOIS_IDLE,
IRCTXT_WHOIS_IDLE_SIGNON,
IRCTXT_WHOIS_SERVER,
IRCTXT_WHOIS_OPER,
IRCTXT_WHOIS_CHANNELS,
IRCTXT_WHOIS_AWAY,
IRCTXT_END_OF_WHOIS,
IRCTXT_WHO,
IRCTXT_END_OF_WHO,
IRCTXT_FILL_6,
IRCTXT_OWN_MSG,
IRCTXT_OWN_MSG_CHANNEL,
IRCTXT_OWN_MSG_PRIVATE,
IRCTXT_OWN_MSG_PRIVATE_QUERY,
IRCTXT_OWN_NOTICE,
IRCTXT_OWN_ME,
IRCTXT_OWN_CTCP,
IRCTXT_FILL_7,
IRCTXT_PUBMSG_ME,
IRCTXT_PUBMSG_ME_CHANNEL,
IRCTXT_PUBMSG_HILIGHT,
IRCTXT_PUBMSG_HILIGHT_CHANNEL,
IRCTXT_PUBMSG,
IRCTXT_PUBMSG_CHANNEL,
IRCTXT_MSG_PRIVATE,
IRCTXT_MSG_PRIVATE_QUERY,
IRCTXT_NOTICE_SERVER,
IRCTXT_NOTICE_PUBLIC,
IRCTXT_NOTICE_PUBLIC_OPS,
IRCTXT_NOTICE_PRIVATE,
IRCTXT_ACTION_PRIVATE,
IRCTXT_ACTION_PRIVATE_QUERY,
IRCTXT_ACTION_PUBLIC,
IRCTXT_ACTION_PUBLIC_CHANNEL,
IRCTXT_FILL_8,
IRCTXT_CTCP_REPLY,
IRCTXT_CTCP_PING_REPLY,
IRCTXT_CTCP_REQUESTED,
IRCTXT_FILL_10,
IRCTXT_ONLINE,
IRCTXT_PONG,
IRCTXT_WALLOPS,
IRCTXT_ACTION_WALLOPS,
IRCTXT_ERROR,
IRCTXT_UNKNOWN_MODE,
IRCTXT_NOT_CHANOP,
IRCTXT_FILL_11,
IRCTXT_IGNORED,
IRCTXT_UNIGNORED,
IRCTXT_IGNORE_NOT_FOUND,
IRCTXT_IGNORE_NO_IGNORES,
IRCTXT_IGNORE_HEADER,
IRCTXT_IGNORE_LINE,
IRCTXT_IGNORE_FOOTER,
IRCTXT_TALKING_IN,
IRCTXT_NO_QUERY,
IRCTXT_NO_MSGS_GOT,
IRCTXT_NO_MSGS_SENT
};
extern FORMAT_REC fecommon_irc_formats[];
#define MODULE_FORMATS fecommon_irc_formats

View file

@ -0,0 +1,3 @@
#include "common.h"
#define MODULE_NAME "fe-common/irc"

View file

@ -0,0 +1,17 @@
noinst_LTLIBRARIES = libfe_common_irc_notifylist.la
INCLUDES = \
$(GLIB_CFLAGS) \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core/ \
-I$(top_srcdir)/src/irc/core/ \
-I$(top_srcdir)/src/fe-common/core/ \
-DHELPDIR=\""$(datadir)/irssi/help"\" \
-DSYSCONFDIR=\""$(sysconfdir)"\"
libfe_common_irc_notifylist_la_SOURCES = \
fe-notifylist.c \
module-formats.c
noinst_headers = \
module-formats.h

View file

@ -0,0 +1,241 @@
/*
fe-notifylist.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
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 "module.h"
#include "module-formats.h"
#include "signals.h"
#include "commands.h"
#include "misc.h"
#include "lib-config/iconfig.h"
#include "settings.h"
#include "levels.h"
#include "irc-server.h"
#include "ircnet-setup.h"
#include "irc/notifylist/notifylist.h"
/* add the nick of a hostmask to list if it isn't there already */
static GSList *mask_add_once(GSList *list, const char *mask)
{
char *str, *ptr;
g_return_val_if_fail(mask != NULL, NULL);
ptr = strchr(mask, '!');
str = ptr == NULL ? g_strdup(mask) :
g_strndup(mask, (int) (ptr-mask)+1);
if (gslist_find_icase_string(list, str) == NULL)
return g_slist_append(list, str);
g_free(str);
return list;
}
/* search for online people, print them and update offline list */
static void print_notify_onserver(IRC_SERVER_REC *server, GSList *nicks,
GSList **offline, const char *desc)
{
GSList *tmp;
GString *str;
g_return_if_fail(server != NULL);
g_return_if_fail(offline != NULL);
g_return_if_fail(desc != NULL);
str = g_string_new(NULL);
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
char *nick = tmp->data;
if (!notifylist_ison_server(server, nick))
continue;
g_string_sprintfa(str, "%s, ", nick);
*offline = g_slist_remove(*offline, nick);
}
if (str->len > 0) {
g_string_truncate(str, str->len-2);
printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_ONLINE, desc, str->str);
}
g_string_free(str, TRUE);
}
/* show the notify list, displaying who is on which net */
static void cmd_notify_show(void)
{
GSList *nicks, *offline, *tmp;
IRC_SERVER_REC *server;
if (notifies == NULL)
return;
/* build a list containing only the nicks */
nicks = NULL;
for (tmp = notifies; tmp != NULL; tmp = tmp->next) {
NOTIFYLIST_REC *rec = tmp->data;
nicks = mask_add_once(nicks, rec->mask);
}
offline = g_slist_copy(nicks);
/* print the notifies on specific ircnets */
for (tmp = ircnets; tmp != NULL; tmp = tmp->next) {
IRCNET_REC *rec = tmp->data;
server = (IRC_SERVER_REC *) server_find_ircnet(rec->name);
if (server == NULL) continue;
print_notify_onserver(server, nicks, &offline, rec->name);
}
/* print the notifies on servers without a specified ircnet */
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
server = tmp->data;
if (server->connrec->ircnet != NULL)
continue;
print_notify_onserver(server, nicks, &offline, server->tag);
}
/* print offline people */
if (offline != NULL) {
GString *str;
str = g_string_new(NULL);
for (tmp = offline; tmp != NULL; tmp = tmp->next)
g_string_sprintfa(str, "%s, ", (char *) tmp->data);
g_string_truncate(str, str->len-2);
printformat(NULL,NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_OFFLINE, str->str);
g_string_free(str, TRUE);
g_slist_free(offline);
}
g_slist_foreach(nicks, (GFunc) g_free, NULL);
g_slist_free(nicks);
}
static void notifylist_print(NOTIFYLIST_REC *rec)
{
char idle[MAX_INT_STRLEN], *ircnets;
if (rec->idle_check_time <= 0)
idle[0] = '\0';
else
g_snprintf(idle, sizeof(idle), "%d", rec->idle_check_time);
ircnets = rec->ircnets == NULL ? NULL :
g_strjoinv(",", rec->ircnets);
printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_NOTIFY_LIST,
rec->mask, ircnets != NULL ? ircnets : "",
rec->away_check ? "-away" : "", idle);
g_free_not_null(ircnets);
}
static void cmd_notifylist_show(void)
{
g_slist_foreach(notifies, (GFunc) notifylist_print, NULL);
}
static void cmd_notify(const char *data)
{
if (*data == '\0') {
cmd_notify_show();
signal_stop();
}
if (g_strcasecmp(data, "-list") == 0) {
cmd_notifylist_show();
signal_stop();
}
}
static void notifylist_joined(IRC_SERVER_REC *server, const char *nick,
const char *username, const char *host,
const char *realname, const char *awaymsg)
{
g_return_if_fail(nick != NULL);
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_JOIN,
nick, username, host, realname,
server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet);
}
static void notifylist_left(IRC_SERVER_REC *server, const char *nick,
const char *username, const char *host,
const char *realname, const char *awaymsg)
{
g_return_if_fail(nick != NULL);
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_PART,
nick, username, host, realname,
server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet);
}
static void notifylist_away(IRC_SERVER_REC *server, const char *nick,
const char *username, const char *host,
const char *realname, const char *awaymsg)
{
g_return_if_fail(nick != NULL);
if (awaymsg != NULL) {
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_AWAY,
nick, username, host, realname, awaymsg,
server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet);
} else {
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_UNAWAY,
nick, username, host, realname,
server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet);
}
}
static void notifylist_unidle(IRC_SERVER_REC *server, const char *nick,
const char *username, const char *host,
const char *realname, const char *awaymsg)
{
g_return_if_fail(nick != NULL);
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_UNIDLE,
nick, username, host, realname, awaymsg != NULL ? awaymsg : "",
server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet);
}
void fe_notifylist_init(void)
{
command_bind("notify", NULL, (SIGNAL_FUNC) cmd_notify);
signal_add("notifylist joined", (SIGNAL_FUNC) notifylist_joined);
signal_add("notifylist left", (SIGNAL_FUNC) notifylist_left);
signal_add("notifylist away changed", (SIGNAL_FUNC) notifylist_away);
signal_add("notifylist unidle", (SIGNAL_FUNC) notifylist_unidle);
}
void fe_notifylist_deinit(void)
{
command_unbind("notify", (SIGNAL_FUNC) cmd_notify);
signal_remove("notifylist joined", (SIGNAL_FUNC) notifylist_joined);
signal_remove("notifylist left", (SIGNAL_FUNC) notifylist_left);
signal_remove("notifylist away changed", (SIGNAL_FUNC) notifylist_away);
signal_remove("notifylist unidle", (SIGNAL_FUNC) notifylist_unidle);
}

View file

@ -0,0 +1,39 @@
/*
module-formats.c : irssi
Copyright (C) 2000 Timo Sirainen
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 "module.h"
#include "printtext.h"
FORMAT_REC fecommon_irc_notifylist_formats[] =
{
{ MODULE_NAME, N_("Notifylist"), 0 },
/* ---- */
{ NULL, N_("Notifylist"), 0 },
{ "notify_join", N_("%_$0%_ %K[%n$1@$2%K] [%n%_$3%_%K]%n has joined to $4"), 5, { 0, 0, 0, 0, 0 } },
{ "notify_part", N_("%_$0%_ has left $4"), 5, { 0, 0, 0, 0, 0 } },
{ "notify_away", N_("%_$0%_ %K[%n$5%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n is now away: $4"), 6, { 0, 0, 0, 0, 0, 0 } },
{ "notify_unaway", N_("%_$0%_ %K[%n$4%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n is now unaway"), 5, { 0, 0, 0, 0, 0 } },
{ "notify_unidle", N_("%_$0%_ %K[%n$5%K]%n %K[%n$1@$2%K] [%n%_$3%_%K]%n just stopped idling"), 6, { 0, 0, 0, 0, 0, 0 } },
{ "notify_online", N_("On $0: %_$1%_"), 2, { 0, 0 } },
{ "notify_offline", N_("Offline: $0"), 1, { 0 } },
{ "notify_list", N_("$0: $1 $2 $3"), 4, { 0, 0, 0, 0 } }
};

View file

@ -0,0 +1,19 @@
#include "printtext.h"
enum {
IRCTXT_MODULE_NAME,
IRCTXT_FILL_1,
IRCTXT_NOTIFY_JOIN,
IRCTXT_NOTIFY_PART,
IRCTXT_NOTIFY_AWAY,
IRCTXT_NOTIFY_UNAWAY,
IRCTXT_NOTIFY_UNIDLE,
IRCTXT_NOTIFY_ONLINE,
IRCTXT_NOTIFY_OFFLINE,
IRCTXT_NOTIFY_LIST
};
extern FORMAT_REC fecommon_irc_notifylist_formats[];
#define MODULE_FORMATS fecommon_irc_notifylist_formats