summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--chat.h1
-rw-r--r--handle.c5
-rw-r--r--input.c24
-rw-r--r--ui.c81
4 files changed, 88 insertions, 23 deletions
diff --git a/chat.h b/chat.h
index a4ab195..7e9f220 100644
--- a/chat.h
+++ b/chat.h
@@ -93,6 +93,7 @@ void uiDraw(void);
 void uiRead(void);
 void uiViewTag(struct Tag tag);
 void uiViewNum(int num);
+void uiCloseTag(struct Tag tag);
 void uiTopic(struct Tag tag, const char *topic);
 void uiLog(struct Tag tag, const wchar_t *line);
 void uiFmt(struct Tag tag, const wchar_t *format, ...);
diff --git a/handle.c b/handle.c
index 4d2d4b1..80ed1b4 100644
--- a/handle.c
+++ b/handle.c
@@ -122,12 +122,15 @@ static void handleJoin(char *prefix, char *params) {
 	char *nick, *user, *chan;
 	shift(prefix, &nick, &user, NULL, params, 1, 0, &chan);
 	struct Tag tag = tagFor(chan);
+	if (isSelf(nick, user)) {
+		tabTouch(TAG_NONE, chan);
+		uiViewTag(tag);
+	}
 	tabTouch(tag, nick);
 	uiFmt(
 		tag, "\3%d%s\3 arrives in \3%d%s\3",
 		color(user), nick, color(chan), chan
 	);
-	if (isSelf(nick, user)) uiViewTag(tag);
 }
 
 static void handlePart(char *prefix, char *params) {
diff --git a/input.c b/input.c
index 9f7eddf..2d9bc46 100644
--- a/input.c
+++ b/input.c
@@ -64,6 +64,21 @@ static void inputJoin(struct Tag tag, char *params) {
 	ircFmt("JOIN %s\r\n", chan);
 }
 
+static void inputPart(struct Tag tag, char *params) {
+	if (params) {
+		ircFmt("PART %s :%s\r\n", tag.name, params);
+	} else {
+		ircFmt("PART %s :Goodbye\r\n", tag.name);
+	}
+}
+
+static void inputQuery(struct Tag tag, char *params) {
+	(void)tag;
+	char *nick = param("/query", &params, "name");
+	tabTouch(TAG_NONE, nick);
+	uiViewTag(tagFor(nick));
+}
+
 static void inputWho(struct Tag tag, char *params) {
 	(void)params;
 	ircFmt("WHO %s\r\n", tag.name);
@@ -113,15 +128,24 @@ static void inputView(struct Tag tag, char *params) {
 	}
 }
 
+static void inputClose(struct Tag tag, char *params) {
+	(void)params;
+	uiCloseTag(tag);
+	tabRemove(TAG_NONE, tag.name);
+}
+
 static const struct {
 	const char *command;
 	Handler handler;
 } COMMANDS[] = {
+	{ "/close", inputClose },
 	{ "/join", inputJoin },
 	{ "/me", inputMe },
 	{ "/names", inputWho },
 	{ "/nick", inputNick },
 	{ "/open", inputOpen },
+	{ "/part", inputPart },
+	{ "/query", inputQuery },
 	{ "/quit", inputQuit },
 	{ "/topic", inputTopic },
 	{ "/url", inputUrl },
diff --git a/ui.c b/ui.c
index 559f7b7..6fcb75e 100644
--- a/ui.c
+++ b/ui.c
@@ -70,11 +70,7 @@ static short pair8(short pair) {
 	return (pair & 0x70) >> 1 | (pair & 0x07);
 }
 
-static const int LOG_LINES   = 256;
-static const int TOPIC_COLS  = 512;
-static const int INPUT_COLS  = 512;
-
-static struct View {
+struct View {
 	struct Tag tag;
 	WINDOW *topic;
 	WINDOW *log;
@@ -82,16 +78,35 @@ static struct View {
 	bool mark;
 	struct View *prev;
 	struct View *next;
-} *viewHead, *viewTail;
+};
+
+static struct {
+	struct View *head;
+	struct View *tail;
+	struct View *tags[TAGS_LEN];
+} views;
 
 static void viewAppend(struct View *view) {
-	if (viewTail) viewTail->next = view;
-	view->prev = viewTail;
+	if (views.tail) views.tail->next = view;
+	view->prev = views.tail;
 	view->next = NULL;
-	viewTail = view;
-	if (!viewHead) viewHead = view;
+	if (!views.head) views.head = view;
+	views.tail = view;
+	views.tags[view->tag.id] = view;
+}
+
+static void viewRemove(struct View *view) {
+	if (view->prev) view->prev->next = view->next;
+	if (view->next) view->next->prev = view->prev;
+	if (views.head == view) views.head = view->next;
+	if (views.tail == view) views.tail = view->prev;
+	views.tags[view->tag.id] = NULL;
 }
 
+static const int LOG_LINES   = 256;
+static const int TOPIC_COLS  = 512;
+static const int INPUT_COLS  = 512;
+
 static int logHeight(const struct View *view) {
 	return LINES - (view->topic ? 2 : 0) - 2;
 }
@@ -105,15 +120,8 @@ static int lastCol(void) {
 	return COLS - 1;
 }
 
-static struct {
-	bool hide;
-	WINDOW *input;
-	struct View *view;
-	struct View *tags[TAGS_LEN];
-} ui;
-
 static struct View *viewTag(struct Tag tag) {
-	struct View *view = ui.tags[tag.id];
+	struct View *view = views.tags[tag.id];
 	if (view) return view;
 
 	view = calloc(1, sizeof(*view));
@@ -127,10 +135,22 @@ static struct View *viewTag(struct Tag tag) {
 	view->scroll = LOG_LINES;
 
 	viewAppend(view);
-	ui.tags[tag.id] = view;
 	return view;
 }
 
+static void viewClose(struct View *view) {
+	viewRemove(view);
+	if (view->topic) delwin(view->topic);
+	delwin(view->log);
+	free(view);
+}
+
+static struct {
+	bool hide;
+	struct View *view;
+	WINDOW *input;
+} ui;
+
 void uiHide(void) {
 	ui.hide = true;
 	termMode(TERM_FOCUS, false);
@@ -170,7 +190,7 @@ void uiExit(void) {
 }
 
 static void uiResize(void) {
-	for (struct View *view = viewHead; view; view = view->next) {
+	for (struct View *view = views.head; view; view = view->next) {
 		wresize(view->log, LOG_LINES, COLS);
 		wmove(view->log, lastLogLine(), lastCol());
 	}
@@ -215,19 +235,36 @@ static void uiView(struct View *view) {
 	ui.view = view;
 }
 
+static void uiClose(struct View *view) {
+	if (ui.view == view) {
+		if (view->next) {
+			uiView(view->next);
+		} else if (view->prev) {
+			uiView(view->prev);
+		} else {
+			return;
+		}
+	}
+	viewClose(view);
+}
+
 void uiViewTag(struct Tag tag) {
 	uiView(viewTag(tag));
 }
 
+void uiCloseTag(struct Tag tag) {
+	uiClose(viewTag(tag));
+}
+
 void uiViewNum(int num) {
 	if (num < 0) {
-		for (struct View *view = viewTail; view; view = view->prev) {
+		for (struct View *view = views.tail; view; view = view->prev) {
 			if (++num) continue;
 			uiView(view);
 			break;
 		}
 	} else {
-		for (struct View *view = viewHead; view; view = view->next) {
+		for (struct View *view = views.head; view; view = view->next) {
 			if (num--) continue;
 			uiView(view);
 			break;