diff --git a/degesch.c b/degesch.c index 8b79ffd..c3aab2d 100644 --- a/degesch.c +++ b/degesch.c @@ -284,6 +284,14 @@ enum buffer_line_type BUFFER_LINE_ERROR ///< Whatever error messages }; +struct buffer_line_args +{ + char *who; ///< Name of the origin or NULL (user) + char *object; ///< Object of action + char *text; ///< Text of message + char *reason; ///< Reason for PART, KICK, QUIT +}; + struct buffer_line { LIST_HEADER (struct buffer_line) @@ -294,9 +302,7 @@ struct buffer_line int flags; ///< Flags time_t when; ///< Time of the event - char *who; ///< Name of the origin or NULL (user) - char *object; ///< Text of message, object of action - char *reason; ///< Reason for PART, KICK, QUIT + struct buffer_line_args args; ///< Arguments }; struct buffer_line * @@ -309,9 +315,10 @@ buffer_line_new (void) static void buffer_line_destroy (struct buffer_line *self) { - free (self->who); - free (self->object); - free (self->reason); + free (self->args.who); + free (self->args.object); + free (self->args.text); + free (self->args.reason); free (self); } @@ -824,10 +831,6 @@ setup_signal_handlers (void) // --- Buffers ----------------------------------------------------------------- -static void buffer_send (struct app_context *ctx, struct buffer *buffer, - enum buffer_line_type type, int flags, const char *origin, - const char *reason, const char *format, ...) ATTRIBUTE_PRINTF (7, 8); - static void buffer_update_time (struct app_context *ctx, time_t now) { @@ -859,19 +862,25 @@ buffer_line_display (struct app_context *ctx, struct buffer_line *line) // confused as to when an event has happened buffer_update_time (ctx, line->when); - struct str text; - str_init (&text); + struct str output; + str_init (&output); struct tm current; if (!localtime_r (&line->when, ¤t)) print_error ("%s: %s", "localtime_r", strerror (errno)); else - str_append_printf (&text, "%02d:%02d:%02d ", + str_append_printf (&output, "%02d:%02d:%02d ", current.tm_hour, current.tm_min, current.tm_sec); - char *who = iconv_xstrdup (ctx->term_from_utf8, line->who, -1, NULL); - char *object = iconv_xstrdup (ctx->term_from_utf8, line->object, -1, NULL); - char *reason = iconv_xstrdup (ctx->term_from_utf8, line->reason, -1, NULL); +#define GET_FIELD(name) char *name = line->args.name \ + ? iconv_xstrdup (ctx->term_from_utf8, line->args.name, -1, NULL) : NULL + + GET_FIELD (who); + GET_FIELD (object); + GET_FIELD (text); + GET_FIELD (reason); + +#undef GET_FIELD // TODO: colorize the output, note that we shouldn't put everything through // tputs but only the attribute strings. That might prove a bit @@ -882,7 +891,7 @@ buffer_line_display (struct app_context *ctx, struct buffer_line *line) char *nick = NULL; const char *userhost = NULL; - if (*who) + if (who) { nick = irc_cut_nickname (who); userhost = irc_find_userhost (who); @@ -891,70 +900,71 @@ buffer_line_display (struct app_context *ctx, struct buffer_line *line) switch (line->type) { case BUFFER_LINE_PRIVMSG: - str_append_printf (&text, "<%s> %s", nick, object); + str_append_printf (&output, "<%s> %s", nick, text); break; case BUFFER_LINE_ACTION: - str_append_printf (&text, " * %s %s", nick, object); + str_append_printf (&output, " * %s %s", nick, text); break; case BUFFER_LINE_NOTICE: - str_append_printf (&text, " - Notice(%s): %s", nick, object); + str_append_printf (&output, " - Notice(%s): %s", nick, text); break; case BUFFER_LINE_JOIN: - if (*who) - str_append_printf (&text, "--> %s (%s) has joined %s", + if (who) + str_append_printf (&output, "--> %s (%s) has joined %s", nick, userhost, object); else - str_append_printf (&text, "--> You have joined %s", object); + str_append_printf (&output, "--> You have joined %s", object); break; case BUFFER_LINE_PART: - if (*who) - str_append_printf (&text, "<-- %s (%s) has left %s (%s)", + if (who) + str_append_printf (&output, "<-- %s (%s) has left %s (%s)", nick, userhost, object, reason); else - str_append_printf (&text, "<-- You have left %s (%s)", + str_append_printf (&output, "<-- You have left %s (%s)", object, reason); break; case BUFFER_LINE_KICK: - if (*who) - str_append_printf (&text, "<-- %s has kicked %s (%s)", + if (who) + str_append_printf (&output, "<-- %s has kicked %s (%s)", nick, object, reason); else - str_append_printf (&text, "<-- You have kicked %s (%s)", + str_append_printf (&output, "<-- You have kicked %s (%s)", object, reason); break; case BUFFER_LINE_NICK: - if (*who) - str_append_printf (&text, " - %s is now known as %s", + if (who) + str_append_printf (&output, " - %s is now known as %s", nick, object); else - str_append_printf (&text, " - You are now known as %s", object); + str_append_printf (&output, " - You are now known as %s", object); break; case BUFFER_LINE_TOPIC: - if (*who) - str_append_printf (&text, - " - %s has changed the topic to: %s", nick, object); + if (who) + str_append_printf (&output, + " - %s has changed the topic to: %s", nick, text); else - str_append_printf (&text, - " - You have changed the topic to: %s", object); + str_append_printf (&output, + " - You have changed the topic to: %s", text); break; case BUFFER_LINE_QUIT: - if (*who) - str_append_printf (&text, "<-- %s (%s) has quit (%s)", + if (who) + str_append_printf (&output, "<-- %s (%s) has quit (%s)", nick, userhost, reason); else - str_append_printf (&text, "<-- You have quit (%s)", reason); + str_append_printf (&output, "<-- You have quit (%s)", reason); break; case BUFFER_LINE_STATUS: - str_append_printf (&text, " - %s", object); + str_append_printf (&output, " - %s", text); break; case BUFFER_LINE_ERROR: - str_append_printf (&text, "=!= %s", object); + str_append_printf (&output, "=!= %s", text); } free (nick); free (who); free (object); + free (text); free (reason); struct app_readline_state state; @@ -964,32 +974,23 @@ buffer_line_display (struct app_context *ctx, struct buffer_line *line) // TODO: write the line to a log file; note that the global and server // buffers musn't collide with filenames - printf ("%s\n", text.str); - str_free (&text); + printf ("%s\n", output.str); + str_free (&output); if (ctx->readline_prompt_shown) app_readline_restore (&state, ctx->readline_prompt); } static void -buffer_send (struct app_context *ctx, struct buffer *buffer, +buffer_send_internal (struct app_context *ctx, struct buffer *buffer, enum buffer_line_type type, int flags, - const char *origin, const char *reason, const char *format, ...) + struct buffer_line_args a) { - va_list ap; - va_start (ap, format); - struct str text; - str_init (&text); - str_append_vprintf (&text, format, ap); - va_end (ap); - struct buffer_line *line = buffer_line_new (); line->type = type; line->flags = flags; line->when = time (NULL); - line->who = xstrdup (origin ? origin : ""); - line->object = str_steal (&text); - line->reason = xstrdup (reason ? reason : ""); + line->args = a; LIST_APPEND_WITH_TAIL (buffer->lines, buffer->lines_tail, line); buffer->lines_count++; @@ -1007,10 +1008,16 @@ buffer_send (struct app_context *ctx, struct buffer *buffer, } } -#define buffer_send_status(ctx, buffer, ...) \ - buffer_send (ctx, buffer, BUFFER_LINE_STATUS, 0, NULL, NULL, __VA_ARGS__) -#define buffer_send_error(ctx, buffer, ...) \ - buffer_send (ctx, buffer, BUFFER_LINE_ERROR, 0, NULL, NULL, __VA_ARGS__) +#define buffer_send(ctx, buffer, type, flags, ...) \ + buffer_send_internal ((ctx), (buffer), (type), (flags), \ + (struct buffer_line_args) { __VA_ARGS__ }) + +#define buffer_send_status(ctx, buffer, ...) \ + buffer_send (ctx, buffer, BUFFER_LINE_STATUS, 0, \ + .text = xstrdup_printf (__VA_ARGS__)) +#define buffer_send_error(ctx, buffer, ...) \ + buffer_send (ctx, buffer, BUFFER_LINE_ERROR, 0, \ + .text = xstrdup_printf (__VA_ARGS__)) static struct buffer * buffer_by_name (struct app_context *ctx, const char *name) @@ -1962,7 +1969,8 @@ irc_handle_join (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_JOIN, 0, - msg->prefix, NULL, "%s", channel_name); + .who = xstrdup (msg->prefix), + .object = xstrdup (channel_name)); } } @@ -1978,7 +1986,7 @@ irc_handle_kick (struct app_context *ctx, const struct irc_message *msg) || irc_is_channel (ctx, target)) return; - const char *message = NULL; + const char *message = ""; if (msg->params.len > 2) message = msg->params.vector[2]; @@ -1995,7 +2003,9 @@ irc_handle_kick (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_KICK, 0, - msg->prefix, message, "%s", target); + .who = xstrdup (msg->prefix), + .object = xstrdup (target), + .reason = xstrdup (message)); } } @@ -2035,7 +2045,8 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg) str_map_set (&ctx->irc_buffer_map, user->nickname, NULL); buffer_send (ctx, pm_buffer, BUFFER_LINE_NICK, 0, - msg->prefix, NULL, "%s", new_nickname); + .who = xstrdup (msg->prefix), + .object = xstrdup (new_nickname)); // TODO: use a full weechat-style buffer name here buffer_rename (ctx, pm_buffer, new_nickname); } @@ -2053,7 +2064,7 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg) continue; buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0, - NULL, NULL, "%s", new_nickname); + .object = xstrdup (new_nickname)); } } else @@ -2065,7 +2076,8 @@ irc_handle_nick (struct app_context *ctx, const struct irc_message *msg) str_map_find (&ctx->irc_buffer_map, iter->channel->name); hard_assert (buffer != NULL); buffer_send (ctx, buffer, BUFFER_LINE_NICK, 0, - msg->prefix, NULL, "%s", new_nickname); + .who = xstrdup (msg->prefix), + .object = xstrdup (new_nickname)); } } @@ -2096,7 +2108,7 @@ irc_handle_part (struct app_context *ctx, const struct irc_message *msg) if (!irc_is_channel (ctx, channel_name)) return; - const char *message = NULL; + const char *message = ""; if (msg->params.len > 1) message = msg->params.vector[1]; @@ -2116,7 +2128,9 @@ irc_handle_part (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_PART, 0, - msg->prefix, message, "%s", channel_name); + .who = xstrdup (msg->prefix), + .object = xstrdup (channel_name), + .reason = xstrdup (message)); } } @@ -2161,7 +2175,8 @@ irc_handle_privmsg (struct app_context *ctx, const struct irc_message *msg) // TODO: handle CTCP messages // TODO: highlights buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0, - msg->prefix, NULL, "%s", message); + .who = xstrdup (msg->prefix), + .text = xstrdup (message)); } } @@ -2181,7 +2196,7 @@ irc_handle_quit (struct app_context *ctx, const struct irc_message *msg) if (!user) return; - const char *message = NULL; + const char *message = ""; if (msg->params.len > 0) message = msg->params.vector[0]; @@ -2191,7 +2206,8 @@ irc_handle_quit (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_QUIT, 0, - msg->prefix, message, "%s", ""); + .who = xstrdup (msg->prefix), + .reason = xstrdup (message)); // TODO: set some kind of a flag in the buffer and when the user // reappers on a channel (JOIN), log a "is back online" message. @@ -2205,7 +2221,8 @@ irc_handle_quit (struct app_context *ctx, const struct irc_message *msg) buffer = str_map_find (&ctx->irc_buffer_map, iter->channel->name); if (buffer) buffer_send (ctx, buffer, BUFFER_LINE_QUIT, 0, - msg->prefix, message, "%s", ""); + .who = xstrdup (msg->prefix), + .reason = xstrdup (message)); // This destroys "iter" which doesn't matter to us irc_remove_user_from_channel (user, iter->channel); @@ -2238,7 +2255,8 @@ irc_handle_topic (struct app_context *ctx, const struct irc_message *msg) if (buffer) { buffer_send (ctx, buffer, BUFFER_LINE_TOPIC, 0, - msg->prefix, NULL, "%s", topic); + .who = xstrdup (msg->prefix), + .text = xstrdup (topic)); } } @@ -2559,11 +2577,12 @@ log_outcoming_privmsg (struct app_context *ctx, { if (buffer) buffer_send (ctx, buffer, BUFFER_LINE_PRIVMSG, 0, - ctx->irc_user->nickname, NULL, "%s", line); + .who = xstrdup (ctx->irc_user->nickname), + .text = xstrdup (line)); else // TODO: fix logging buffer_send (ctx, ctx->server_buffer, BUFFER_LINE_STATUS, 0, - NULL, NULL, "MSG(%s): %s", a->target, line); + .text = xstrdup_printf ("MSG(%s): %s", a->target, line)); } #define SEND_AUTOSPLIT_PRIVMSG(ctx, target, message) \ @@ -2576,11 +2595,12 @@ log_outcoming_notice (struct app_context *ctx, { if (buffer) buffer_send (ctx, buffer, BUFFER_LINE_NOTICE, 0, - ctx->irc_user->nickname, NULL, "%s", line); + .who = xstrdup (ctx->irc_user->nickname), + .text = xstrdup (line)); else // TODO: fix logging buffer_send (ctx, ctx->server_buffer, BUFFER_LINE_STATUS, 0, - NULL, NULL, "Notice -> %s: %s", a->target, line); + .text = xstrdup_printf ("Notice -> %s: %s", a->target, line)); } #define SEND_AUTOSPLIT_NOTICE(ctx, target, message) \