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); }
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); } }
static void friendlist_onDraw(ToxWindow *self, Tox *m) { curs_set(0); werase(self->window); int x2, y2; getmaxyx(self->window, y2, x2); bool fix_statuses = x2 != self->x; /* true if window max x value has changed */ wattron(self->window, COLOR_PAIR(CYAN)); wprintw(self->window, " Press the"); wattron(self->window, A_BOLD); wprintw(self->window, " h "); wattroff(self->window, A_BOLD); wprintw(self->window, "key for help\n\n"); wattroff(self->window, COLOR_PAIR(CYAN)); if (blocklist_view == 1) { blocklist_onDraw(self, m, y2, x2); return; } uint64_t cur_time = time(NULL); struct tm cur_loc_tm = *localtime((const time_t *) &cur_time); wattron(self->window, A_BOLD); wprintw(self->window, " Online: "); wattroff(self->window, A_BOLD); wprintw(self->window, "%d/%d \n\n", Friends.num_online, Friends.num_friends); if ((y2 - FLIST_OFST) <= 0) return; uint32_t selected_num = 0; /* Determine which portion of friendlist to draw based on current position */ pthread_mutex_lock(&Winthread.lock); int page = Friends.num_selected / (y2 - FLIST_OFST); pthread_mutex_unlock(&Winthread.lock); int start = (y2 - FLIST_OFST) * page; int end = y2 - FLIST_OFST + start; pthread_mutex_lock(&Winthread.lock); size_t num_friends = Friends.num_friends; pthread_mutex_unlock(&Winthread.lock); int i; for (i = start; i < num_friends && i < end; ++i) { pthread_mutex_lock(&Winthread.lock); uint32_t f = Friends.index[i]; bool is_active = Friends.list[f].active; int num_selected = Friends.num_selected; pthread_mutex_unlock(&Winthread.lock); bool f_selected = false; if (is_active) { if (i == num_selected) { wattron(self->window, A_BOLD); wprintw(self->window, " > "); wattroff(self->window, A_BOLD); selected_num = f; f_selected = true; } else { wprintw(self->window, " "); } pthread_mutex_lock(&Winthread.lock); TOX_CONNECTION connection_status = Friends.list[f].connection_status; TOX_USER_STATUS status = Friends.list[f].status; pthread_mutex_unlock(&Winthread.lock); if (connection_status != TOX_CONNECTION_NONE) { int colour = MAGENTA; switch (status) { case TOX_USER_STATUS_NONE: colour = GREEN; break; case TOX_USER_STATUS_AWAY: colour = YELLOW; break; case TOX_USER_STATUS_BUSY: colour = RED; break; } wattron(self->window, COLOR_PAIR(colour) | A_BOLD); wprintw(self->window, "%s ", ONLINE_CHAR); wattroff(self->window, COLOR_PAIR(colour) | A_BOLD); if (f_selected) wattron(self->window, COLOR_PAIR(BLUE)); wattron(self->window, A_BOLD); pthread_mutex_lock(&Winthread.lock); wprintw(self->window, "%s", Friends.list[f].name); pthread_mutex_unlock(&Winthread.lock); wattroff(self->window, A_BOLD); if (f_selected) wattroff(self->window, COLOR_PAIR(BLUE)); /* Reset Friends.list[f].statusmsg on window resize */ if (fix_statuses) { char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH]; pthread_mutex_lock(&Winthread.lock); tox_friend_get_status_message(m, Friends.list[f].num, (uint8_t *) statusmsg, NULL); size_t s_len = tox_friend_get_status_message_size(m, Friends.list[f].num, NULL); pthread_mutex_unlock(&Winthread.lock); statusmsg[s_len] = '\0'; filter_str(statusmsg, s_len); pthread_mutex_lock(&Winthread.lock); snprintf(Friends.list[f].statusmsg, sizeof(Friends.list[f].statusmsg), "%s", statusmsg); Friends.list[f].statusmsg_len = strlen(Friends.list[f].statusmsg); pthread_mutex_unlock(&Winthread.lock); } /* Truncate note if it doesn't fit on one line */ size_t maxlen = x2 - getcurx(self->window) - 2; pthread_mutex_lock(&Winthread.lock); if (Friends.list[f].statusmsg_len > maxlen) { Friends.list[f].statusmsg[maxlen - 3] = '\0'; strcat(Friends.list[f].statusmsg, "..."); Friends.list[f].statusmsg[maxlen] = '\0'; Friends.list[f].statusmsg_len = maxlen; } if (Friends.list[f].statusmsg_len > 0) wprintw(self->window, " %s", Friends.list[f].statusmsg); pthread_mutex_unlock(&Winthread.lock); wprintw(self->window, "\n"); } else { wprintw(self->window, "%s ", OFFLINE_CHAR); if (f_selected) wattron(self->window, COLOR_PAIR(BLUE)); wattron(self->window, A_BOLD); pthread_mutex_lock(&Winthread.lock); wprintw(self->window, "%s", Friends.list[f].name); pthread_mutex_unlock(&Winthread.lock); wattroff(self->window, A_BOLD); if (f_selected) wattroff(self->window, COLOR_PAIR(BLUE)); pthread_mutex_lock(&Winthread.lock); uint64_t last_seen = Friends.list[f].last_online.last_on; pthread_mutex_unlock(&Winthread.lock); if (last_seen != 0) { pthread_mutex_lock(&Winthread.lock); int day_dist = ( cur_loc_tm.tm_yday - Friends.list[f].last_online.tm.tm_yday + ((cur_loc_tm.tm_year - Friends.list[f].last_online.tm.tm_year) * 365) ); const char *hourmin = Friends.list[f].last_online.hour_min_str; pthread_mutex_unlock(&Winthread.lock); switch (day_dist) { case 0: wprintw(self->window, " Last seen: Today %s\n", hourmin); break; case 1: wprintw(self->window, " Last seen: Yesterday %s\n", hourmin); break; default: wprintw(self->window, " Last seen: %d days ago\n", day_dist); break; } } else { wprintw(self->window, " Last seen: Never\n"); } } } } self->x = x2; if (num_friends) { wmove(self->window, y2 - 1, 1); wattron(self->window, A_BOLD); wprintw(self->window, "Key: "); wattroff(self->window, A_BOLD); int i; for (i = 0; i < TOX_PUBLIC_KEY_SIZE; ++i) wprintw(self->window, "%02X", Friends.list[selected_num].pub_key[i] & 0xff); } wrefresh(self->window); draw_del_popup(); if (self->help->active) help_onDraw(self); }
static void blocklist_onDraw(ToxWindow *self, Tox *m, int y2, int x2) { wattron(self->window, A_BOLD); wprintw(self->window, " Blocked: "); wattroff(self->window, A_BOLD); wprintw(self->window, "%d\n\n", Blocked.num_blocked); if ((y2 - FLIST_OFST) <= 0) return; uint32_t selected_num = 0; /* Determine which portion of friendlist to draw based on current position */ int page = Blocked.num_selected / (y2 - FLIST_OFST); int start = (y2 - FLIST_OFST) * page; int end = y2 - FLIST_OFST + start; int i; for (i = start; i < Blocked.num_blocked && i < end; ++i) { uint32_t f = Blocked.index[i]; bool f_selected = false; if (i == Blocked.num_selected) { wattron(self->window, A_BOLD); wprintw(self->window, " > "); wattroff(self->window, A_BOLD); selected_num = f; f_selected = true; } else { wprintw(self->window, " "); } wattron(self->window, COLOR_PAIR(RED)); wprintw(self->window, "x"); wattroff(self->window, COLOR_PAIR(RED)); if (f_selected) wattron(self->window, COLOR_PAIR(BLUE)); wattron(self->window, A_BOLD); wprintw(self->window, " %s\n", Blocked.list[f].name); wattroff(self->window, A_BOLD); if (f_selected) wattroff(self->window, COLOR_PAIR(BLUE)); } wprintw(self->window, "\n"); self->x = x2; if (Blocked.num_blocked) { wmove(self->window, y2 - 1, 1); wattron(self->window, A_BOLD); wprintw(self->window, "Key: "); wattroff(self->window, A_BOLD); int i; for (i = 0; i < TOX_PUBLIC_KEY_SIZE; ++i) wprintw(self->window, "%02X", Blocked.list[selected_num].pub_key[i] & 0xff); } wrefresh(self->window); draw_del_popup(); if (self->help->active) help_onDraw(self); }
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); }
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); }
static void friendlist_onDraw(ToxWindow *self, Tox *m) { curs_set(0); werase(self->window); int x2, y2; getmaxyx(self->window, y2, x2); bool fix_statuses = x2 != self->x; /* true if window max x value has changed */ wattron(self->window, COLOR_PAIR(CYAN)); wprintw(self->window, " Press the"); wattron(self->window, A_BOLD); wprintw(self->window, " H "); wattroff(self->window, A_BOLD); wprintw(self->window, "key for help\n\n"); wattroff(self->window, COLOR_PAIR(CYAN)); if (blocklist_view == 1) { blocklist_onDraw(self, m, y2, x2); return; } uint64_t cur_time = get_unix_time(); struct tm cur_loc_tm = *localtime((const time_t *) &cur_time); pthread_mutex_lock(&Winthread.lock); int nf = tox_get_num_online_friends(m); pthread_mutex_unlock(&Winthread.lock); wattron(self->window, A_BOLD); wprintw(self->window, " Online: "); wattroff(self->window, A_BOLD); wprintw(self->window, "%d/%d \n\n", nf, num_friends); if ((y2 - FLIST_OFST) <= 0) return; int selected_num = 0; /* Determine which portion of friendlist to draw based on current position */ int page = num_selected / (y2 - FLIST_OFST); int start = (y2 - FLIST_OFST) * page; int end = y2 - FLIST_OFST + start; int i; for (i = start; i < num_friends && i < end; ++i) { int f = friendlist_index[i]; bool f_selected = false; if (friends[f].active) { if (i == num_selected) { wattron(self->window, A_BOLD); wprintw(self->window, " > "); wattroff(self->window, A_BOLD); selected_num = f; f_selected = true; } else { wprintw(self->window, " "); } if (friends[f].online) { uint8_t status = friends[f].status; int colour = WHITE; 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(self->window, COLOR_PAIR(colour) | A_BOLD); wprintw(self->window, "%s ", ONLINE_CHAR); wattroff(self->window, COLOR_PAIR(colour) | A_BOLD); if (f_selected) wattron(self->window, COLOR_PAIR(BLUE)); wattron(self->window, A_BOLD); wprintw(self->window, "%s", friends[f].name); wattroff(self->window, A_BOLD); if (f_selected) wattroff(self->window, COLOR_PAIR(BLUE)); /* Reset friends[f].statusmsg on window resize */ if (fix_statuses) { char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH]; pthread_mutex_lock(&Winthread.lock); tox_get_status_message(m, friends[f].num, (uint8_t *) statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH); pthread_mutex_unlock(&Winthread.lock); snprintf(friends[f].statusmsg, sizeof(friends[f].statusmsg), "%s", statusmsg); friends[f].statusmsg_len = strlen(friends[f].statusmsg); } /* Truncate note if it doesn't fit on one line */ uint16_t maxlen = x2 - getcurx(self->window) - 2; if (friends[f].statusmsg_len > maxlen) { friends[f].statusmsg[maxlen - 3] = '\0'; strcat(friends[f].statusmsg, "..."); friends[f].statusmsg[maxlen] = '\0'; friends[f].statusmsg_len = maxlen; } if (friends[f].statusmsg[0]) wprintw(self->window, " %s", friends[f].statusmsg); wprintw(self->window, "\n"); } else { wprintw(self->window, "%s ", OFFLINE_CHAR); if (f_selected) wattron(self->window, COLOR_PAIR(BLUE)); wattron(self->window, A_BOLD); wprintw(self->window, "%s", friends[f].name); wattroff(self->window, A_BOLD); if (f_selected) wattroff(self->window, COLOR_PAIR(BLUE)); uint64_t last_seen = friends[f].last_online.last_on; if (last_seen != 0) { int day_dist = (cur_loc_tm.tm_yday - friends[f].last_online.tm.tm_yday) % 365; const char *hourmin = friends[f].last_online.hour_min_str; switch (day_dist) { case 0: wprintw(self->window, " Last seen: Today %s\n", hourmin); break; case 1: wprintw(self->window, " Last seen: Yesterday %s\n", hourmin); break; default: wprintw(self->window, " Last seen: %d days ago\n", day_dist); break; } } else { wprintw(self->window, " Last seen: Never\n"); } } } } self->x = x2; if (num_friends) { wmove(self->window, y2 - 1, 1); wattron(self->window, A_BOLD); wprintw(self->window, "ID: "); wattroff(self->window, A_BOLD); int i; for (i = 0; i < TOX_CLIENT_ID_SIZE; ++i) wprintw(self->window, "%02X", friends[selected_num].pub_key[i] & 0xff); } wrefresh(self->window); draw_del_popup(); if (self->help->active) help_onDraw(self); }