1
0
mirror of https://github.com/irssi/irssi.git synced 2024-06-23 06:35:36 +00:00

Added/moved several "typedef struct _XXX XXX;" to common.h so that

they're known to all files and I don't need those stupid "void *xxx"
anymore just to avoid useless #include. Header files themselves don't
either include others as often anymore.

Added channel->ownnick to point to our NICK_REC in channel's nicks.
Gives a minor speedup in few places :)

Moved completion specific lastmsgs from channel/server core records to
fe-common/core specific records. Also changed the nick completion logic
a bit so it should work better now. Removed
completion_keep_publics_count setting, but changed the meaning of
completion_keep_publics to same as _count was before. Nick completion
doesn't have any time specific code anymore.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1034 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2001-01-01 07:45:54 +00:00 committed by cras
parent 21f9da6092
commit 4a33801669
50 changed files with 316 additions and 266 deletions

View File

@ -62,4 +62,23 @@ int g_input_add_full(GIOChannel *source, int priority, int condition,
#define MAX_INT_STRLEN ((sizeof(int) * CHAR_BIT + 2) / 3 + 1)
typedef struct _IPADDR IPADDR;
typedef struct _CONFIG_REC CONFIG_REC;
typedef struct _CONFIG_NODE CONFIG_NODE;
typedef struct _LINEBUF_REC LINEBUF_REC;
typedef struct _NET_SENDBUF_REC NET_SENDBUF_REC;
typedef struct _RAWLOG_REC RAWLOG_REC;
typedef struct _CHATNET_REC CHATNET_REC;
typedef struct _SERVER_REC SERVER_REC;
typedef struct _WI_ITEM_REC WI_ITEM_REC;
typedef struct _CHANNEL_REC CHANNEL_REC;
typedef struct _QUERY_REC QUERY_REC;
typedef struct _NICK_REC NICK_REC;
typedef struct _SERVER_CONNECT_REC SERVER_CONNECT_REC;
typedef struct _SERVER_SETUP_REC SERVER_SETUP_REC;
typedef struct _CHANNEL_SETUP_REC CHANNEL_SETUP_REC;
#endif

View File

@ -5,7 +5,9 @@
char *topic;
char *topic_by;
time_t topic_time;
GHashTable *nicks; /* list of nicks */
NICK_REC *ownnick; /* our own nick */
unsigned int no_modes:1; /* channel doesn't support modes */
char *mode;
@ -21,6 +23,3 @@ unsigned int joined:1; /* Have we even received JOIN event for this channel? */
unsigned int left:1; /* You just left the channel */
unsigned int kicked:1; /* You just got kicked */
unsigned int destroying:1;
GSList *lastmsgs; /* List of nicks who last send message */
GSList *lastownmsgs; /* List of nicks who last send message to you */

View File

@ -3,7 +3,7 @@
#include "modules.h"
typedef struct {
struct _CHANNEL_SETUP_REC {
char *name;
char *chatnet;
char *password;
@ -13,7 +13,7 @@ typedef struct {
unsigned int autojoin:1;
GHashTable *module_data;
} CHANNEL_SETUP_REC;
};
extern GSList *setupchannels;

View File

@ -1,7 +1,7 @@
#ifndef __CHANNELS_H
#define __CHANNELS_H
#include "servers.h"
#include "modules.h"
/* Returns CHANNEL_REC if it's channel, NULL if it isn't. */
#define CHANNEL(channel) \
@ -12,9 +12,9 @@
(CHANNEL(channel) ? TRUE : FALSE)
#define STRUCT_SERVER_REC SERVER_REC
typedef struct {
struct _CHANNEL_REC {
#include "channel-rec.h"
} CHANNEL_REC;
};
extern GSList *channels;

View File

@ -30,10 +30,8 @@
GSList *chatnets; /* list of available chat networks */
void chatnet_read(CHATNET_REC *chatnet, void *nodep)
void chatnet_read(CHATNET_REC *chatnet, CONFIG_NODE *node)
{
CONFIG_NODE *node = nodep;
g_return_if_fail(chatnet != NULL);
g_return_if_fail(node != NULL);
g_return_if_fail(node->key != NULL);
@ -49,11 +47,9 @@ void chatnet_read(CHATNET_REC *chatnet, void *nodep)
chatnets = g_slist_append(chatnets, chatnet);
}
void *chatnet_save(CHATNET_REC *chatnet, void *parentnode)
CONFIG_NODE *chatnet_save(CHATNET_REC *chatnet, CONFIG_NODE *node)
{
CONFIG_NODE *node = parentnode;
g_return_val_if_fail(parentnode != NULL, NULL);
g_return_val_if_fail(node != NULL, NULL);
g_return_val_if_fail(chatnet != NULL, NULL);
node = config_node_section(node, chatnet->name, NODE_TYPE_BLOCK);

View File

@ -10,15 +10,15 @@
#define IS_CHATNET(chatnet) \
(CHATNET(chatnet) ? TRUE : FALSE)
typedef struct {
struct _CHATNET_REC {
#include "chatnet-rec.h"
} CHATNET_REC;
};
extern GSList *chatnets; /* list of available chat networks */
/* read/save to configuration file */
void chatnet_read(CHATNET_REC *chatnet, void *node);
void *chatnet_save(CHATNET_REC *chatnet, void *parentnode);
void chatnet_read(CHATNET_REC *chatnet, CONFIG_NODE *node);
CONFIG_NODE *chatnet_save(CHATNET_REC *chatnet, CONFIG_NODE *parentnode);
/* add the chatnet to chat networks list */
void chatnet_create(CHATNET_REC *chatnet);

View File

@ -19,6 +19,7 @@
*/
#include "module.h"
#include "modules.h"
#include "signals.h"
#include "expandos.h"
#include "settings.h"
@ -26,6 +27,7 @@
#include "misc.h"
#include "irssi-version.h"
#include "servers.h"
#include "channels.h"
#include "queries.h"
#include "window-item-def.h"

View File

@ -2,7 +2,6 @@
#define __EXPANDOS_H
#include "signals.h"
#include "servers.h"
/* first argument of signal must match to active .. */
typedef enum {

View File

@ -1,7 +1,6 @@
#ifndef __IGNORE_H
#define __IGNORE_H
#include "servers.h"
#ifdef HAVE_REGEX_H
# include <regex.h>
#endif

View File

@ -31,12 +31,12 @@
too high. */
#define MAX_CHARS_IN_LINE 65536
typedef struct {
struct _LINEBUF_REC {
int len;
int alloc;
int remove;
char *str;
} LINEBUF_REC;
};
static inline int nearest_power(int num)
{

View File

@ -1,8 +1,6 @@
#ifndef __LINE_SPLIT_H
#define __LINE_SPLIT_H
typedef struct _LINEBUF_REC LINEBUF_REC;
/* line-split `data'. Initially `*buffer' should contain NULL. */
int line_split(const char *data, int len, char **output, LINEBUF_REC **buffer);
void line_split_free(LINEBUF_REC *buffer);

View File

@ -1,8 +1,6 @@
#ifndef __LOG_H
#define __LOG_H
#include "servers.h"
enum {
LOG_ITEM_TARGET, /* channel, query, .. */
LOG_ITEM_WINDOW_REFNUM

View File

@ -1,8 +1,6 @@
#ifndef __MASKS_H
#define __MASKS_H
#include "servers.h"
int mask_match(SERVER_REC *server, const char *mask,
const char *nick, const char *user, const char *host);
int mask_match_address(SERVER_REC *server, const char *mask,

View File

@ -3,8 +3,6 @@
#define DEFAULT_BUFFER_SIZE 8192
typedef struct _NET_SENDBUF_REC NET_SENDBUF_REC;
/* Create new buffer - if `bufsize' is zero or less, DEFAULT_BUFFER_SIZE
is used */
NET_SENDBUF_REC *net_sendbuffer_create(GIOChannel *handle, int bufsize);

View File

@ -7,7 +7,7 @@
# include <netinet/in.h>
#endif
struct _ipaddr {
struct _IPADDR {
unsigned short family;
union {
#ifdef HAVE_IPV6
@ -18,8 +18,6 @@ struct _ipaddr {
} addr;
};
typedef struct _ipaddr IPADDR;
/* maxmimum string length of IP address */
#ifdef HAVE_IPV6
# define MAX_IP_LEN INET6_ADDRSTRLEN

View File

@ -22,6 +22,8 @@
#include "signals.h"
#include "misc.h"
#include "servers.h"
#include "channels.h"
#include "nicklist.h"
#include "masks.h"

View File

@ -1,9 +1,6 @@
#ifndef __NICKLIST_H
#define __NICKLIST_H
#include "servers.h"
#include "channels.h"
/* Returns NICK_REC if it's nick, NULL if it isn't. */
#define NICK(server) \
MODULE_CHECK_CAST(server, NICK_REC, type, "NICK")
@ -11,9 +8,9 @@
#define IS_NICK(server) \
(NICK(server) ? TRUE : FALSE)
typedef struct {
struct _NICK_REC {
#include "nick-rec.h"
} NICK_REC;
};
/* Add new nick to list */
NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick,

View File

@ -22,6 +22,7 @@
#include "signals.h"
#include "misc.h"
#include "servers.h"
#include "queries.h"
GSList *queries;

View File

@ -1,7 +1,7 @@
#ifndef __QUERIES_H
#define __QUERIES_H
#include "servers.h"
#include "modules.h"
/* Returns QUERY_REC if it's query, NULL if it isn't. */
#define QUERY(query) \
@ -12,9 +12,9 @@
(QUERY(query) ? TRUE : FALSE)
#define STRUCT_SERVER_REC SERVER_REC
typedef struct {
struct _QUERY_REC {
#include "query-rec.h"
} QUERY_REC;
};
extern GSList *queries;

View File

@ -1,13 +1,13 @@
#ifndef __RAWLOG_H
#define __RAWLOG_H
typedef struct {
struct _RAWLOG_REC {
int logging;
int handle;
int nlines;
GSList *lines;
} RAWLOG_REC;
};
RAWLOG_REC *rawlog_create(void);
void rawlog_destroy(RAWLOG_REC *rawlog);

View File

@ -13,7 +13,7 @@ char *nick; /* current nick */
unsigned int connected:1; /* connected to server */
unsigned int connection_lost:1; /* Connection lost unintentionally */
void *handle; /* NET_SENDBUF_REC socket */
NET_SENDBUF_REC *handle;
int readtag; /* input tag */
/* for net_connect_nonblock() */
@ -26,8 +26,8 @@ GHashTable *eventtable; /* "event xxx" : GSList* of REDIRECT_RECs */
GHashTable *eventgrouptable; /* event group : GSList* of REDIRECT_RECs */
GHashTable *cmdtable; /* "command xxx" : REDIRECT_CMD_REC* */
void *rawlog;
void *buffer; /* receive buffer */
RAWLOG_REC *rawlog;
LINEBUF_REC *buffer; /* receive buffer */
GHashTable *module_data;
char *version; /* server version */
@ -41,8 +41,6 @@ time_t lag_sent; /* 0 or time when last lag query was sent to server */
time_t lag_last_check; /* last time we checked lag */
int lag; /* server lag in milliseconds */
GSList *lastmsgs; /* List of nicks who last send you msg */
GSList *channels;
GSList *queries;
@ -52,7 +50,7 @@ GSList *queries;
/* join to a number of channels, channels are specified in `data' separated
with commas. there can exist other information after first space like
channel keys etc. */
void (*channels_join)(void *server, const char *data, int automatic);
void (*channels_join)(SERVER_REC *server, const char *data, int automatic);
/* returns true if `flag' indicates a nick flag (op/voice/halfop) */
int (*isnickflag)(char flag);
/* returns true if `flag' indicates a channel */
@ -61,11 +59,11 @@ int (*ischannel)(char flag);
of them aren't supported '\0' can be used. */
const char *(*get_nick_flags)(void);
/* send public or private message to server */
void (*send_message)(void *server, const char *target, const char *msg);
void (*send_message)(SERVER_REC *server, const char *target, const char *msg);
/* -- Default implementations are used if NULL -- */
void *(*channel_find_func)(void *server, const char *name);
void *(*query_find_func)(void *server, const char *nick);
CHANNEL_REC *(*channel_find_func)(SERVER_REC *server, const char *name);
QUERY_REC *(*query_find_func)(SERVER_REC *server, const char *nick);
int (*mask_match_func)(const char *mask, const char *data);
/* returns true if `msg' was meant for `nick' */
int (*nick_match_msg)(const char *nick, const char *msg);

View File

@ -23,6 +23,7 @@
#include "network.h"
#include "signals.h"
#include "servers.h"
#include "servers-setup.h"
#include "servers-reconnect.h"

View File

@ -1,8 +1,6 @@
#ifndef __SERVERS_REDIRECT_H
#define __SERVERS_REDIRECT_H
#include "servers.h"
typedef struct {
int last; /* number of "last" events at the start of the events list */
GSList *events; /* char* list of events */

View File

@ -1,7 +1,7 @@
#ifndef __SERVERS_SETUP_H
#define __SERVERS_SETUP_H
#include "servers.h"
#include "modules.h"
#define SERVER_SETUP(server) \
MODULE_CHECK_CAST(server, SERVER_SETUP_REC, type, "SERVER SETUP")
@ -10,9 +10,9 @@
(SERVER_SETUP(server) ? TRUE : FALSE)
/* servers */
typedef struct {
struct _SERVER_SETUP_REC {
#include "server-setup-rec.h"
} SERVER_SETUP_REC;
};
extern GSList *setupservers;

View File

@ -3,10 +3,6 @@
#include "modules.h"
#ifndef __NETWORK_H
typedef struct _ipaddr IPADDR;
#endif
/* Returns SERVER_REC if it's server, NULL if it isn't. */
#define SERVER(server) \
MODULE_CHECK_CAST(server, SERVER_REC, type, "SERVER")
@ -23,19 +19,14 @@ typedef struct _ipaddr IPADDR;
/* all strings should be either NULL or dynamically allocated */
/* address and nick are mandatory, rest are optional */
typedef struct {
struct _SERVER_CONNECT_REC {
#include "server-connect-rec.h"
} SERVER_CONNECT_REC;
};
#define STRUCT_SERVER_CONNECT_REC SERVER_CONNECT_REC
typedef struct {
struct _SERVER_REC {
#include "server-rec.h"
} SERVER_REC;
typedef struct {
time_t time;
char *nick;
} LAST_MSG_REC;
};
extern GSList *servers, *lookup_servers;

View File

@ -1,10 +1,6 @@
#ifndef __SETTINGS_H
#define __SETTINGS_H
#ifndef __ICONFIG_H
typedef struct _config_rec CONFIG_REC;
#endif
enum {
SETTING_TYPE_STRING,
SETTING_TYPE_INT,

View File

@ -2,7 +2,6 @@
#define __SPECIAL_VARS_H
#include "signals.h"
#include "servers.h"
#define PARSE_FLAG_GETNAME 0x01 /* return argument name instead of it's value */
#define PARSE_FLAG_ISSET_ANY 0x02 /* arg_used field specifies that at least one of the $variables was non-empty */

View File

@ -2,8 +2,8 @@
#define __WINDOW_ITEM_DEF_H
#define STRUCT_SERVER_REC SERVER_REC
typedef struct {
struct _WI_ITEM_REC {
#include "window-item-rec.h"
} WI_ITEM_REC;
};
#endif

View File

@ -4,6 +4,7 @@ int type; /* module_get_uniq_id("CHANNEL/QUERY/xxx", 0) */
int chat_type; /* chat_protocol_lookup(xx) */
GHashTable *module_data;
void *window;
STRUCT_SERVER_REC *server;
char *name;

View File

@ -22,10 +22,8 @@
#include "signals.h"
#include "commands.h"
#include "misc.h"
#include "lib-config/iconfig.h"
#include "settings.h"
#include "servers.h"
#include "chatnets.h"
#include "servers-setup.h"
#include "channels.h"
@ -36,12 +34,17 @@
#include "completion.h"
#include "window-items.h"
static int complete_tag;
static int keep_privates_count, keep_publics_count;
static int completion_lowercase;
static const char *completion_char, *cmdchars;
#define SERVER_LAST_MSG_ADD(server, nick) \
last_msg_add(&server->lastmsgs, nick)
#define SERVER_LAST_MSG_DESTROY(server, nick) \
last_msg_destroy(&server->lastmsgs, nick)
last_msg_add(&((MODULE_SERVER_REC *) MODULE_DATA(server))->lastmsgs, \
nick, TRUE, keep_privates_count)
#define CHANNEL_LAST_MSG_ADD(channel, nick, own) \
last_msg_add(&((MODULE_CHANNEL_REC *) MODULE_DATA(channel))->lastmsgs, \
nick, own, keep_publics_count)
static LAST_MSG_REC *last_msg_find(GSList *list, const char *nick)
{
@ -56,20 +59,43 @@ static LAST_MSG_REC *last_msg_find(GSList *list, const char *nick)
return NULL;
}
static void last_msg_add(GSList **list, const char *nick)
static void last_msg_dec_owns(GSList *list)
{
LAST_MSG_REC *rec;
while (list != NULL) {
rec = list->data;
if (rec->own) rec->own--;
list = list->next;
}
}
static void last_msg_add(GSList **list, const char *nick, int own, int max)
{
LAST_MSG_REC *rec;
rec = last_msg_find(*list, nick);
if (rec != NULL) {
/* msg already exists, update it */
*list = g_slist_remove(*list, rec);
*list = g_slist_remove(*list, rec);
if (own)
rec->own = max;
else if (rec->own)
rec->own--;
} else {
rec = g_new(LAST_MSG_REC, 1);
rec->nick = g_strdup(nick);
if (g_slist_length(*list) == max)
*list = g_slist_remove(*list, (*list)->data);
rec->own = own ? max : 0;
}
rec->time = time(NULL);
last_msg_dec_owns(*list);
*list = g_slist_prepend(*list, rec);
}
@ -81,77 +107,17 @@ static void last_msg_destroy(GSList **list, LAST_MSG_REC *rec)
g_free(rec);
}
static void last_msgs_remove_old(GSList **list, int timeout, time_t now)
{
GSList *tmp, *next;
for (tmp = *list; tmp != NULL; tmp = next) {
LAST_MSG_REC *rec = tmp->data;
next = tmp->next;
if (now-rec->time > timeout)
last_msg_destroy(list, rec);
}
}
static int last_msg_cmp(LAST_MSG_REC *m1, LAST_MSG_REC *m2)
{
return m1->time < m2->time ? 1 : -1;
}
static int nick_completion_timeout(void)
{
GSList *tmp;
time_t now;
int len, keep_private_count;
int keep_msgs_time, keep_msgs_count, keep_ownmsgs_time;
keep_private_count = settings_get_int("completion_keep_privates");
now = time(NULL);
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
SERVER_REC *server = tmp->data;
len = g_slist_length(server->lastmsgs);
if (len > 0 && len >= keep_private_count) {
/* remove the oldest msg nick. */
GSList *link = g_slist_last(server->lastmsgs);
SERVER_LAST_MSG_DESTROY(server, link->data);
}
}
keep_ownmsgs_time = settings_get_int("completion_keep_ownpublics");
keep_msgs_time = settings_get_int("completion_keep_publics");
keep_msgs_count = settings_get_int("completion_keep_publics_count");
for (tmp = channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *channel = tmp->data;
last_msgs_remove_old(&channel->lastmsgs, keep_msgs_time, now);
if (keep_msgs_count == 0 ||
(int)g_slist_length(channel->lastownmsgs) > keep_msgs_count) {
last_msgs_remove_old(&channel->lastownmsgs,
keep_ownmsgs_time, now);
}
}
return 1;
}
static void sig_message_public(SERVER_REC *server, const char *msg,
const char *nick, const char *address,
const char *target)
{
CHANNEL_REC *channel;
GSList **list;
int own;
channel = channel_find(server, target);
if (channel != NULL) {
list = nick_match_msg(channel, msg, server->nick) ?
&channel->lastownmsgs :
&channel->lastmsgs;
last_msg_add(list, nick);
own = nick_match_msg(channel, msg, server->nick);
CHANNEL_LAST_MSG_ADD(channel, nick, own);
}
}
@ -164,7 +130,8 @@ static void sig_message_private(SERVER_REC *server, const char *msg,
static void cmd_msg(const char *data, SERVER_REC *server)
{
GHashTable *optlist;
char *target, *msg;
NICK_REC *nick;
char *target, *msg, *p;
void *free_arg;
g_return_if_fail(data != NULL);
@ -175,46 +142,74 @@ static void cmd_msg(const char *data, SERVER_REC *server)
return;
server = cmd_options_get_server("msg", optlist, server);
if (*target != '\0' && *msg != '\0' && *target != '=' &&
server != NULL && !server->ischannel(*target))
SERVER_LAST_MSG_ADD(server, target);
if (server != NULL && *target != '\0' && *msg != '\0' &&
query_find(server, target) == NULL) {
CHANNEL_REC *channel = channel_find(server, target);
MODULE_CHANNEL_REC *mchannel;
mchannel = MODULE_DATA(channel);
if (channel != NULL) {
/* channel msg - if first word in line is nick,
add it to lastmsgs */
p = strchr(msg, ' ');
if (p != NULL && p != msg) {
*p = '\0';
nick = nicklist_find(channel, msg);
if (nick == NULL) {
/* probably ':' or ',' or some other
char after nick, try without it */
p[-1] = '\0';
nick = nicklist_find(channel, msg);
}
if (nick != NULL && nick != channel->ownnick) {
CHANNEL_LAST_MSG_ADD(channel,
nick->nick, TRUE);
}
}
} else if (!server->ischannel(*target)) {
/* private msg */
SERVER_LAST_MSG_ADD(server, target);
}
}
cmd_params_free(free_arg);
}
static void sig_nick_removed(CHANNEL_REC *channel, NICK_REC *nick)
{
MODULE_CHANNEL_REC *mchannel;
LAST_MSG_REC *rec;
rec = last_msg_find(channel->lastownmsgs, nick->nick);
if (rec != NULL) last_msg_destroy(&channel->lastownmsgs, rec);
rec = last_msg_find(channel->lastmsgs, nick->nick);
if (rec != NULL) last_msg_destroy(&channel->lastmsgs, rec);
mchannel = MODULE_DATA(channel);
rec = last_msg_find(mchannel->lastmsgs, nick->nick);
if (rec != NULL) last_msg_destroy(&mchannel->lastmsgs, rec);
}
static void sig_nick_changed(CHANNEL_REC *channel, NICK_REC *nick,
const char *oldnick)
{
MODULE_CHANNEL_REC *mchannel;
LAST_MSG_REC *rec;
rec = last_msg_find(channel->lastownmsgs, oldnick);
mchannel = MODULE_DATA(channel);
rec = last_msg_find(mchannel->lastmsgs, oldnick);
if (rec != NULL) {
g_free(rec->nick);
rec->nick = g_strdup(nick->nick);
}
}
rec = last_msg_find(channel->lastmsgs, oldnick);
if (rec != NULL) {
g_free(rec->nick);
rec->nick = g_strdup(nick->nick);
}
static int last_msg_cmp(LAST_MSG_REC *m1, LAST_MSG_REC *m2)
{
return m1->time < m2->time ? 1 : -1;
}
/* Complete /MSG from specified server */
static void completion_msg_server(GSList **list, SERVER_REC *server,
const char *nick, const char *prefix)
{
MODULE_SERVER_REC *mserver;
LAST_MSG_REC *msg;
GSList *tmp;
int len;
@ -222,7 +217,8 @@ static void completion_msg_server(GSList **list, SERVER_REC *server,
g_return_if_fail(nick != NULL);
len = strlen(nick);
for (tmp = server->lastmsgs; tmp != NULL; tmp = tmp->next) {
mserver = MODULE_DATA(server);
for (tmp = mserver->lastmsgs; tmp != NULL; tmp = tmp->next) {
LAST_MSG_REC *rec = tmp->data;
if (len != 0 && g_strncasecmp(rec->nick, nick, len) != 0)
@ -290,49 +286,55 @@ static GList *completion_msg(SERVER_REC *win_server,
return convert_msglist(list);
}
static void complete_from_nicklist(GList **outlist, GSList *list,
const char *nick, const char *prefix)
static void complete_from_nicklist(GList **outlist, CHANNEL_REC *channel,
const char *nick, const char *suffix)
{
MODULE_CHANNEL_REC *mchannel;
GSList *tmp;
GList *ownlist;
char *str;
int len, lowercase;
lowercase = settings_get_bool("completion_nicks_lowercase");
int len;
/* go through the last x nicks who have said something in the channel.
nicks of all the "own messages" are placed before others */
ownlist = NULL;
len = strlen(nick);
for (tmp = list; tmp != NULL; tmp = tmp->next) {
mchannel = MODULE_DATA(channel);
for (tmp = mchannel->lastmsgs; tmp != NULL; tmp = tmp->next) {
LAST_MSG_REC *rec = tmp->data;
if (g_strncasecmp(rec->nick, nick, len) == 0 &&
glist_find_icase_string(*outlist, rec->nick) == NULL) {
str = g_strconcat(rec->nick, prefix, NULL);
if (lowercase) g_strdown(str);
*outlist = g_list_append(*outlist, str);
str = g_strconcat(rec->nick, suffix, NULL);
if (completion_lowercase) g_strdown(str);
if (rec->own)
ownlist = g_list_append(ownlist, str);
else
*outlist = g_list_append(*outlist, str);
}
}
*outlist = g_list_concat(ownlist, *outlist);
}
static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick,
const char *prefix)
const char *suffix)
{
GSList *nicks, *tmp;
GList *list;
char *str;
int lowercase, len;
int len;
g_return_val_if_fail(channel != NULL, NULL);
g_return_val_if_fail(nick != NULL, NULL);
if (*nick == '\0') return NULL;
lowercase = settings_get_bool("completion_nicks_lowercase");
if (suffix != NULL && *suffix == '\0')
suffix = NULL;
if (prefix != NULL && *prefix == '\0')
prefix = NULL;
/* put first the nicks who have recently said something [to you] */
/* put first the nicks who have recently said something */
list = NULL;
complete_from_nicklist(&list, channel->lastownmsgs, nick, prefix);
complete_from_nicklist(&list, channel->lastmsgs, nick, prefix);
complete_from_nicklist(&list, channel, nick, suffix);
/* and add the rest of the nicks too */
len = strlen(nick);
@ -342,9 +344,9 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick,
if (g_strncasecmp(rec->nick, nick, len) == 0 &&
glist_find_icase_string(list, rec->nick) == NULL &&
g_strcasecmp(rec->nick, channel->server->nick) != 0) {
str = g_strconcat(rec->nick, prefix, NULL);
if (lowercase) g_strdown(str);
rec != channel->ownnick) {
str = g_strconcat(rec->nick, suffix, NULL);
if (completion_lowercase) g_strdown(str);
list = g_list_append(list, str);
}
}
@ -353,6 +355,8 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick,
return list;
}
/* append all strings in list2 to list1 that already aren't there and
free list2 */
static GList *completion_joinlist(GList *list1, GList *list2)
{
GList *old;
@ -396,7 +400,8 @@ GList *completion_get_channels(SERVER_REC *server, const char *word)
for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) {
CHANNEL_SETUP_REC *rec = tmp->data;
if (g_strncasecmp(rec->name, word, len) == 0)
if (g_strncasecmp(rec->name, word, len) == 0 &&
glist_find_icase_string(list, rec->name) == NULL)
list = g_list_append(list, g_strdup(rec->name));
}
@ -410,20 +415,19 @@ static void complete_window_nicks(GList **list, WINDOW_REC *window,
CHANNEL_REC *channel;
GList *tmplist;
GSList *tmp;
const char *nickprefix;
const char *nicksuffix;
nickprefix = *linestart != '\0' ? NULL :
settings_get_str("completion_char");
nicksuffix = *linestart != '\0' ? NULL : completion_char;
channel = CHANNEL(window->active);
/* first the active channel */
if (channel != NULL) {
tmplist = completion_channel_nicks(channel, word, nickprefix);
tmplist = completion_channel_nicks(channel, word, nicksuffix);
*list = completion_joinlist(*list, tmplist);
}
if (nickprefix != NULL) {
if (nicksuffix != NULL) {
/* completing nick at the start of line - probably answering
to some other nick, don't even try to complete from
non-active channels */
@ -435,7 +439,7 @@ static void complete_window_nicks(GList **list, WINDOW_REC *window,
channel = CHANNEL(tmp->data);
if (channel != NULL && tmp->data != window->active) {
tmplist = completion_channel_nicks(channel, word,
nickprefix);
nicksuffix);
*list = completion_joinlist(*list, tmplist);
}
}
@ -447,7 +451,6 @@ static void sig_complete_word(GList **list, WINDOW_REC *window,
SERVER_REC *server;
CHANNEL_REC *channel;
QUERY_REC *query;
const char *cmdchars;
char *prefix;
g_return_if_fail(list != NULL);
@ -469,7 +472,6 @@ static void sig_complete_word(GList **list, WINDOW_REC *window,
if (server == NULL || !server->connected)
return;
cmdchars = settings_get_str("cmdchars");
if (*linestart == '\0' && *word == '\0') {
/* pressed TAB at the start of line - add /MSG */
prefix = g_strdup_printf("%cmsg", *cmdchars);
@ -645,7 +647,7 @@ static void event_text(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
line = settings_get_bool("expand_escapes") ?
expand_escapes(data, server, item) : g_strdup(data);
comp_char = *settings_get_str("completion_char");
comp_char = *completion_char;
/* check for automatic nick completion */
ptr = NULL;
@ -682,35 +684,47 @@ static void event_text(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
static void sig_server_disconnected(SERVER_REC *server)
{
MODULE_SERVER_REC *mserver;
g_return_if_fail(server != NULL);
while (server->lastmsgs)
SERVER_LAST_MSG_DESTROY(server, server->lastmsgs->data);
mserver = MODULE_DATA(server);
while (mserver->lastmsgs)
last_msg_destroy(&mserver->lastmsgs, mserver->lastmsgs->data);
}
static void sig_channel_destroyed(CHANNEL_REC *channel)
{
MODULE_CHANNEL_REC *mchannel;
g_return_if_fail(channel != NULL);
while (channel->lastmsgs != NULL)
last_msg_destroy(&channel->lastmsgs, channel->lastmsgs->data);
while (channel->lastownmsgs != NULL)
last_msg_destroy(&channel->lastownmsgs, channel->lastownmsgs->data);
mchannel = MODULE_DATA(channel);
while (mchannel->lastmsgs != NULL) {
last_msg_destroy(&mchannel->lastmsgs,
mchannel->lastmsgs->data);
}
}
static void read_settings(void)
{
keep_privates_count = settings_get_int("completion_keep_privates");
keep_publics_count = settings_get_int("completion_keep_publics");
completion_lowercase = settings_get_bool("completion_nicks_lowercase");
completion_char = settings_get_str("completion_char");
cmdchars = settings_get_str("cmdchars");
}
void chat_completion_init(void)
{
settings_add_str("completion", "completion_char", ":");
settings_add_bool("completion", "completion_auto", FALSE);
settings_add_int("completion", "completion_keep_publics", 180);
settings_add_int("completion", "completion_keep_publics_count", 50);
settings_add_int("completion", "completion_keep_ownpublics", 360);
settings_add_int("completion", "completion_keep_publics", 50);
settings_add_int("completion", "completion_keep_privates", 10);
settings_add_bool("completion", "expand_escapes", FALSE);
settings_add_bool("completion", "completion_nicks_lowercase", FALSE);
complete_tag = g_timeout_add(1000, (GSourceFunc) nick_completion_timeout, NULL);
read_settings();
signal_add("complete word", (SIGNAL_FUNC) sig_complete_word);
signal_add("complete command msg", (SIGNAL_FUNC) sig_complete_msg);
signal_add("complete command connect", (SIGNAL_FUNC) sig_complete_connect);
@ -723,12 +737,11 @@ void chat_completion_init(void)
signal_add("send text", (SIGNAL_FUNC) event_text);
signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
}
void chat_completion_deinit(void)
{
g_source_remove(complete_tag);
signal_remove("complete word", (SIGNAL_FUNC) sig_complete_word);
signal_remove("complete command msg", (SIGNAL_FUNC) sig_complete_msg);
signal_remove("complete command connect", (SIGNAL_FUNC) sig_complete_connect);
@ -741,4 +754,5 @@ void chat_completion_deinit(void)
signal_remove("send text", (SIGNAL_FUNC) event_text);
signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
}

View File

@ -27,6 +27,7 @@
#include "misc.h"
#include "settings.h"
#include "channels.h"
#include "channels-setup.h"
#include "nicklist.h"
@ -34,7 +35,7 @@
#include "window-items.h"
#include "printtext.h"
static void signal_channel_created(CHANNEL_REC *channel, gpointer automatic)
static void signal_channel_created(CHANNEL_REC *channel, void *automatic)
{
if (window_item_find(channel->server, channel->name) == NULL) {
window_item_create((WI_ITEM_REC *) channel,

View File

@ -22,6 +22,7 @@
#include "module-formats.h"
#include "levels.h"
#include "settings.h"
#include "channels.h"
#include "fe-queries.h"
#include "hilight-text.h"
@ -83,12 +84,28 @@ void window_commands_deinit(void);
void fe_core_commands_init(void);
void fe_core_commands_deinit(void);
static void sig_connected(SERVER_REC *server)
{
MODULE_DATA_SET(server, g_new0(MODULE_SERVER_REC, 1));
}
static void sig_disconnected(SERVER_REC *server)
{
g_free(MODULE_DATA(server));
}
static void sig_channel_created(CHANNEL_REC *channel)
{
MODULE_DATA_SET(channel, g_new0(MODULE_CHANNEL_REC, 1));
}
static void sig_channel_destroyed(CHANNEL_REC *channel)
{
g_free(MODULE_DATA(channel));
}
void fe_common_core_init(void)
{
/*settings_add_bool("lookandfeel", "show_menubar", TRUE);
settings_add_bool("lookandfeel", "show_toolbar", FALSE);
settings_add_bool("lookandfeel", "show_statusbar", TRUE);
settings_add_bool("lookandfeel", "show_nicklist", TRUE);*/
settings_add_bool("lookandfeel", "timestamps", TRUE);
settings_add_bool("lookandfeel", "msgs_timestamps", FALSE);
settings_add_bool("lookandfeel", "hide_text_style", FALSE);
@ -98,9 +115,6 @@ void fe_common_core_init(void)
settings_add_bool("lookandfeel", "use_status_window", TRUE);
settings_add_bool("lookandfeel", "use_msgs_window", FALSE);
/*settings_add_bool("lookandfeel", "autoraise_msgs_window", FALSE);*/
/*settings_add_bool("lookandfeel", "use_tabbed_windows", TRUE);
settings_add_int("lookandfeel", "tab_orientation", 3);*/
themes_init();
theme_register(fecommon_core_formats);
@ -133,7 +147,12 @@ void fe_common_core_init(void)
fe_messages_init();
fe_ignore_messages_init();
settings_check();
settings_check();
signal_add_first("server connected", (SIGNAL_FUNC) sig_connected);
signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected);
signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created);
signal_add_last("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
}
void fe_common_core_deinit(void)
@ -168,6 +187,11 @@ void fe_common_core_deinit(void)
theme_unregister();
themes_deinit();
signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
signal_remove("channel created", (SIGNAL_FUNC) sig_channel_created);
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
}
void fe_common_core_finish_init(void)

View File

@ -325,8 +325,7 @@ static void sig_exec_input_reader(PROCESS_REC *rec)
recvlen = -1;
do {
ret = line_split(tmpbuf, recvlen, &str,
(LINEBUF_REC **) &rec->databuf);
ret = line_split(tmpbuf, recvlen, &str, &rec->databuf);
if (ret == -1) {
/* link to terminal closed? */
g_source_remove(rec->read_tag);

View File

@ -1,3 +1,34 @@
#include "common.h"
#define MODULE_NAME "fe-common/core"
typedef struct {
time_t time;
char *nick;
/* channel specific msg to/from me - this is actually a reference
count. it begins from `completion_keep_publics' and is decreased
every time some nick is added to lastmsgs list.
this is because of how the nick completion works. the same nick
is never in the lastmsgs list twice, but every time it's used
it's just moved to the beginning of the list. if this would be
just a boolean value the own-status would never be removed
from the nick if it didn't keep quiet for long enough.
so, the own-status is rememberd only for the last
`completion_keep_publics' lines */
int own;
} LAST_MSG_REC;
typedef struct {
/* /MSG completion: */
GSList *lastmsgs; /* list of nicks who sent you msg or
to who you send msg */
} MODULE_SERVER_REC;
typedef struct {
/* nick completion: */
GSList *lastmsgs; /* list of nicks who sent latest msgs and
list of nicks who you sent msgs to */
} MODULE_CHANNEL_REC;

View File

@ -22,6 +22,7 @@
#include "signals.h"
#include "levels.h"
#include "servers.h"
#include "channels.h"
#include "misc.h"
#include "settings.h"

View File

@ -36,7 +36,7 @@ void window_item_add(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);
item->window = window;
if (window->items == NULL) {
window->active = item;
@ -66,7 +66,7 @@ void window_item_remove(WINDOW_REC *window, WI_ITEM_REC *item)
if (g_slist_find(window->items, item) == NULL)
return;
MODULE_DATA_SET(item, NULL);
item->window = NULL;
window->items = g_slist_remove(window->items, item);
if (window->active == item) {
@ -84,13 +84,6 @@ void window_item_destroy(WINDOW_REC *window, WI_ITEM_REC *item)
signal_emit("window item destroy", 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_change_server(WI_ITEM_REC *item, void *server)
{
WINDOW_REC *window;

View File

@ -11,7 +11,8 @@ void window_item_destroy(WINDOW_REC *window, WI_ITEM_REC *item);
/* Find a window for `item' and call window_item_add(). */
void window_item_create(WI_ITEM_REC *item, int automatic);
WINDOW_REC *window_item_window(WI_ITEM_REC *item);
#define window_item_window(item) \
((WINDOW_REC *) ((WI_ITEM_REC *) (item))->window)
void window_item_change_server(WI_ITEM_REC *item, void *server);
void window_item_set_active(WINDOW_REC *window, WI_ITEM_REC *item);

View File

@ -156,8 +156,7 @@ static void statusbar_nick(SBAR_ITEM_REC *item, int ypos)
nick[9] = '\0';
channel = CHANNEL(active_win->active);
nickrec = channel == NULL ? NULL :
nicklist_find(channel, server->nick);
nickrec = channel == NULL ? NULL : channel->ownnick;
}
size_needed = 2 + strlen(nick) + umode_size +

View File

@ -58,7 +58,7 @@ static void sig_bot_read(BOT_REC *bot)
for (;;) {
recvlen = bot->handle == NULL ? -1 :
net_receive(bot->handle, tmpbuf, sizeof(tmpbuf));
ret = line_split(tmpbuf, recvlen, &str, (LINEBUF_REC **) &bot->buffer);
ret = line_split(tmpbuf, recvlen, &str, &bot->buffer);
if (ret == 0)
break;

View File

@ -46,7 +46,7 @@ typedef struct {
GIOChannel *handle;
int read_tag;
void *buffer;
LINEBUF_REC *buffer;
int file_handle; /* if bot is sending a file to us */

View File

@ -218,7 +218,7 @@ static void server_rejoin_channels(IRC_SERVER_REC *server)
g_string_truncate(keys, keys->len-1);
if (use_keys) g_string_sprintfa(channels, " %s", keys->str);
server->channels_join(server, channels->str, TRUE);
server->channels_join(SERVER(server), channels->str, TRUE);
}
g_string_free(channels, TRUE);

View File

@ -422,7 +422,6 @@ static void multi_query_remove(IRC_SERVER_REC *server, const char *event, const
static void event_end_of_who(IRC_SERVER_REC *server, const char *data)
{
IRC_CHANNEL_REC *chanrec;
NICK_REC *nick;
char *params, *channel, **chans;
int n, onewho;
@ -441,8 +440,7 @@ static void event_end_of_who(IRC_SERVER_REC *server, const char *data)
/* check that the WHO actually did return something
(that it understood #chan1,#chan2,..) */
chanrec = irc_channel_find(server, chans[0]);
nick = nicklist_find(CHANNEL(chanrec), server->nick);
if (nick->host == NULL)
if (chanrec->ownnick->host == NULL)
server->no_multi_who = TRUE;
}

View File

@ -93,14 +93,14 @@ static void sig_channel_destroyed(IRC_CHANNEL_REC *channel)
#define get_join_key(key) \
(((key) == NULL || *(key) == '\0') ? "x" : (key))
static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
static void irc_channels_join(SERVER_REC *server, const char *data,
int automatic)
{
CHANNEL_SETUP_REC *schannel;
IRC_CHANNEL_REC *chanrec;
CHANNEL_REC *chanrec;
GString *outchans, *outkeys;
char *channels, *keys, *key;
char **chanlist, **keylist, **tmp, **tmpkey, *channel;
char **chanlist, **keylist, **tmp, **tmpkey, *channel, *channame;
void *free_arg;
int use_keys;
@ -124,7 +124,7 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
channel = ischannel(**tmp) ? g_strdup(*tmp) :
g_strdup_printf("#%s", *tmp);
chanrec = irc_channel_find(server, channel);
chanrec = channel_find(server, channel);
if (chanrec == NULL) {
schannel = channels_setup_find(channel, server->connrec->chatnet);
@ -138,7 +138,10 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
} else key = NULL;
g_string_sprintfa(outkeys, "%s,", get_join_key(key));
chanrec = irc_channel_create(server, channel + (channel[0] == '!' && channel[1] == '!'), automatic);
channame = channel + (channel[0] == '!' &&
channel[1] == '!');
chanrec = channel_create(server->chat_type, server,
channame, automatic);
if (key != NULL) chanrec->key = g_strdup(key);
}
g_free(channel);
@ -150,7 +153,8 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data,
if (outchans->len > 0) {
g_string_truncate(outchans, outchans->len-1);
g_string_truncate(outkeys, outkeys->len-1);
irc_send_cmdv(server, use_keys ? "JOIN %s %s" : "JOIN %s",
irc_send_cmdv(IRC_SERVER(server),
use_keys ? "JOIN %s %s" : "JOIN %s",
outchans->str, outkeys->str);
}
@ -192,10 +196,8 @@ static void sig_server_looking(SERVER_REC *server)
if (!IS_IRC_SERVER(server))
return;
server->channel_find_func =
(void *(*)(void *, const char *)) irc_channel_find_server;
server->channels_join =
(void (*)(void *, const char *, int)) irc_channels_join;
server->channel_find_func = irc_channel_find_server;
server->channels_join = irc_channels_join;
}
void irc_channels_init(void)

View File

@ -778,7 +778,7 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
NICK_REC *rec = tmp->data;
if (g_strcasecmp(rec->nick, server->nick) != 0)
if (rec != chanrec->ownnick)
irc_send_cmdv(server, "NOTICE %s :%s", rec->nick, msg);
}
g_free(msg);

View File

@ -85,9 +85,6 @@ static void event_names_list(SERVER_REC *server, const char *data)
while (*names != '\0' && *names != ' ') names++;
if (*names != '\0') *names++ = '\0';
if (*ptr == '@' && g_strcasecmp(server->nick, ptr+1) == 0)
chanrec->chanop = TRUE;
nicklist_insert(chanrec, ptr+isnickflag(*ptr),
*ptr == '@', *ptr == '+', FALSE);
}
@ -98,14 +95,16 @@ static void event_names_list(SERVER_REC *server, const char *data)
static void event_end_of_names(SERVER_REC *server, const char *data)
{
char *params, *channel;
IRC_CHANNEL_REC *chanrec;
CHANNEL_REC *chanrec;
g_return_if_fail(server != NULL);
params = event_get_params(data, 2, NULL, &channel);
chanrec = irc_channel_find(server, channel);
chanrec = channel_find(server, channel);
if (chanrec != NULL && !chanrec->names_got) {
chanrec->ownnick = nicklist_find(chanrec, server->nick);
chanrec->chanop = chanrec->ownnick->op;
chanrec->names_got = TRUE;
signal_emit("channel joined", 1, chanrec);
}

View File

@ -73,17 +73,19 @@ static int ischannel_func(char flag)
return ischannel(flag);
}
static void send_message(IRC_SERVER_REC *server, const char *target,
static void send_message(SERVER_REC *server, const char *target,
const char *msg)
{
IRC_SERVER_REC *ircserver;
char *str;
g_return_if_fail(server != NULL);
ircserver = IRC_SERVER(server);
g_return_if_fail(ircserver != NULL);
g_return_if_fail(target != NULL);
g_return_if_fail(msg != NULL);
str = g_strdup_printf("PRIVMSG %s :%s", target, msg);
irc_send_cmd_split(server, str, 2, server->max_msgs_in_cmd);
irc_send_cmd_split(ircserver, str, 2, ircserver->max_msgs_in_cmd);
g_free(str);
}
@ -94,8 +96,7 @@ static void sig_server_looking(IRC_SERVER_REC *server)
server->isnickflag = isnickflag_func;
server->ischannel = ischannel_func;
server->send_message =
(void (*)(void *, const char *, const char *)) send_message;
server->send_message = send_message;
}
static void server_init(IRC_SERVER_REC *server)

View File

@ -291,7 +291,7 @@ static int irc_receive_line(SERVER_REC *server, char **str, int read_socket)
net_receive(net_sendbuffer_handle(server->handle),
tmpbuf, sizeof(tmpbuf));
ret = line_split(tmpbuf, recvlen, str, (LINEBUF_REC **) &server->buffer);
ret = line_split(tmpbuf, recvlen, str, &server->buffer);
if (ret == -1) {
/* connection lost */
server->connection_lost = TRUE;

View File

@ -24,6 +24,7 @@
#include "misc.h"
#include "irc-servers.h"
#include "irc-channels.h"
#include "netsplit.h"
/* How long to keep netsplits in memory (seconds) */

View File

@ -41,7 +41,7 @@ typedef struct DCC_REC {
long size, transfd, skipped; /* file size / bytes transferred / skipped at start */
GIOChannel *handle; /* socket handle */
void *sendbuf;
NET_SENDBUF_REC *sendbuf;
int tagconn, tagread, tagwrite;
int fhandle; /* file handle */
time_t starttime; /* transfer start time */

View File

@ -14,11 +14,11 @@ enum {
#define is_node_list(a) \
((a)->type == NODE_TYPE_BLOCK || (a)->type == NODE_TYPE_LIST)
typedef struct {
struct _CONFIG_NODE {
int type;
char *key;
void *value;
} CONFIG_NODE;
};
/* a = { x=y; y=z; }
@ -43,7 +43,7 @@ typedef struct {
*/
struct _config_rec {
struct _CONFIG_REC {
char *fname;
int handle;
int create_mode;
@ -61,8 +61,6 @@ struct _config_rec {
int tmp_last_lf; /* last character was a line feed */
};
typedef struct _config_rec CONFIG_REC;
/* Open configuration. The file is created if it doesn't exist, unless
`create_mode' is -1. `fname' can be NULL if you just want to use
config_parse_data() */