HTMLify

ui.c
Views: 6 | Author: abh
#define _XOPEN_SOURCE_EXTENDED
#include <ncursesw/ncurses.h>
#include <string.h>
#include <locale.h>
#include "chatbot.h"
#include "ui.h"

enum {
    HEADER_BG,
    SEND_BUBBLE_BG,
    RECV_BUBBLE_BG,
    CHAT_BG,
    TEXT_AREA_BG,
    HEADER_COLOR,
    SEND_BUBBLE_COLOR,
    RECV_BUBBLE_COLOR,
    CHAT_COLOR,
    TEXT_AREA_COLOR,
};

void draw_chat_select_page(ChatBot chatbots[], int cbc, int selected) {
    int i, tly, tlx = (COLS-40)/2;
    for (i=0; i<cbc; i++) {
        tly = i*3;
        if (selected-1 == i)
            attron(A_REVERSE);
        
        mvaddwstr(tly+0, tlx, L"╔══════════════════════════════════════╗");
        mvaddwstr(tly+1, tlx, L"║                                      ║");
        mvaddwstr(tly+2, tlx, L"╚══════════════════════════════════════╝");
        mvaddstr(tly+1, tlx+2, chatbots[i].name);
        
        if (selected-1 == i)
            attroff(A_REVERSE);
    }
}

void draw_chatting_page(ChatBot chatbot, char *typed_message, ChatMsg messages[]) {
    int i, j;
    int top_pad = 4, bottom_pad = 3, left_pad = 2, right_pad = 2;


    // chat messages
    int
        vh = LINES - top_pad - bottom_pad,
        vw = COLS - left_pad - bottom_pad,
        vl = vh,
        mmw = vw * 0.8, msgi = chatbot.msgcount-1,
        msglen, mh, mw, mhwb, tw;
    ChatMsg msg;
    while (vl > 0 && msgi >= 0) {
        msg = chatbot.messages[msgi];
        msglen = strlen(msg.content);
        mw = msglen > mmw ? mmw : msglen;
        mh = ((msglen + 1)/ mw)+2+(msglen%mw?1:0);
        tw = 0;
        // attron(COLOR_PAIR(CHAT_COLOR));
        if (msg.type == SEND) {
            for (i=0; i<mw+2; i++) {
                mvaddwstr(top_pad + vl - mh, COLS - mw - 1 + i, L"▄");
                mvaddwstr(top_pad + vl - 1, COLS - mw - 1 + i, L"▀");
            }
            for (i=0; i<mh; i++) {
                if (i == 0) {
                    mvaddwstr(top_pad + vl - mh + i, COLS - mw - 2, L"▄");
                    mvaddwstr(top_pad + vl - mh + i, COLS - 1, L"▄");
                } else if (i == mh-1) { 
                    mvaddwstr(top_pad + vl - mh + i, COLS - mw - 2, L"▀");
                    mvaddwstr(top_pad + vl - mh + i, COLS - 1, L"▀");
                } else {
                    mvaddwstr(top_pad + vl - mh + i, COLS - mw - 2, L"█");
                    mvaddwstr(top_pad + vl - mh + i, COLS - 1, L"█");
                }
            }
            attron(COLOR_PAIR(SEND_BUBBLE_COLOR));
            for (i=1; i<mh; i++ && tw<msglen)
                for (j=0; j<mw && tw<msglen; j++, tw++)
                        mvaddch(top_pad + vl - mh + i, COLS-mw+j-1, msg.content[tw]);
            for (;tw%mw;tw++)
                mvaddch(top_pad + vl - mh + (tw/mw)+1, COLS-mw+(tw%mw)-1, ' ');
            attroff(COLOR_PAIR(SEND_BUBBLE_COLOR));

        } else {
            for (i=0; i<mw+2; i++) {
                mvaddwstr(top_pad + vl - mh, i, L"▄");
                mvaddwstr(top_pad + vl - 1, i, L"▀");
            }
            for (i=0; i<mh; i++) {
                if (i == 0) {
                    mvaddwstr(top_pad + vl -mh , 0, L"▄");
                    mvaddwstr(top_pad + vl -mh + i, mw+1, L"▄");
                } else if (i == mh-1) {        
                    mvaddwstr(top_pad + vl -mh + i, 0, L"▀");
                    mvaddwstr(top_pad + vl -mh + i, mw+1, L"▀");
                } else {
                    mvaddwstr(top_pad + vl -mh + i, 0, L"█");
                    mvaddwstr(top_pad + vl -mh + i, mw+1, L"█");
                }
            }
            attron(COLOR_PAIR(RECV_BUBBLE_COLOR));
            for (i=0; i<mh; i++ && tw<msglen)
                for (j=0; j<mw && tw<msglen; j++, tw++)
                    mvaddch(top_pad + vl - mh + i+1, j+1, msg.content[tw]);
            for (;tw%mw;tw++)
                mvaddch(top_pad + vl - mh + (tw/mw)+1, (tw%mw)+1, ' ');
            attroff(COLOR_PAIR(RECV_BUBBLE_COLOR));

        }
        // attroff(COLOR_PAIR(CHAT_COLOR));
        vl -= mh;
        msgi--;
    }
    

    // header
    attron(COLOR_PAIR(HEADER_COLOR));
    for (i=0; i<COLS; i++) {
        for (j=0; j<3; j++) {
            move(j, i);
            addch(' ');
        }
        mvaddwstr(j, i, L"━");
    }
    mvaddstr(1, 10, chatbot.name);
    mvprintw(1, COLS-20, "message count: %d", chatbot.msgcount);
    attroff(COLOR_PAIR(HEADER_COLOR));


    // text box
    attron(COLOR_PAIR(TEXT_AREA_COLOR));
    int len = strlen(typed_message);
    mvaddwstr(LINES-3, 0, L"╔"); for(i=1;i<COLS-1;i++)mvaddwstr(LINES-3,i,L"═"); mvaddwstr(LINES-3, COLS-1, L"╗");
    mvaddwstr(LINES-2, 0, L"║");
    for(i=1;i<COLS-1;i++)mvaddch(LINES-2,i,' ');
    for(i=(len>COLS-5?len-COLS+5:0),j=2;i<len;i++,j++)mvaddch(LINES-2,j,typed_message[i]);
    mvaddwstr(LINES-2, j, L"█");
    mvaddwstr(LINES-2, COLS-1, L"║"); 
    mvaddwstr(LINES-1, 0, L"╚"); for(i=1;i<COLS-1;i++)mvaddwstr(LINES-1,i,L"═"); mvaddwstr(LINES-1, COLS-1, L"╝");
    attroff(COLOR_PAIR(TEXT_AREA_COLOR));
}

void ui(int cbc, ChatBot chatbots[]) {
    Page page = CHAT_SELECT_PAGE;
    int selected = 0, key, type_cur_pos = 0;
    char typed_message[512] = "\0";
    ChatBot *selected_chatbot;

    setlocale(LC_ALL, "");
    initscr();
    noecho();
    curs_set(0);
    keypad(stdscr, true);
    start_color();

    // colors
    assume_default_colors(COLOR_WHITE, COLOR_BLACK);
    init_color(HEADER_BG, 85, 88, 88);
    init_color(SEND_BUBBLE_BG, 74, 301, 249);
    init_color(RECV_BUBBLE_BG, 141, 149, 149);
    init_color(CHAT_BG, 999, 441, 446);
    init_color(TEXT_AREA_BG, 141, 149, 149);
    init_pair(HEADER_COLOR, COLOR_WHITE, HEADER_BG);
    init_pair(SEND_BUBBLE_COLOR, COLOR_WHITE, SEND_BUBBLE_BG);
    init_pair(RECV_BUBBLE_COLOR, COLOR_WHITE, RECV_BUBBLE_BG);
    init_pair(CHAT_COLOR, COLOR_WHITE, CHAT_BG);
    init_pair(TEXT_AREA_COLOR, COLOR_WHITE, TEXT_AREA_BG);

    while (true) {
        erase();
        switch (page) {
            case CHAT_SELECT_PAGE:
                draw_chat_select_page(chatbots, cbc, selected);
                break;
            case CHATING_PAGE:
                draw_chatting_page(chatbots[selected-1], typed_message, chatbots[selected-1].messages);
                break;
        }

        key = getch();

        switch (page) {
            case CHAT_SELECT_PAGE:
                switch (key) {
                    case 'k':
                    case KEY_UP:
                        if (selected > 1)
                            selected--;
                        else
                            selected = cbc;
                        break;
                    case 'j':
                    case KEY_DOWN:
                        if (selected < cbc)
                            selected++;
                        else
                            selected = 1;
                        break;
                    case '\n':
                    case KEY_ENTER:
                        if (selected == 0)
                            continue;
                        page = CHATING_PAGE;
                        selected_chatbot = &chatbots[selected-1];
                        break;
                }
                break;

            case CHATING_PAGE:
                if (key == '\n') {
                    char *buf = strdup(typed_message);
                    ChatBot_chat(selected_chatbot, buf);
                    memset(typed_message, 0, 512);
                    type_cur_pos = 0;
                }
                if (key == KEY_BACKSPACE) {
                    if (type_cur_pos != 0) {
                        type_cur_pos--;
                        typed_message[type_cur_pos] = '\0';
                    }
                }
                if (key == 27) {
                    page = CHAT_SELECT_PAGE;
                }
                if (31 < key && key < 127) {
                    typed_message[type_cur_pos] = (char)key;
                    type_cur_pos++;
                    typed_message[type_cur_pos] = '\0';
                }
                break;
        }
    }

    endwin();
}

Comments