Beispiel #1
0
/* refresh inactive windows to prevent scrolling bugs. 
   call at least once per second */
void refresh_inactive_windows(void)
{
    int i;

    for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
        ToxWindow *a = &windows[i];

        if (a->active && a != active_window && !a->is_friendlist)
            line_info_print(a);
    }
}
Beispiel #2
0
void line_info_print(ToxWindow *self)
{
    ChatContext *ctx = self->chatwin;

    if (ctx == NULL)
        return;

    struct history *hst = ctx->hst;

    /* Only allow one new item to be added to chat window per call to this function */
    line_info_check_queue(self);

    WINDOW *win = ctx->history;
    wclear(win);
    int y2, x2;
    getmaxyx(self->window, y2, x2);

    if (x2 <= SIDEBAR_WIDTH)
        return;

    if (self->is_groupchat)
        wmove(win, 0, 0);
    else
        wmove(win, 2, 0);

    struct line_info *line = hst->line_start->next;
    int numlines = 0;

    while (line && numlines++ <= y2) {
        uint8_t type = line->type;

        switch (type) {
            case OUT_MSG:
            case IN_MSG:
                wattron(win, COLOR_PAIR(BLUE));
                wprintw(win, "%s", line->timestamp);
                wattroff(win, COLOR_PAIR(BLUE));

                int nameclr = GREEN;

                if (line->colour)
                    nameclr = line->colour;
                else if (type == IN_MSG)
                    nameclr = CYAN;

                wattron(win, COLOR_PAIR(nameclr));
                wprintw(win, "%s: ", line->name1);
                wattroff(win, COLOR_PAIR(nameclr));

                if (line->msg[0] == '>')
                    wattron(win, COLOR_PAIR(GREEN));

                wprintw(win, "%s\n", line->msg);

                if (line->msg[0] == '>')
                    wattroff(win, COLOR_PAIR(GREEN));

                break;

            case ACTION:
                wattron(win, COLOR_PAIR(BLUE));
                wprintw(win, "%s", line->timestamp);
                wattroff(win, COLOR_PAIR(BLUE));

                wattron(win, COLOR_PAIR(YELLOW));
                wprintw(win, "* %s %s\n", line->name1, line->msg);
                wattroff(win, COLOR_PAIR(YELLOW));

                break;

            case SYS_MSG:
                if (line->timestamp[0]) {
                    wattron(win, COLOR_PAIR(BLUE));
                    wprintw(win, "%s", line->timestamp);
                    wattroff(win, COLOR_PAIR(BLUE));
                }

                if (line->bold)
                    wattron(win, A_BOLD);

                if (line->colour)
                    wattron(win, COLOR_PAIR(line->colour));

                wprintw(win, "%s\n", line->msg);

                if (line->bold)
                    wattroff(win, A_BOLD);

                if (line->colour)
                    wattroff(win, COLOR_PAIR(line->colour));

                break;

            case PROMPT:
                wattron(win, COLOR_PAIR(GREEN));
                wprintw(win, "$ ");
                wattroff(win, COLOR_PAIR(GREEN));

                if (line->msg[0])
                    wprintw(win, "%s", line->msg);

                wprintw(win, "\n");
                break;

            case CONNECTION:
                wattron(win, COLOR_PAIR(BLUE));
                wprintw(win, "%s", line->timestamp);
                wattroff(win, COLOR_PAIR(BLUE));

                wattron(win, COLOR_PAIR(line->colour));
                wattron(win, A_BOLD);
                wprintw(win, "* %s ", line->name1);
                wattroff(win, A_BOLD);
                wprintw(win, "%s\n", line->msg);
                wattroff(win, COLOR_PAIR(line->colour));

                break;

            case NAME_CHANGE:
                wattron(win, COLOR_PAIR(BLUE));
                wprintw(win, "%s", line->timestamp);
                wattroff(win, COLOR_PAIR(BLUE));

                wattron(win, COLOR_PAIR(MAGENTA));
                wattron(win, A_BOLD);
                wprintw(win, "* %s", line->name1);
                wattroff(win, A_BOLD);

                wprintw(win, "%s", line->msg);

                wattron(win, A_BOLD);
                wprintw(win, "%s\n", line->name2);
                wattroff(win, A_BOLD);
                wattroff(win, COLOR_PAIR(MAGENTA));

                break;
        }

        line = line->next;
    }

    /* keep calling until queue is empty */
    if (hst->queue_sz > 0)
        line_info_print(self);
}
Beispiel #3
0
static void prompt_onDraw(ToxWindow *self, Tox *m)
{
    int x2, y2;
    getmaxyx(self->window, y2, x2);

    ChatContext *ctx = self->chatwin;

    line_info_print(self);
    wclear(ctx->linewin);

    curs_set(1);

    if (ctx->len > 0)
        mvwprintw(ctx->linewin, 1, 0, "%ls", &ctx->line[ctx->start]);

    StatusBar *statusbar = self->stb;
    mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2);
    wmove(statusbar->topline, 0, 0);

    if (statusbar->is_online) {
        int colour = WHITE;
        const uint8_t *status_text = "Unknown";

        switch (statusbar->status) {
            case TOX_USERSTATUS_NONE:
                status_text = "Online";
                colour = GREEN;
                break;

            case TOX_USERSTATUS_AWAY:
                status_text = "Away";
                colour = YELLOW;
                break;

            case TOX_USERSTATUS_BUSY:
                status_text = "Busy";
                colour = RED;
                break;

            case TOX_USERSTATUS_INVALID:
                status_text = "ERROR";
                colour = MAGENTA;
                break;
        }

        wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
        wprintw(statusbar->topline, " [%s]", status_text);
        wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);

        wattron(statusbar->topline, A_BOLD);
        wprintw(statusbar->topline, " %s", statusbar->nick);
        wattroff(statusbar->topline, A_BOLD);
    } else {
        wprintw(statusbar->topline, "[Offline]");
        wattron(statusbar->topline, A_BOLD);
        wprintw(statusbar->topline, " %s ", statusbar->nick);
        wattroff(statusbar->topline, A_BOLD);
    }

    if (statusbar->statusmsg[0])
        wprintw(statusbar->topline, " - %s", statusbar->statusmsg);

    mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2);

    int y, x;
    getyx(self->window, y, x);
    int new_x = ctx->start ? x2 - 1 : ctx->pos;
    wmove(self->window, y + 1, new_x);

    if (self->help->active) {
        wrefresh(self->window);
        help_onDraw(self);
    }
}
Beispiel #4
0
static void prompt_onDraw(ToxWindow *self, Tox *m)
{
    int x2, y2;
    getmaxyx(self->window, y2, x2);

    ChatContext *ctx = self->chatwin;

    line_info_print(self);
    wclear(ctx->linewin);

    curs_set(1);

    if (ctx->len > 0)
        mvwprintw(ctx->linewin, 1, 0, "%ls", &ctx->line[ctx->start]);

    StatusBar *statusbar = self->stb;
    mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2);
    wmove(statusbar->topline, 0, 0);

    if (statusbar->is_online) {
        int colour = WHITE;
        const char *status_text = "Unknown";

        switch (statusbar->status) {
            case TOX_USERSTATUS_NONE:
                status_text = "Online";
                colour = GREEN;
                break;

            case TOX_USERSTATUS_AWAY:
                status_text = "Away";
                colour = YELLOW;
                break;

            case TOX_USERSTATUS_BUSY:
                status_text = "Busy";
                colour = RED;
                break;

            case TOX_USERSTATUS_INVALID:
                status_text = "ERROR";
                colour = MAGENTA;
                break;
        }

        wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
        wprintw(statusbar->topline, " [%s]", status_text);
        wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);

        wattron(statusbar->topline, A_BOLD);
        wprintw(statusbar->topline, " %s", statusbar->nick);
        wattroff(statusbar->topline, A_BOLD);
    } else {
        wprintw(statusbar->topline, " [Offline]");
        wattron(statusbar->topline, A_BOLD);
        wprintw(statusbar->topline, " %s ", statusbar->nick);
        wattroff(statusbar->topline, A_BOLD);
    }

    /* Reset statusbar->statusmsg on window resize */
    if (x2 != self->x) {
        char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {0};

        pthread_mutex_lock(&Winthread.lock);
        tox_get_self_status_message(m, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH);
        pthread_mutex_unlock(&Winthread.lock);

        snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg);
        statusbar->statusmsg_len = strlen(statusbar->statusmsg);
    }

    self->x = x2;

    /* Truncate note if it doesn't fit in statusbar */
    uint16_t maxlen = x2 - getcurx(statusbar->topline) - 3;

    if (statusbar->statusmsg_len > maxlen) {
        statusbar->statusmsg[maxlen - 3] = '\0';
        strcat(statusbar->statusmsg, "...");
        statusbar->statusmsg_len = maxlen;
    }

    if (statusbar->statusmsg[0])
        wprintw(statusbar->topline, " - %s", statusbar->statusmsg);

    mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2);

    int y, x;
    getyx(self->window, y, x);
    (void) x;

    int new_x = ctx->start ? x2 - 1 : wcswidth(ctx->line, ctx->pos);
    wmove(self->window, y + 1, new_x);

    wrefresh(self->window);

    if (self->help->active)
        help_onDraw(self);
}
Beispiel #5
0
static void groupchat_onDraw(ToxWindow *self, Tox *m)
{
    int x2, y2;
    getmaxyx(self->window, y2, x2);

    if (x2 <= 0 || y2 <= 0)
        return;

    ChatContext *ctx = self->chatwin;

    pthread_mutex_lock(&Winthread.lock);
    line_info_print(self);
    pthread_mutex_unlock(&Winthread.lock);

    wclear(ctx->linewin);

    curs_set(1);

    if (ctx->len > 0)
        mvwprintw(ctx->linewin, 1, 0, "%ls", &ctx->line[ctx->start]);

    wclear(ctx->sidebar);
    mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2);

    if (self->show_peerlist) {
        mvwvline(ctx->sidebar, 0, 0, ACS_VLINE, y2 - CHATBOX_HEIGHT);
        mvwaddch(ctx->sidebar, y2 - CHATBOX_HEIGHT, 0, ACS_BTEE);

        int num_peers = groupchats[self->num].num_peers;

        wmove(ctx->sidebar, 0, 1);
        wattron(ctx->sidebar, A_BOLD);
        wprintw(ctx->sidebar, "Peers: %d\n", num_peers);
        wattroff(ctx->sidebar, A_BOLD);

        mvwaddch(ctx->sidebar, 1, 0, ACS_LTEE);
        mvwhline(ctx->sidebar, 1, 1, ACS_HLINE, SIDEBAR_WIDTH - 1);

        int maxlines = y2 - SDBAR_OFST - CHATBOX_HEIGHT;
        int i;

        for (i = 0; i < num_peers && i < maxlines; ++i) {
            wmove(ctx->sidebar, i + 2, 1);
            int peer = i + groupchats[self->num].side_pos;

            /* truncate nick to fit in side panel without modifying list */
            char tmpnck[TOX_MAX_NAME_LENGTH];
            int maxlen = SIDEBAR_WIDTH - 2;
            memcpy(tmpnck, &groupchats[self->num].peer_names[peer * TOX_MAX_NAME_LENGTH], maxlen);
            tmpnck[maxlen] = '\0';

            wprintw(ctx->sidebar, "%s\n", tmpnck);
        }
    }

    int y, x;
    getyx(self->window, y, x);
    (void) x;
    int new_x = ctx->start ? x2 - 1 : MAX(0, wcswidth(ctx->line, ctx->pos));
    wmove(self->window, y + 1, new_x);

    wrefresh(self->window);

    if (self->help->active)
        help_onDraw(self);
}
Beispiel #6
0
void line_info_print(ToxWindow *self)
{
    ChatContext *ctx = self->chatwin;

    if (ctx == NULL)
        return;

    struct history *hst = ctx->hst;

    /* Only allow one new item to be added to chat window per call to this function */
    line_info_check_queue(self);

    WINDOW *win = ctx->history;
    wclear(win);
    int y2, x2;
    getmaxyx(self->window, y2, x2);

    if (x2 <= SIDEBAR_WIDTH)
        return;

    if (self->is_groupchat)
        wmove(win, 0, 0);
    else
        wmove(win, 2, 0);

    struct line_info *line = hst->line_start->next;
    int numlines = 0;

    while (line && numlines++ <= y2) {
        uint8_t type = line->type;

        switch (type) {
        case OUT_MSG:
        /* fallthrough */
        case OUT_MSG_READ:
        /* fallthrough */
        case IN_MSG:
            wattron(win, COLOR_PAIR(BLUE));
            wprintw(win, "%s ", line->timestr);
            wattroff(win, COLOR_PAIR(BLUE));

            int nameclr = GREEN;

            if (line->colour)
                nameclr = line->colour;
            else if (type == IN_MSG)
                nameclr = CYAN;

            wattron(win, COLOR_PAIR(nameclr));
            wprintw(win, "%s %s: ", user_settings->line_normal, line->name1);
            wattroff(win, COLOR_PAIR(nameclr));

            if (line->msg[0] == '>')
                wattron(win, COLOR_PAIR(GREEN));

            wprintw(win, "%s", line->msg);

            if (line->msg[0] == '>')
                wattroff(win, COLOR_PAIR(GREEN));

            if (type == OUT_MSG && timed_out(line->timestamp, get_unix_time(), NOREAD_FLAG_TIMEOUT)) {
                wattron(win, COLOR_PAIR(RED));
                wprintw(win, " x", line->msg);
                wattroff(win, COLOR_PAIR(RED));

                if (line->noread_flag == false) {
                    line->noread_flag = true;
                    line->len += 2;
                }
            }

            wprintw(win, "\n", line->msg);
            break;

        case OUT_ACTION_READ:
        /* fallthrough */
        case OUT_ACTION:
        /* fallthrough */
        case IN_ACTION:
            wattron(win, COLOR_PAIR(BLUE));
            wprintw(win, "%s ", line->timestr);
            wattroff(win, COLOR_PAIR(BLUE));

            wattron(win, COLOR_PAIR(YELLOW));
            wprintw(win, "%s %s %s", user_settings->line_normal, line->name1, line->msg);
            wattroff(win, COLOR_PAIR(YELLOW));

            if (type == OUT_ACTION && timed_out(line->timestamp, get_unix_time(), NOREAD_FLAG_TIMEOUT)) {
                wattron(win, COLOR_PAIR(RED));
                wprintw(win, " x", line->msg);
                wattroff(win, COLOR_PAIR(RED));

                if (line->noread_flag == false) {
                    line->noread_flag = true;
                    line->len += 2;
                }
            }

            wprintw(win, "\n", line->msg);
            break;

        case SYS_MSG:
            if (line->timestr[0]) {
                wattron(win, COLOR_PAIR(BLUE));
                wprintw(win, "%s ", line->timestr);
                wattroff(win, COLOR_PAIR(BLUE));
            }

            if (line->bold)
                wattron(win, A_BOLD);

            if (line->colour)
                wattron(win, COLOR_PAIR(line->colour));

            wprintw(win, "%s\n", line->msg);

            if (line->bold)
                wattroff(win, A_BOLD);

            if (line->colour)
                wattroff(win, COLOR_PAIR(line->colour));

            break;

        case PROMPT:
            wattron(win, COLOR_PAIR(GREEN));
            wprintw(win, "$ ");
            wattroff(win, COLOR_PAIR(GREEN));

            if (line->msg[0])
                wprintw(win, "%s", line->msg);

            wprintw(win, "\n");
            break;

        case CONNECTION:
            wattron(win, COLOR_PAIR(BLUE));
            wprintw(win, "%s ", line->timestr);
            wattroff(win, COLOR_PAIR(BLUE));

            wattron(win, COLOR_PAIR(line->colour));
            wprintw(win, "%s ", user_settings->line_join);

            wattron(win, A_BOLD);
            wprintw(win, "%s ", line->name1);
            wattroff(win, A_BOLD);

            wprintw(win, "%s\n", line->msg);
            wattroff(win, COLOR_PAIR(line->colour));

            break;

        case DISCONNECTION:
            wattron(win, COLOR_PAIR(BLUE));
            wprintw(win, "%s ", line->timestr);
            wattroff(win, COLOR_PAIR(BLUE));

            wattron(win, COLOR_PAIR(line->colour));
            wprintw(win, "%s ", user_settings->line_quit);

            wattron(win, A_BOLD);
            wprintw(win, "%s ", line->name1);
            wattroff(win, A_BOLD);

            wprintw(win, "%s\n", line->msg);
            wattroff(win, COLOR_PAIR(line->colour));

            break;

        case NAME_CHANGE:
            wattron(win, COLOR_PAIR(BLUE));
            wprintw(win, "%s ", line->timestr);
            wattroff(win, COLOR_PAIR(BLUE));

            wattron(win, COLOR_PAIR(MAGENTA));
            wprintw(win, "%s ", user_settings->line_alert);
            wattron(win, A_BOLD);
            wprintw(win, "%s", line->name1);
            wattroff(win, A_BOLD);

            wprintw(win, "%s", line->msg);

            wattron(win, A_BOLD);
            wprintw(win, "%s\n", line->name2);
            wattroff(win, A_BOLD);
            wattroff(win, COLOR_PAIR(MAGENTA));

            break;
        }

        line = line->next;
    }

    /* keep calling until queue is empty */
    if (hst->queue_sz > 0)
        line_info_print(self);
}
Beispiel #7
0
static void chat_onDraw(ToxWindow *self, Tox *m)
{
    int x2, y2;
    getmaxyx(self->window, y2, x2);

    ChatContext *ctx = self->chatwin;

    line_info_print(self);
    wclear(ctx->linewin);

    curs_set(1);

    if (ctx->len > 0)
        mvwprintw(ctx->linewin, 1, 0, "%ls", &ctx->line[ctx->start]);

    /* Draw status bar */
    StatusBar *statusbar = self->stb;
    mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2);
    wmove(statusbar->topline, 0, 0);

    /* Draw name, status and note in statusbar */
    if (statusbar->is_online) {
        int colour = WHITE;
        uint8_t status = statusbar->status;

        switch (status) {
            case TOX_USERSTATUS_NONE:
                colour = GREEN;
                break;

            case TOX_USERSTATUS_AWAY:
                colour = YELLOW;
                break;

            case TOX_USERSTATUS_BUSY:
                colour = RED;
                break;

            case TOX_USERSTATUS_INVALID:
                colour = MAGENTA;
                break;
        }

        wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
        wprintw(statusbar->topline, " %s", ONLINE_CHAR);
        wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);

        if (friends[self->num].is_typing)
            wattron(statusbar->topline, COLOR_PAIR(YELLOW));

        wattron(statusbar->topline, A_BOLD);
        wprintw(statusbar->topline, " %s ", statusbar->nick);
        wattroff(statusbar->topline, A_BOLD);

        if (friends[self->num].is_typing)
            wattroff(statusbar->topline, COLOR_PAIR(YELLOW));
    } else {
        wprintw(statusbar->topline, " %s", OFFLINE_CHAR);
        wattron(statusbar->topline, A_BOLD);
        wprintw(statusbar->topline, " %s ", statusbar->nick);
        wattroff(statusbar->topline, A_BOLD);
    }

    /* Reset statusbar->statusmsg on window resize */
    if (x2 != self->x) {
        char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'};

        pthread_mutex_lock(&Winthread.lock);
        tox_get_status_message(m, self->num, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH);
        pthread_mutex_unlock(&Winthread.lock);

        snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg);
        statusbar->statusmsg_len = strlen(statusbar->statusmsg);
    }

    self->x = x2;

    /* Truncate note if it doesn't fit in statusbar */
    uint16_t maxlen = x2 - getcurx(statusbar->topline) - (KEY_IDENT_DIGITS * 2) - 7;

    if (statusbar->statusmsg_len > maxlen) {
        statusbar->statusmsg[maxlen] = '\0';
        statusbar->statusmsg_len = maxlen;
    }

    if (statusbar->statusmsg[0])
        wprintw(statusbar->topline, "- %s ", statusbar->statusmsg);

    wclrtoeol(statusbar->topline);
    wmove(statusbar->topline, 0, x2 - (KEY_IDENT_DIGITS * 2) - 3);
    wprintw(statusbar->topline, "{");

    int i;

    for (i = 0; i < KEY_IDENT_DIGITS; ++i)
        wprintw(statusbar->topline, "%02X", friends[self->num].pub_key[i] & 0xff);

    wprintw(statusbar->topline, "}\n");

    mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2);

    int y, x;
    getyx(self->window, y, x);
    (void) x;
    int new_x = ctx->start ? x2 - 1 : wcswidth(ctx->line, ctx->pos);
    wmove(self->window, y + 1, new_x);

    wrefresh(self->window);

#ifdef _AUDIO
    if (ctx->infobox.active) {
        draw_infobox(self);
        wrefresh(self->window);
    }
#endif

    if (self->help->active)
        help_onDraw(self);
}
Beispiel #8
0
static void prompt_onDraw(ToxWindow *self, Tox *m)
{
    ChatContext *ctx = self->chatwin;

    int x, y, x2, y2;
    getyx(ctx->history, y, x);
    getmaxyx(ctx->history, y2, x2);

    if (!ctx->hst->scroll_mode)
        curs_set(1);

    line_info_print(self);

    /* if len is >= screen width offset max x by X_OFST to account for prompt char */
    int px2 = ctx->len >= x2 ? x2 : x2 - X_OFST;

    if (px2 <= 0)
        return;

    /* len offset to account for prompt char (0 if len is < width of screen) */
    int p_ofst = px2 != x2 ? 0 : X_OFST;

    if (ctx->len > 0) {
        uint8_t line[MAX_STR_SIZE];

        if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
            reset_buf(ctx->line, &ctx->pos, &ctx->len);
        else
            mvwprintw(ctx->history, ctx->orig_y, X_OFST, line);

        int k = ctx->orig_y + ((ctx->len + p_ofst) / px2);

        ctx->at_bottom = k == y2 - 1;
        bool botm = k == y2;
        bool edge = (ctx->len + p_ofst) % px2 == 0;

        /* move point of line origin up when input scrolls screen down */
        if (edge && botm)
            --ctx->orig_y;

    } else {    /* Mark point of origin for new line */
        ctx->orig_y = y;    
    }

    wattron(ctx->history, COLOR_PAIR(GREEN));
    mvwprintw(ctx->history, ctx->orig_y, 0, "$ ");
    wattroff(ctx->history, COLOR_PAIR(GREEN));

    StatusBar *statusbar = self->stb;
    werase(statusbar->topline);
    mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2);
    wmove(statusbar->topline, 0, 0);

    if (statusbar->is_online) {
        int colour = WHITE;
        const uint8_t *status_text = "Unknown";

        switch (statusbar->status) {
        case TOX_USERSTATUS_NONE:
            status_text = "Online";
            colour = GREEN;
            break;
        case TOX_USERSTATUS_AWAY:
            status_text = "Away";
            colour = YELLOW;
            break;
        case TOX_USERSTATUS_BUSY:
            status_text = "Busy";
            colour = RED;
            break;
        case TOX_USERSTATUS_INVALID:
            status_text = "ERROR";
            colour = MAGENTA;
            break;
        }
        wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
        wprintw(statusbar->topline, " [%s]", status_text);
        wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);

        wattron(statusbar->topline, A_BOLD);
        wprintw(statusbar->topline, " %s", statusbar->nick);
        wattroff(statusbar->topline, A_BOLD);
    } else {
        wprintw(statusbar->topline, "[Offline]");
        wattron(statusbar->topline, A_BOLD);
        wprintw(statusbar->topline, " %s ", statusbar->nick);
        wattroff(statusbar->topline, A_BOLD);
    }

    if (statusbar->statusmsg[0])
        wprintw(statusbar->topline, " - %s", statusbar->statusmsg);

    /* put cursor back in correct spot */
    int y_m = ctx->orig_y + ((ctx->pos + p_ofst) / px2);
    int x_m = (ctx->pos + X_OFST) % x2;
    wmove(self->window, y_m, x_m);
}