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", ¶ms, "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;