#ident "@(#)fset.c 1.10" /* * fset.c - keep track of all our format strings * Modified by Rex Feany (laeos@laeos.net) for Xaric * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_ASSERT_H # include #endif #include "irc.h" #include "ircaux.h" #include "screen.h" #include "output.h" #include "misc.h" #include "vars.h" #include "fset.h" #include "alist.h" #include "tcommand.h" #include "format.h" /* default formats */ static struct format_set { const char *name; char *value; char *old; int modified; int len; } formatset_array[] = { /*--start--*/ {"FORMAT_381", DEF_FORMAT_381, NULL, 0, 0 }, {"FORMAT_391", DEF_FORMAT_391, NULL, 0, 0 }, {"FORMAT_443", DEF_FORMAT_443, NULL, 0, 0 }, {"FORMAT_471", DEF_FORMAT_471, NULL, 0, 0 }, {"FORMAT_473", DEF_FORMAT_473, NULL, 0, 0 }, {"FORMAT_474", DEF_FORMAT_474, NULL, 0, 0 }, {"FORMAT_475", DEF_FORMAT_475, NULL, 0, 0 }, {"FORMAT_476", DEF_FORMAT_476, NULL, 0, 0 }, {"FORMAT_ACTION", DEF_FORMAT_ACTION, NULL, 0, 0 }, {"FORMAT_ACTION_OTHER", DEF_FORMAT_ACTION_OTHER, NULL, 0, 0 }, {"FORMAT_ACTION_PRIV", DEF_FORMAT_ACTION_PRIV, NULL, 0, 0 }, {"FORMAT_ALIAS", DEF_FORMAT_ALIAS, NULL, 0, 0 }, {"FORMAT_ASSIGN", DEF_FORMAT_ASSIGN, NULL, 0, 0 }, {"FORMAT_AWAY", DEF_FORMAT_AWAY, NULL, 0, 0 }, {"FORMAT_BACK", DEF_FORMAT_BACK, NULL, 0, 0 }, {"FORMAT_BANS", DEF_FORMAT_BANS, NULL, 0, 0 }, {"FORMAT_BANS_HEADER", DEF_FORMAT_BANS_HEADER, NULL, 0, 0 }, {"FORMAT_BWALL", DEF_FORMAT_BWALL, NULL, 0, 0 }, {"FORMAT_CHANNEL_SIGNOFF", DEF_FORMAT_CHANNEL_SIGNOFF, NULL, 0, 0 }, {"FORMAT_CONNECT", DEF_FORMAT_CONNECT, NULL, 0, 0 }, {"FORMAT_CTCP", DEF_FORMAT_CTCP, NULL, 0, 0 }, {"FORMAT_CTCP_REPLY", DEF_FORMAT_CTCP_REPLY, NULL, 0, 0 }, {"FORMAT_CTCP_UNKNOWN", DEF_FORMAT_CTCP_UNKNOWN, NULL, 0, 0 }, {"FORMAT_DCC", DEF_FORMAT_DCC, NULL, 0, 0 }, {"FORMAT_DCC_CHAT", DEF_FORMAT_DCC_CHAT, NULL, 0, 0 }, {"FORMAT_DCC_CONNECT", DEF_FORMAT_DCC_CONNECT, NULL, 0, 0 }, {"FORMAT_DCC_ERROR", DEF_FORMAT_DCC_ERROR, NULL, 0, 0 }, {"FORMAT_DCC_LOST", DEF_FORMAT_DCC_LOST, NULL, 0, 0 }, {"FORMAT_DCC_REQUEST", DEF_FORMAT_DCC_REQUEST, NULL, 0, 0 }, {"FORMAT_DESYNC", DEF_FORMAT_DESYNC, NULL, 0, 0 }, {"FORMAT_DISCONNECT", DEF_FORMAT_DISCONNECT, NULL, 0, 0 }, {"FORMAT_ENCRYPTED_NOTICE", DEF_FORMAT_ENCRYPTED_NOTICE, NULL, 0, 0 }, {"FORMAT_ENCRYPTED_PRIVMSG", DEF_FORMAT_ENCRYPTED_PRIVMSG, NULL, 0, 0 }, {"FORMAT_FLOOD", DEF_FORMAT_FLOOD, NULL, 0, 0 }, {"FORMAT_HOOK", DEF_FORMAT_HOOK, NULL, 0, 0 }, {"FORMAT_IGNORE_INVITE", DEF_FORMAT_IGNORE_INVITE, NULL, 0, 0 }, {"FORMAT_IGNORE_MSG", DEF_FORMAT_IGNORE_MSG, NULL, 0, 0 }, {"FORMAT_IGNORE_MSG_AWAY", DEF_FORMAT_IGNORE_MSG_AWAY, NULL, 0, 0 }, {"FORMAT_IGNORE_NOTICE", DEF_FORMAT_IGNORE_NOTICE, NULL, 0, 0 }, {"FORMAT_IGNORE_WALL", DEF_FORMAT_IGNORE_WALL, NULL, 0, 0 }, {"FORMAT_INVITE", DEF_FORMAT_INVITE, NULL, 0, 0 }, {"FORMAT_INVITE_USER", DEF_FORMAT_INVITE_USER, NULL, 0, 0 }, {"FORMAT_JOIN", DEF_FORMAT_JOIN, NULL, 0, 0 }, {"FORMAT_KICK", DEF_FORMAT_KICK, NULL, 0, 0 }, {"FORMAT_KICK_USER", DEF_FORMAT_KICK_USER, NULL, 0, 0 }, {"FORMAT_KILL", DEF_FORMAT_KILL, NULL, 0, 0 }, {"FORMAT_LEAVE", DEF_FORMAT_LEAVE, NULL, 0, 0 }, {"FORMAT_LINKS", DEF_FORMAT_LINKS, NULL, 0, 0 }, {"FORMAT_LIST", DEF_FORMAT_LIST, NULL, 0, 0 }, {"FORMAT_MODE", DEF_FORMAT_MODE, NULL, 0, 0 }, {"FORMAT_MODE_CHANNEL", DEF_FORMAT_MODE_CHANNEL, NULL, 0, 0 }, {"FORMAT_MSG", DEF_FORMAT_MSG, NULL, 0, 0 }, {"FORMAT_MSGLOG", DEF_FORMAT_MSGLOG, NULL, 0, 0 }, {"FORMAT_MSG_GROUP", DEF_FORMAT_MSG_GROUP, NULL, 0, 0 }, {"FORMAT_NAMES", DEF_FORMAT_NAMES, NULL, 0, 0 }, {"FORMAT_NAMES_BANNER", DEF_FORMAT_NAMES_BANNER, NULL, 0, 0 }, {"FORMAT_NAMES_FOOTER", DEF_FORMAT_NAMES_FOOTER, NULL, 0, 0 }, {"FORMAT_NAMES_IRCOP", DEF_FORMAT_NAMES_IRCOP, NULL, 0, 0 }, {"FORMAT_NAMES_NICKCOLOR", DEF_FORMAT_NAMES_NICKCOLOR, NULL, 0, 0 }, {"FORMAT_NAMES_NONOP", DEF_FORMAT_NAMES_NONOP, NULL, 0, 0 }, {"FORMAT_NAMES_OP", DEF_FORMAT_NAMES_OP, NULL, 0, 0 }, {"FORMAT_NAMES_OPCOLOR", DEF_FORMAT_NAMES_OPCOLOR, NULL, 0, 0 }, {"FORMAT_NAMES_VOICE", DEF_FORMAT_NAMES_VOICE, NULL, 0, 0 }, {"FORMAT_NAMES_VOICECOLOR", DEF_FORMAT_NAMES_VOICECOLOR, NULL, 0, 0 }, {"FORMAT_NETADD", DEF_FORMAT_NETADD, NULL, 0, 0 }, {"FORMAT_NETJOIN", DEF_FORMAT_NETJOIN, NULL, 0, 0 }, {"FORMAT_NETSPLIT", DEF_FORMAT_NETSPLIT, NULL, 0, 0 }, {"FORMAT_NETSPLIT_HEADER", DEF_FORMAT_NETSPLIT_HEADER, NULL, 0, 0 }, {"FORMAT_NICKNAME", DEF_FORMAT_NICKNAME, NULL, 0, 0 }, {"FORMAT_NICKNAME_OTHER", DEF_FORMAT_NICKNAME_OTHER, NULL, 0, 0 }, {"FORMAT_NICKNAME_USER", DEF_FORMAT_NICKNAME_USER, NULL, 0, 0 }, {"FORMAT_NICK_AUTO", DEF_FORMAT_NICK_AUTO, NULL, 0, 0 }, {"FORMAT_NICK_COMP", DEF_FORMAT_NICK_COMP, NULL, 0, 0 }, {"FORMAT_NICK_MSG", DEF_FORMAT_NICK_MSG, NULL, 0, 0 }, {"FORMAT_NONICK", DEF_FORMAT_NONICK, NULL, 0, 0 }, {"FORMAT_NOTE", DEF_FORMAT_NOTE, NULL, 0, 0 }, {"FORMAT_NOTICE", DEF_FORMAT_NOTICE, NULL, 0, 0 }, {"FORMAT_NOTIFY_OFF", DEF_FORMAT_NOTIFY_OFF, NULL, 0, 0 }, {"FORMAT_NOTIFY_ON", DEF_FORMAT_NOTIFY_ON, NULL, 0, 0 }, {"FORMAT_NOTIFY_SIGNOFF", DEF_FORMAT_NOTIFY_SIGNOFF, NULL, 0, 0 }, {"FORMAT_NOTIFY_SIGNOFF_UH", DEF_FORMAT_NOTIFY_SIGNOFF_UH, NULL, 0, 0 }, {"FORMAT_NOTIFY_SIGNON", DEF_FORMAT_NOTIFY_SIGNON, NULL, 0, 0 }, {"FORMAT_NOTIFY_SIGNON_UH", DEF_FORMAT_NOTIFY_SIGNON_UH, NULL, 0, 0 }, {"FORMAT_OPER", DEF_FORMAT_OPER, NULL, 0, 0 }, {"FORMAT_PUBLIC", DEF_FORMAT_PUBLIC, NULL, 0, 0 }, {"FORMAT_PUBLIC_MSG", DEF_FORMAT_PUBLIC_MSG, NULL, 0, 0 }, {"FORMAT_PUBLIC_NOTICE", DEF_FORMAT_PUBLIC_NOTICE, NULL, 0, 0 }, {"FORMAT_PUBLIC_OTHER", DEF_FORMAT_PUBLIC_OTHER, NULL, 0, 0 }, {"FORMAT_SCANDIR_LIST_FOOTER", DEF_FORMAT_SCANDIR_LIST_FOOTER, NULL, 0, 0 }, {"FORMAT_SCANDIR_LIST_HEADER", DEF_FORMAT_SCANDIR_LIST_HEADER, NULL, 0, 0 }, {"FORMAT_SCANDIR_LIST_LINE", DEF_FORMAT_SCANDIR_LIST_LINE, NULL, 0, 0 }, {"FORMAT_SEND_ACTION", DEF_FORMAT_SEND_ACTION, NULL, 0, 0 }, {"FORMAT_SEND_ACTION_OTHER", DEF_FORMAT_SEND_ACTION_OTHER, NULL, 0, 0 }, {"FORMAT_SEND_AWAY", DEF_FORMAT_SEND_AWAY, NULL, 0, 0 }, {"FORMAT_SEND_CTCP", DEF_FORMAT_SEND_CTCP, NULL, 0, 0 }, {"FORMAT_SEND_DCC_CHAT", DEF_FORMAT_SEND_DCC_CHAT, NULL, 0, 0 }, {"FORMAT_SEND_MSG", DEF_FORMAT_SEND_MSG, NULL, 0, 0 }, {"FORMAT_SEND_NOTICE", DEF_FORMAT_SEND_NOTICE, NULL, 0, 0 }, {"FORMAT_SEND_PUBLIC", DEF_FORMAT_SEND_PUBLIC, NULL, 0, 0 }, {"FORMAT_SEND_PUBLIC_OTHER", DEF_FORMAT_SEND_PUBLIC_OTHER, NULL, 0, 0 }, {"FORMAT_SERVER", DEF_FORMAT_SERVER, NULL, 0, 0 }, {"FORMAT_SERVER_MSG1", DEF_FORMAT_SERVER_MSG1, NULL, 0, 0 }, {"FORMAT_SERVER_MSG1_FROM", DEF_FORMAT_SERVER_MSG1_FROM, NULL, 0, 0 }, {"FORMAT_SERVER_MSG2", DEF_FORMAT_SERVER_MSG2, NULL, 0, 0 }, {"FORMAT_SERVER_MSG2_FROM", DEF_FORMAT_SERVER_MSG2_FROM, NULL, 0, 0 }, {"FORMAT_SERVER_NOTICE", DEF_FORMAT_SERVER_NOTICE, NULL, 0, 0 }, {"FORMAT_SET", DEF_FORMAT_SET, NULL, 0, 0 }, {"FORMAT_SET_NOVALUE", DEF_FORMAT_SET_NOVALUE, NULL, 0, 0 }, {"FORMAT_SIGNOFF", DEF_FORMAT_SIGNOFF, NULL, 0, 0 }, {"FORMAT_SILENCE", DEF_FORMAT_SILENCE, NULL, 0, 0 }, {"FORMAT_SMODE", DEF_FORMAT_SMODE, NULL, 0, 0 }, {"FORMAT_STATUS", DEF_FORMAT_STATUS, NULL, 0, 0 }, {"FORMAT_STATUS2", DEF_FORMAT_STATUS2, NULL, 0, 0 }, {"FORMAT_TIMER", DEF_FORMAT_TIMER, NULL, 0, 0 }, {"FORMAT_TOPIC", DEF_FORMAT_TOPIC, NULL, 0, 0 }, {"FORMAT_TOPIC_CHANGE", DEF_FORMAT_TOPIC_CHANGE, NULL, 0, 0 }, {"FORMAT_TOPIC_CHANGE_HEADER", DEF_FORMAT_TOPIC_CHANGE_HEADER, NULL, 0, 0 }, {"FORMAT_TOPIC_SETBY", DEF_FORMAT_TOPIC_SETBY, NULL, 0, 0 }, {"FORMAT_TOPIC_UNSET", DEF_FORMAT_TOPIC_UNSET, NULL, 0, 0 }, {"FORMAT_TRACE_OPER", DEF_FORMAT_TRACE_OPER, NULL, 0, 0 }, {"FORMAT_TRACE_SERVER", DEF_FORMAT_TRACE_SERVER, NULL, 0, 0 }, {"FORMAT_TRACE_USER", DEF_FORMAT_TRACE_USER, NULL, 0, 0 }, {"FORMAT_USAGE", DEF_FORMAT_USAGE, NULL, 0, 0 }, {"FORMAT_USERMODE", DEF_FORMAT_USERMODE, NULL, 0, 0 }, {"FORMAT_USERS", DEF_FORMAT_USERS, NULL, 0, 0 }, {"FORMAT_USERS_HEADER", DEF_FORMAT_USERS_HEADER, NULL, 0, 0 }, {"FORMAT_USERS_USER", DEF_FORMAT_USERS_USER, NULL, 0, 0 }, {"FORMAT_VERSION", DEF_FORMAT_VERSION, NULL, 0, 0 }, {"FORMAT_WALL", DEF_FORMAT_WALL, NULL, 0, 0 }, {"FORMAT_WALLOP", DEF_FORMAT_WALLOP, NULL, 0, 0 }, {"FORMAT_WHO", DEF_FORMAT_WHO, NULL, 0, 0 }, {"FORMAT_WHOIS_AWAY", DEF_FORMAT_WHOIS_AWAY, NULL, 0, 0 }, {"FORMAT_WHOIS_CHANNELS", DEF_FORMAT_WHOIS_CHANNELS, NULL, 0, 0 }, {"FORMAT_WHOIS_FOOTER", DEF_FORMAT_WHOIS_FOOTER, NULL, 0, 0 }, {"FORMAT_WHOIS_HEADER", DEF_FORMAT_WHOIS_HEADER, NULL, 0, 0 }, {"FORMAT_WHOIS_IDLE", DEF_FORMAT_WHOIS_IDLE, NULL, 0, 0 }, {"FORMAT_WHOIS_NAME", DEF_FORMAT_WHOIS_NAME, NULL, 0, 0 }, {"FORMAT_WHOIS_NICK", DEF_FORMAT_WHOIS_NICK, NULL, 0, 0 }, {"FORMAT_WHOIS_OPER", DEF_FORMAT_WHOIS_OPER, NULL, 0, 0 }, {"FORMAT_WHOIS_SERVER", DEF_FORMAT_WHOIS_SERVER, NULL, 0, 0 }, {"FORMAT_WHOIS_SIGNON", DEF_FORMAT_WHOIS_SIGNON, NULL, 0, 0 }, {"FORMAT_WHOLEFT_FOOTER", DEF_FORMAT_WHOLEFT_FOOTER, NULL, 0, 0 }, {"FORMAT_WHOLEFT_HEADER", DEF_FORMAT_WHOLEFT_HEADER, NULL, 0, 0 }, {"FORMAT_WHOLEFT_USER", DEF_FORMAT_WHOLEFT_USER, NULL, 0, 0 }, {"FORMAT_WHOWAS_HEADER", DEF_FORMAT_WHOWAS_HEADER, NULL, 0, 0 }, {"FORMAT_WHOWAS_NICK", DEF_FORMAT_WHOWAS_NICK, NULL, 0, 0 }, {"FORMAT_WIDELIST", DEF_FORMAT_WIDELIST, NULL, 0, 0 }, {"FORMAT_WINDOW_SET", DEF_FORMAT_WINDOW_SET, NULL, 0, 0 }, /*--end--*/ {NULL, NULL} }; /*** Private ***/ /* reset a format to its original value */ static inline void reset_var (xformat fmt) { if (formatset_array[fmt].modified) { new_free(&formatset_array[fmt].value); formatset_array[fmt].value = formatset_array[fmt].old; formatset_array[fmt].modified = 0; formatset_array[fmt].len = 0; say ("Reset [%s]", formatset_array[fmt].name); } } /* reset every format to there original values */ static inline void reset_all (void) { xformat i; for (i = 0; i < NUMBER_OF_FSET; i++) if (formatset_array[i].modified) reset_var(i); } /* find a variable by name */ /* return location, or -1 if there were none found */ static xformat find_format (const char *name, int *cnt) { int loc; assert(name); assert(cnt); *cnt = 0; if ((find_fixed_array_item(formatset_array, sizeof (struct format_set), NUMBER_OF_FSET, name, cnt, &loc) == NULL)) return -1; if ( *cnt < 0 ) *cnt = -*cnt; assert(loc < NUMBER_OF_FSET); return loc; } /* set a format */ static void set_format (xformat loc, const char *value) { struct format_set *var = &(formatset_array[loc]); if ( value && *value == '\0' ) { put_it ("%s", convert_output_format (get_fset_var (FORMAT_SET_FSET), "%s %s", var->name, var->value ? var->value : empty_str)); return; } if ( var->modified == 0 ) { var->old = var->value; var->value = NULL; var->modified = 1; } var->len = 0; if (value) malloc_strcpy (&(var->value), value); else if (var->value) new_free (&(var->value)); say ("Value of %s set to %s", var->name, var->value ? var->value : ""); } static void set_format_range (xformat loc, int cnt, const char *arg) { int end = loc + cnt; assert(loc >= 0 && loc < NUMBER_OF_FSET); assert(cnt >= 0 && cnt < NUMBER_OF_FSET); assert(end >= 0 && end < NUMBER_OF_FSET); for ( ; loc < end ; loc++ ) set_format(loc, arg); } /*** Public ***/ /** * get_format_len - return printable length of format * @which: what format * * When the format is displayed, how many printable * character spaces will it use? **/ unsigned int get_format_len(xformat which) { char *conv; /* if already calculated, or NULL value */ if (formatset_array[which].len || !formatset_array[which].value) return formatset_array[which].len; /* XXX */ conv = convert_output_format(formatset_array[which].value, "", NULL); conv = stripansicodes(conv); return (formatset_array[which].len = strlen(conv)); } /** * get_format - fetch a format string * @which: The ID of the format string. * * Return the format string for a given format. **/ const char * get_format(xformat which) { return formatset_array[which].value; } /** * save_formats - write out the changed formats. * @outfile: file handle to write commands to. * * Write out any changes made to the format table in a format that * we can load later. **/ int save_formats (FILE * outfile) { int count = 0; xformat i; assert(outfile); for (i = 0; i < NUMBER_OF_FSET; i++) if ( formatset_array[i].modified ) { count++; if (formatset_array[i].value) fprintf (outfile, "FSET %s %s\n", formatset_array[i].name, formatset_array[i].value); else fprintf (outfile, "FSET -%s\n", formatset_array[i].name); } bitchsay ("Saved %d formats.", count); return 0; } /** * get_format_byname - given a name, return the format string. * @name: Which format to return. * * Return a malloc'ed copy of the format string * given a name, like "FORMAT_FOO" **/ char * get_format_byname (const char *name) { int cnt; int loc; assert(name); if ((find_fixed_array_item(formatset_array, sizeof (struct format_set), NUMBER_OF_FSET, name, &cnt, &loc) == NULL)) return NULL; if (cnt >= 0) return NULL; assert(loc >= 0 && loc < NUMBER_OF_FSET); return m_strdup(formatset_array[loc].value); } /** * cmd_freset - reset modified formats to there compiled-in defaults * @cmd: command struct * @args: command arguments * * Takes either one or zero arguments. * With no arguments, resets all variables to there defaults. * With one argument of a variable name, reset that variable. **/ void cmd_freset(struct command *cmd, char *args) { char *var; int cnt = 0; assert(cmd); if ((var = next_arg (args, &args)) != NULL) { xformat loc = find_format (var, &cnt); switch (cnt) { case 0: say ("No such variable \"%s\"", var); break; case 1: reset_var(loc); break; default: say ("%s is ambiguous", var); set_format_range(loc, cnt, empty_str); break; } } else { reset_all(); } } /** * cmd_fset - modify or query the format table * @cmd: command struct * @args: command arguments * * Takes zero, one, or two arguments. * With no arguments, print out the whole format table. * With one argument, display the value of any matching formats. * With one argument prefixed with '-' unset the format. * Two arguments, the format and the value to change it to. **/ void cmd_fset (struct command *cmd, char *args) { char *var; int cnt; assert(cmd); if ((var = next_arg (args, &args)) != NULL) { xformat loc; if (*var == '-') { var++; args = NULL; } loc = find_format (var, &cnt); switch (cnt) { case 0: say ("No such variable \"%s\"", var); break; case 1: set_format(loc, args); break; default: say ("%s is ambiguous", var); set_format_range(loc, cnt, empty_str); break; } } else set_format_range(0, NUMBER_OF_FSET - 1, empty_str); }