marking.c
author Myhailo Danylenko <isbear@ukrpost.net>
Tue, 21 Aug 2012 03:14:48 +0300
changeset 32 bea3464128d0
parent 31 55395c6ef7ea
child 34 1820e2dc90ef
permissions -rw-r--r--
Rearrange docs

/*
 * marking.c            -- Actions on multiple buddies
 *
 * Copyright (C) 2009-2012 Myhailo Danylenko <isbear@ukrpost.net>
 * Copyright (C) 2012      Mikael Berthe <mikael@lilotux.net>
 *
 * 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 <glib.h>
#include <string.h>

#include <mcabber/hbuf.h>
#include <mcabber/screen.h>
#include <mcabber/commands.h>
#include <mcabber/compl.h>
#include <mcabber/utils.h>
#include <mcabber/logprint.h>
#include <mcabber/modules.h>

#include "config.h"

void marking_init   (void);
void marking_uninit (void);

#define DESCRIPTION ( "Actions on multiple marked buddies\n" \
					  "Provides commands /mark and /marked" )

module_info_t info_marking = {
	.branch      = MCABBER_BRANCH,
	.api         = MCABBER_API_VERSION,
	.version     = PROJECT_VERSION,
	.description = DESCRIPTION,
	.requires    = NULL,
	.init        = marking_init,
	.uninit      = marking_uninit,
	.next        = NULL,
};

#ifdef MCABBER_API_HAVE_CMD_ID
static gpointer mark_cmid   = NULL;
static gpointer marked_cmid = NULL;
#endif

static GSList *marked_jids = NULL;

// mark set jid
// mark clear jid
// mark toggle jid
static void do_mark (char *arg)
{
	char     **args   = split_arg (arg, 2, 1);
	char      *cmd    = NULL;
	char      *jid    = NULL;
	gboolean   jfree  = FALSE;
	int        marked = -1;
	guint	   len;

	if (args[0]) {
		cmd = args[0];

		if (args[1]) {
			const char *j = args[1];
			if (check_jid_syntax(j)) {
				scr_log_print(LPRINT_NORMAL|LPRINT_NOTUTF8,
					          "<%s> is not a valid Jabber ID.", j);
				return;
			}
			jid = g_strdup(j);
			if (!jid) {
				scr_log_print (LPRINT_NORMAL|LPRINT_NOTUTF8,
					           "Unexpected error.");
				return;
			}
			jfree = TRUE;
		}
	} else
		cmd = "set";

	if (!jid) {
		// JID was not provided
		const char *j = NULL;

		if (current_buddy)
			j = CURRENT_JID;

		if (!j) {
			scr_log_print (LPRINT_NORMAL, "No buddy is currently selected.");
			return;
		}

		jid   = g_strdup (j);
		jfree = TRUE;
	}


	if (!strcmp (cmd, "set")) {

		if (!g_slist_find_custom (marked_jids, jid, (GCompareFunc) g_strcmp0)) {
			marked_jids = g_slist_append (marked_jids, jid);
			marked      = 1;
			jfree       = FALSE;
		}

	} else if (!strcmp (cmd, "clear")) {

		GSList *mel = g_slist_find_custom (marked_jids, jid, (GCompareFunc) g_strcmp0);

		if (mel) {
			g_free (mel->data);
			marked_jids = g_slist_delete_link (marked_jids, mel);
			marked      = 0;
		}

	} else if (!strcmp (cmd, "toggle")) {

		GSList *mel = g_slist_find_custom (marked_jids, jid, (GCompareFunc) g_strcmp0);

		if (mel) {
			g_free (mel->data);
			marked_jids = g_slist_delete_link (marked_jids, mel);
			marked      = 0;
		} else {
			marked_jids = g_slist_append (marked_jids, jid);
			marked      = 1;
			jfree       = FALSE;
		}
	} else
		scr_log_print (LPRINT_NORMAL, "Unknown subcommand.");

	len = g_slist_length(marked_jids);
	if (marked == 1) {
		scr_write_incoming_message (jid, "Marked", 0,
					    HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
	} else if (marked == 0) {
		scr_write_incoming_message (jid, "Mark cleared", 0,
					    HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0);
	}
	if (marked >= 0) {
		scr_log_print (LPRINT_NORMAL, "<%s> is now %s (%u mark%s).", jid,
					   marked == 1 ? "marked" : "unmarked",
					   len, len > 1 ? "s" : "");
	}

	if (jfree && jid)
		g_free (jid);

	free_arg_lst (args);
}

// marked clear
// marked do cmd
void do_marked (char *arg)
{
	char **args = split_arg (arg, 2, 1);
	char  *cmd = args[0];

	if (!cmd)
		cmd = "list";

	if (!strcmp (cmd, "list")) {

		GSList *mel;
		guint len = g_slist_length (marked_jids);

		if (!marked_jids) {
			scr_log_print (LPRINT_NORMAL, "No marked JIDs.");
		} else {
			scr_log_print (LPRINT_NORMAL, "%d marked JIDs:", len);
			for (mel = marked_jids; mel; mel = mel->next) {
				char *jid = (char *) mel->data;
				scr_log_print (LPRINT_NORMAL, " * %s", jid);
			}
			// XXX Smartly set the status flag if we have more marks than the log
			// window height.
			if (len + 1 > scr_getlogwinheight()) {
				scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE);
				scr_setattentionflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE,
							       ROSTER_UI_PRIO_STATUS_WIN_MESSAGE, prio_max);
			}
		}

	} else if (!strcmp (cmd, "clear")) {

		GSList *mel;

		for (mel = marked_jids; mel; mel = mel->next)
			g_free (mel->data);

		g_slist_free (marked_jids);
		marked_jids = NULL;

		scr_log_print (LPRINT_NORMAL, "List cleared.  No marked JIDs.");

	} else if (!strcmp (cmd, "do")) {
		char *format = args[1];

		if (!format)
			scr_log_print (LPRINT_NORMAL,
				       "You must specify action to do with marked JIDs");
		else {
			char     *pos   = format;
			gboolean  found = FALSE;
			gboolean  error = FALSE;

			for (pos = strchr (pos, '%'); pos; pos = strchr (pos, '%')) {
				if (*(pos + 1) == 's')
					found = TRUE;
				else if (*(pos + 1) == '%')
					++pos;
				else {
					scr_log_print (LPRINT_NORMAL,
						       "Action string must not contain any other %%-sequences!");
					error = TRUE;
					break;
				}

				++pos;
			}

			if (!found)
				scr_log_print (LPRINT_NORMAL,
					       "Action string must contain one %%s!");
			else if (!error) {
				GSList *mel;

				for (mel = marked_jids; mel; mel = mel->next) {
					char *jid     = (char *) mel->data;
					char *command = g_strdup_printf (format, jid);
					process_command (command, TRUE);
					g_free (command);
				}
			}
		}
	} else
		scr_log_print (LPRINT_NORMAL, "Unknown subcommand.");

	free_arg_lst (args);
}

void marking_init (void)
{
#ifndef MCABBER_API_HAVE_CMD_ID
	cmd_add ("mark",   "", 0, COMPL_JID, do_mark,   NULL);
	cmd_add ("marked", "", 0, COMPL_CMD, do_marked, NULL);
#else
	mark_cmid   = cmd_add ("mark",   "", 0, COMPL_JID, do_mark,   NULL);
	marked_cmid = cmd_add ("marked", "", 0, COMPL_CMD, do_marked, NULL);
#endif
}

void marking_uninit (void)
{
#ifndef MCABBER_API_HAVE_CMD_ID
	cmd_del ("mark");
	cmd_del ("marked");
#else
	if (mark_cmid)
		cmd_del (mark_cmid);
	if (marked_cmid)
		cmd_del (marked_cmid);
#endif

	{
		GSList *mel;

		for (mel = marked_jids; mel; mel = mel->next)
			g_free (mel->data);

		g_slist_free (marked_jids);
		marked_jids = NULL;
	}
}

/* vim: se ts=4 sw=4: */