shithub: xmpp

ref: ed2752fe715680692023bbcaf85ddf03c2444c2c
dir: xmpp/targ.c

View raw version
#include <u.h>
#include <libc.h>
#include "xml.h"
#include "xmpp.h"

Target **targets;
int curr, numtargets;

int
targmatches(Target *t, char *s, int n)
{
	return	(t->name != nil && strncmp(t->name, s, n) == 0) ||
			(t->jid  != nil && strncmp(t->jid,  s, n) == 0);
}

static int
cmptarg(void *a, void *b)
{
	Target *ta, *tb;
	int r;

	ta = *(void**)a;
	tb = *(void**)b;
	if(ta->name != nil && tb->name != nil)
		r = strcmp(ta->name, tb->name);
	else
		r = strcmp(ta->jid, tb->jid);
	if(r == 0 && ta->type == Erost && tb->type == Erost)
		return (ta->rost.flags & Fonline) ? -1 : 1;
	return r;
}

static void
sorttargets(void)
{
	Target *t;

	t = (curr >= 0) ? targets[curr] : nil;
	qsort(targets, numtargets, sizeof(t), cmptarg);
	if(t != nil){
		for(curr = 0; curr < numtargets; curr++)
			if(targets[curr] == t)
				break;
	}
}

Target*
addtarget(int type, char *name)
{
	Target *t;

	numtargets++;
	if(numtargets == 1 || (numtargets & (numtargets-1)) == 0)
		targets = realloc(targets, sizeof(t)*numtargets*2);
	if(targets == nil)
		sysfatal("%r");
	t = targets[numtargets-1] = mallocz(sizeof(*t), 1);
	if(t == nil)
		sysfatal("%r");
	t->type = type;
	t->name = strdup(name);
	sorttargets();
	return t;
}

void
rmtarget(Target *t)
{
	int i;

	if(curr >= 0 && targets[curr] == t){
		setlabel("", nil);
		curr = -1;
	}
	free(t->name);
	free(t->jid);

	if(t->type == Erost)
		free(t->rost.show);
	else if(t->type == Emucent){
		free(t->mucent.jid);
		free(t->mucent.show);
	}else if(t->type == Emuc)
		free(t->muc.subj);

	free(t);
	for(i = 0; i < numtargets; i++){
		if(targets[i] == t){
			numtargets--;
			memcpy(&targets[i], &targets[i+1], sizeof(t)*(numtargets-i));
			if(curr > i)
				curr--;
			t = nil;
			break;
		}
	}
	if(t != nil)
		sysfatal("rmtarget: not found");
}

int
cmdtarget(int, int argc, char **argv)
{
	Target *t;
	char *a, *b;
	int i, cycle, alen, blen;

	if(argc < 2){
		curr = -1;
		setlabel("", nil);
		return 0;
	}

	a = argv[1];
	b = strchr(a, '/');
	if(b == nil){
		blen = 0;
		alen = strlen(a);
	}else{
		b++;
		blen = strlen(b);
		alen = b-1 - a;
	}

	for(cycle = 0, i = curr+1; cycle < 2; cycle++){
		for(; i < numtargets; i++){
			char *s;
			t = targets[i];
			if(b == nil && t->type == Emuc && targmatches(t, a, alen)){
				setlabel(t->jid, nil);
				curr = i;
				return 0;
			}
			if(t->type == Erost && targmatches(t, a, alen) && (b == nil || strncmp(t->jid, b, blen) == 0)){
				s = smprint("%t", t);
				setlabel(s, (t->rost.flags & Fonline) ? t->rost.show : "offline");
				free(s);
				curr = i;
				return 0;
			}
			if(t->type == Emucent && b != nil && targmatches(t->mucent.room, a, alen) && strncmp(t->name, b, blen) == 0){
				s = smprint("%t", t);
				setlabel(s, nil);
				free(s);
				curr = i;
				return 0;
			}
		}
		i = 0;
	}

	print("no such target: %q\n", a);
	return 0;
}

int
targetfmt(Fmt *f)
{
	Target *t;

	t = va_arg(f->args, Target*);
	if(t->type == Erost && curr >= 0 && targets[curr] == t)
		return fmtprint(f, "%s", t->name);
	if(t->type == Emucent)
		return fmtprint(f, "%s/%s", t->mucent.room->name, t->name);
	if(t->jid == nil)
		return fmtprint(f, "%s", t->name);
	return fmtprint(f, "%s/%s", t->name, t->jid);
}