From 9457a74c256bdf090667a5b19238cb5dfd7e031e Mon Sep 17 00:00:00 2001 From: Joursoir Date: Mon, 7 Dec 2020 11:47:44 +0000 Subject: add gui without functionality --- src/client/clui/Makefile | 18 +++++ src/client/clui/client.cpp | 35 +++++++++ src/client/clui/clui.cpp | 187 +++++++++++++++++++++++++++++++++++++++++++++ src/client/clui/clui.hpp | 61 +++++++++++++++ src/client/clui/user.cpp | 153 +++++++++++++++++++++++++++++++++++++ src/client/clui/user.hpp | 32 ++++++++ src/client/gui/Makefile | 18 +++++ src/client/gui/client | Bin 0 -> 46288 bytes src/client/gui/client.cpp | 109 ++++++++++++++++++++++++++ src/client_clui/Makefile | 18 ----- src/client_clui/client.cpp | 35 --------- src/client_clui/clui.cpp | 187 --------------------------------------------- src/client_clui/clui.hpp | 61 --------------- src/client_clui/user.cpp | 153 ------------------------------------- src/client_clui/user.hpp | 32 -------- 15 files changed, 613 insertions(+), 486 deletions(-) create mode 100644 src/client/clui/Makefile create mode 100644 src/client/clui/client.cpp create mode 100644 src/client/clui/clui.cpp create mode 100644 src/client/clui/clui.hpp create mode 100644 src/client/clui/user.cpp create mode 100644 src/client/clui/user.hpp create mode 100644 src/client/gui/Makefile create mode 100755 src/client/gui/client create mode 100644 src/client/gui/client.cpp delete mode 100644 src/client_clui/Makefile delete mode 100644 src/client_clui/client.cpp delete mode 100644 src/client_clui/clui.cpp delete mode 100644 src/client_clui/clui.hpp delete mode 100644 src/client_clui/user.cpp delete mode 100644 src/client_clui/user.hpp diff --git a/src/client/clui/Makefile b/src/client/clui/Makefile new file mode 100644 index 0000000..071462b --- /dev/null +++ b/src/client/clui/Makefile @@ -0,0 +1,18 @@ +CPP = g++ +CPPFLAGS = -Wall -g -lncurses +SOURCES = client.cpp clui.cpp user.cpp +OBJECTS = $(SOURCES:.cpp=.o) +EXECUTABLE = client + +.PHONY: all clean + +all: $(EXECUTABLE) + +clean: + rm -rf $(OBJECTS) $(EXECUTABLE) + +$(EXECUTABLE): $(OBJECTS) + $(CPP) $(CPPFLAGS) -o $(EXECUTABLE) $(OBJECTS) + +$(OBJECTS): + $(CPP) -c $(CPPFLAGS) $(SOURCES) \ No newline at end of file diff --git a/src/client/clui/client.cpp b/src/client/clui/client.cpp new file mode 100644 index 0000000..83f8ef0 --- /dev/null +++ b/src/client/clui/client.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +#include "../config.hpp" +#include "user.hpp" + +int main(int argc, char *argv[]) +{ + initscr(); + noecho(); + + int rows, columns; + getmaxyx(stdscr, rows, columns); + if(rows != 24 || columns != 80) { + endwin(); + printf("Please use terminal with size 24x80\n"); + return 1; + } + + Client *user = Client::Start(SERVER_IP, SERVER_PORT); + if(!user) { + endwin(); + perror("server"); + return 1; + } + + ChatRoom *room = new ChatRoom(); + user->Run(room); + delete room; + + endwin(); + return 0; +} \ No newline at end of file diff --git a/src/client/clui/clui.cpp b/src/client/clui/clui.cpp new file mode 100644 index 0000000..78fd226 --- /dev/null +++ b/src/client/clui/clui.cpp @@ -0,0 +1,187 @@ +#include +#include + +#include "clui.hpp" + +#define CHAT_HEIGHT 20 +#define CHAT_WIDTH 59 +#define PLAYERS_WIDTH 20 +#define PLAYERS_HEIGHT 20 +#define INPUT_HEIGHT 4 +#define INPUT_WIDTH 80 + +Interface_wc::Interface_wc(int num_y, int num_x, int by, + int bx, char ch) : ny(num_y), nx(num_x), beg_y(by), + beg_x(bx), ch_line(ch) +{ + w = newwin(ny, nx, beg_y, beg_x); + box(w, ch_line, ch_line); + this->Update(); +} + +void Interface_wc::Hide() +{ + this->Clear(true); + this->Update(); + this->Delete(); +} + +void Interface_wc::Clear(bool full) +{ + werase(this->GetWindow()); + if(!full) + box(this->GetWindow(), ch_line, ch_line); +} + +//////////////////////////////////////////////////////////////////////// + +ChatRoom::ChatRoom() : first(0) +{ + chat = new Interface_wc(CHAT_HEIGHT, CHAT_WIDTH, 0, 0, 0); + players = new Interface_wc(PLAYERS_HEIGHT, PLAYERS_WIDTH, 0, 60, 0); + input = new Interface_wc(INPUT_HEIGHT, INPUT_WIDTH, 20, 0, 0); + nodelay(input->GetWindow(), true); + keypad(input->GetWindow(), true); + i_nx = 1; + i_ny = 1; +} + +ChatRoom::~ChatRoom() +{ + if(chat) + delete chat; + if(players) + delete players; + if(input) + delete input; + + // #TODO: + /* if(first) ... delete message */ +} + +void ChatRoom::AddMessage(char *msg, int type) +{ + message *recent_msg = new message; + + int lines = 1; + int len = strlen(msg); + if(len > CHAT_WIDTH-2 + CHAT_WIDTH-2) lines = 3; + else if(len > CHAT_WIDTH-2) lines = 2; + + strcpy(recent_msg->msg, msg); + recent_msg->num_lines = lines; + recent_msg->type = type; + + recent_msg->prev = first; + first = recent_msg; + + ChatRedraw(); +} + +void ChatRoom::ChatRedraw() +{ + if(!first) + return; + + chat->Clear(false); + int available_lines = CHAT_HEIGHT - 2; + bool remove = false; + message *tmp; + + message *last; + for(message *m = first; m; m = m->prev) { + if(available_lines-1 >= m->num_lines) { + PrintMessage(available_lines, m); + available_lines -= m->num_lines; + last = m; + } + else { + tmp = m; + remove = true; + break; + } + } + + if(remove) { + last->prev = 0; + while(tmp) { + message *m = tmp; + tmp = tmp->prev; + delete m; + } + } + + SetInputCursor(i_ny, i_nx); + chat->Update(); +} + +void ChatRoom::PrintMessage(int line, message *m) +{ + WINDOW *win = this->chat->GetWindow(); + int need_print = m->num_lines; + int maxlen_oneline = CHAT_WIDTH-2; + + while(need_print != 0) { + if(m->type == system_msg) wattron(win, A_ITALIC); + else wattron(win, A_BOLD); + + wmove(win, line-need_print+1, 1); + + char *tmp = new char[maxlen_oneline]; + int str = maxlen_oneline * (m->num_lines - need_print); + memcpy(tmp, m->msg + str, maxlen_oneline); + + wprintw(win, tmp); + need_print--; + + if(m->type == system_msg) wattroff(win, A_ITALIC); + else wattroff(win, A_BOLD); + + delete[] tmp; + } +} + +bool ChatRoom::AddCharToSendMsg(char ch) +{ + if(i_ny == 2 && i_nx == max_usermsg_len/2-1) + return 0; + + mvwaddch(input->GetWindow(), i_ny, i_nx, ch); + i_nx++; + if(i_nx >= max_usermsg_len/2-1) { + if(i_ny == 1) { + i_ny++; + i_nx = 1; + } + else if(i_ny == 2) + i_nx--; + wmove(input->GetWindow(), i_ny, i_nx); + } + + input->Update(); + return 1; +} + +bool ChatRoom::RemoveCharFromMsg() +{ + if(i_ny == 1 && i_nx == 1) + return 0; + + i_nx--; + if(i_nx < 1) { + i_ny--; + i_nx = max_usermsg_len/2-1; + } + mvwaddch(input->GetWindow(), i_ny, i_nx, ' '); + wmove(input->GetWindow(), i_ny, i_nx); + + input->Update(); + return 1; +} + +void ChatRoom::SetInputCursor(int y, int x) +{ + input->SetCursor(y, x); + i_ny = y; + i_nx = x; +} \ No newline at end of file diff --git a/src/client/clui/clui.hpp b/src/client/clui/clui.hpp new file mode 100644 index 0000000..0373f95 --- /dev/null +++ b/src/client/clui/clui.hpp @@ -0,0 +1,61 @@ +// CLUI - Command Line User Interface + +#ifndef COMMANDLINEUI_H +#define COMMANDLINEUI_H + +#include +#include "../const_vars.hpp" + +class Interface_wc { + WINDOW *w; + int ny, nx; + int beg_y, beg_x; + int ch_line; +public: + Interface_wc(int num_y, int num_x, int by, int bx, char ch); + + WINDOW *GetWindow() { return w; } + void SetCursor(int y, int x) { wmove(w, y, x); } + void Clear(bool full); + void Update() { wrefresh(w); } + void Delete() { delwin(w); } + + void Hide(); +}; + +class ChatRoom { + Interface_wc *chat; + Interface_wc *players; + Interface_wc *input; + int i_nx, i_ny; + + struct message { + char msg[max_msg_len]; + int num_lines; // number of lines + int type; + message *prev; + }; + message *first; +public: + ChatRoom(); + ~ChatRoom(); + + // for chat: + void AddMessage(char *msg, int type); + + // for players: + //void AddPlayer() + + // for input: + int InputGetch() { return wgetch(input->GetWindow()); } + bool AddCharToSendMsg(char ch); + bool RemoveCharFromMsg(); + void InputClear() { input->Clear(false); } + void SetInputCursor(int y, int x); +private: + // for chat: + void ChatRedraw(); + void PrintMessage(int line, message *m); +}; + +#endif \ No newline at end of file diff --git a/src/client/clui/user.cpp b/src/client/clui/user.cpp new file mode 100644 index 0000000..d075751 --- /dev/null +++ b/src/client/clui/user.cpp @@ -0,0 +1,153 @@ +#include +#include +#include // for sockaddr_in +#include // for iten_aton +#include // for bind, connect +#include // for bind, connect +#include +#include +#include + +#include "user.hpp" + +const int key_enter = 10; +const int key_escape = 27; +const int key_backspace = 127; + +Client *Client::Start(const char* ip, int port) +{ + int client; + client = socket(AF_INET, SOCK_STREAM, 0); + if(client == -1) return 0; + + // remove "port sticking" aka socket in TIME_WAIT + int opt = 1; + setsockopt(client, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + + /* call bind optional, the system chooses + the address automatically */ + + struct sockaddr_in server_adress; + server_adress.sin_family = AF_INET; + server_adress.sin_port = htons(port); + if(!inet_aton(ip, &(server_adress.sin_addr))) return 0; + + int res = connect(client, (struct sockaddr*) &server_adress, + sizeof(server_adress)); + if(res == -1) return 0; + + return new Client(client); +} + +void Client::Run(ChatRoom *room) +{ + unsigned int usecs = 0100000; + int flags = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + + int cls = false; + do { + this->HandleButton(room); + + int recive = read(fd, out_buffer+out_buf_used, + sizeof(out_buffer)-out_buf_used); + + if(recive < 0) { + if(errno != EINTR && errno != EAGAIN) + break; + } + else if(recive > 0) + out_buf_used += recive; + else { + if(!cls) { + strcpy(out_buffer, "Server closed the connection. Use ESC to exit."); + room->AddMessage(out_buffer, system_msg); + cls = true; + } + } + + if(out_buf_used > 0) { + /* warning: if we get a (message without '\n') > max_msg_len then + this code will not work */ + for(int i = 0; i < out_buf_used; i++) { + if(out_buffer[i] == '\n') { + out_buffer[i] = 0; + + // in first char have may spec-symbol, check it: + int spec_msg = usual_msg; + char *buf = out_buffer; + if(out_buffer[0] == system_char) { + spec_msg = system_msg; + buf += 1; + } + + room->AddMessage(buf, spec_msg); + memmove(out_buffer, out_buffer + i + 1, out_buf_used - i - 1); + out_buf_used -= i + 1; + break; + } + } + } + + usleep(usecs); + } while (!exit_flag); +} + +void Client::HandleButton(ChatRoom *room) +{ + int key = room->InputGetch(); + switch(key) + { + case key_escape: { + this->BreakLoop(); + break; + } + case ' '...'~': { // ascii table 32...126 + AddCharToBuffer(key); + room->AddCharToSendMsg(key); + break; + } + case '\n': { // send message + SendMessage(); + room->InputClear(); + room->SetInputCursor(1, 1); + break; + } + case key_backspace: { + RemoveCharFromBuffer(); + room->RemoveCharFromMsg(); + break; + } + default: break; + } +} + +void Client::AddCharToBuffer(char ch) +{ + if(in_buf_used >= max_usermsg_len-1) + return; + + in_buffer[in_buf_used] = ch; + in_buf_used++; +} + +void Client::RemoveCharFromBuffer() +{ + if(in_buf_used <= 0) + return; + + in_buffer[in_buf_used] = '\0'; + in_buf_used--; +} + +void Client::SendMessage() +{ + if(in_buf_used <= 0) + return; + + in_buffer[in_buf_used] = '\n'; + + write(fd, in_buffer, (in_buf_used+1)*sizeof(char)); + memset(in_buffer, 0, (in_buf_used+1)*sizeof(char)); + in_buf_used = 0; +} \ No newline at end of file diff --git a/src/client/clui/user.hpp b/src/client/clui/user.hpp new file mode 100644 index 0000000..a203320 --- /dev/null +++ b/src/client/clui/user.hpp @@ -0,0 +1,32 @@ +#ifndef USER_H +#define USER_H + +#include "clui.hpp" +#include "../const_vars.hpp" + +class Client { + int fd; + char in_buffer[max_usermsg_len]; // for input + int in_buf_used; + + char out_buffer[max_msg_len]; // for message + int out_buf_used; + + bool exit_flag; + + Client(int i_fd) : fd(i_fd), in_buf_used(0), + out_buf_used(0), exit_flag(false) {} +public: + ~Client() { close(fd); } + + static Client *Start(const char* ip, int port); + void Run(ChatRoom *room); + void BreakLoop() { exit_flag = true; } + void HandleButton(ChatRoom *room); + + void AddCharToBuffer(char ch); + void RemoveCharFromBuffer(); + void SendMessage(); +}; + +#endif \ No newline at end of file diff --git a/src/client/gui/Makefile b/src/client/gui/Makefile new file mode 100644 index 0000000..2bc0969 --- /dev/null +++ b/src/client/gui/Makefile @@ -0,0 +1,18 @@ +CPP = g++ +CPPFLAGS = -Wall -g -lfltk +SOURCES = client.cpp +OBJECTS = $(SOURCES:.cpp=.o) +EXECUTABLE = client + +.PHONY: all clean + +all: $(EXECUTABLE) + +clean: + rm -rf $(OBJECTS) $(EXECUTABLE) + +$(EXECUTABLE): $(OBJECTS) + $(CPP) $(CPPFLAGS) -o $(EXECUTABLE) $(OBJECTS) + +$(OBJECTS): + $(CPP) -c $(CPPFLAGS) $(SOURCES) \ No newline at end of file diff --git a/src/client/gui/client b/src/client/gui/client new file mode 100755 index 0000000..778511e Binary files /dev/null and b/src/client/gui/client differ diff --git a/src/client/gui/client.cpp b/src/client/gui/client.cpp new file mode 100644 index 0000000..42407aa --- /dev/null +++ b/src/client/gui/client.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include + +const int spacing = 20; +const int border = 2; + +const int chat_w = 695; +const int chat_h = 440; +const int player_w = 225; +const int player_h = chat_h; +const int input_w = chat_w + border + spacing + border + player_w; +const int input_h = 55; + +const int win_w = spacing + border + (input_w) + border + spacing; +const int win_h = spacing + border + chat_h + border + + spacing + border + input_h + border + spacing; + +int main(int argc, char **argv) +{ + Fl_Window *win = new Fl_Window(win_w, win_h, "WantChat"); + win->color(FL_BLACK); + + // + + Fl_Box *outline_chat = new Fl_Box( + spacing, spacing, chat_w+border*2, chat_h+border*2); + outline_chat->box(FL_FLAT_BOX); + outline_chat->color(FL_WHITE); + + + Fl_Multiline_Output *box_chat = new Fl_Multiline_Output( + spacing+border, spacing+border, chat_w, chat_h); + box_chat->box(FL_FLAT_BOX); + box_chat->color(FL_BLACK); + + box_chat->textfont(FL_COURIER); + box_chat->textsize(20); + box_chat->textcolor(FL_WHITE); + + // only for test, please not going to beat me :) + char buffer[2048] = ""; + for(int i = 0; i < 18; i++) + { + sprintf(buffer, "%sNickname: some text some text some text some text some te\n", buffer); + } + box_chat->value(buffer); + + // + + int start_players_x = spacing + border + chat_w + border + spacing; + Fl_Box *outline_players = new Fl_Box( + start_players_x, spacing, player_w+border*2, player_h+border*2); + outline_players->box(FL_FLAT_BOX); + outline_players->color(FL_WHITE); + + + Fl_Multiline_Output *box_players = new Fl_Multiline_Output( + start_players_x + border, spacing+border, player_w, player_h); + box_players->box(FL_FLAT_BOX); + box_players->color(FL_BLACK); + + box_players->textfont(FL_COURIER); + box_players->textsize(20); + box_players->textcolor(FL_WHITE); + + // only for test, please not going to beat me :) (x2) + char buffer1[1024] = ""; + for(int i = 0; i < 18; i++) + { + sprintf(buffer1, "%sHackerspronickname\n", buffer1); + } + box_players->value(buffer1); + + // + + int start_input_y = spacing + border + chat_h + border + spacing; + Fl_Box *outline_input = new Fl_Box( + spacing, start_input_y, input_w+border*2, input_h+border*2); + outline_input->box(FL_FLAT_BOX); + outline_input->color(FL_WHITE); + + + Fl_Multiline_Input *box_input = new Fl_Multiline_Input(spacing+border, + start_input_y+border, input_w, input_h); + + box_input->box(FL_FLAT_BOX); + box_input->color(FL_BLACK); + + box_input->cursor_color(FL_WHITE); + box_input->textfont(FL_COURIER); + box_input->textsize(20); + box_input->textcolor(FL_WHITE); + + // + + win->end(); + win->show(); + return Fl::run(); +} + +// 59 - 1 - 20 + +/* I need this widgets: +- Button +- Inputbox +- Box */ \ No newline at end of file diff --git a/src/client_clui/Makefile b/src/client_clui/Makefile deleted file mode 100644 index 071462b..0000000 --- a/src/client_clui/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -CPP = g++ -CPPFLAGS = -Wall -g -lncurses -SOURCES = client.cpp clui.cpp user.cpp -OBJECTS = $(SOURCES:.cpp=.o) -EXECUTABLE = client - -.PHONY: all clean - -all: $(EXECUTABLE) - -clean: - rm -rf $(OBJECTS) $(EXECUTABLE) - -$(EXECUTABLE): $(OBJECTS) - $(CPP) $(CPPFLAGS) -o $(EXECUTABLE) $(OBJECTS) - -$(OBJECTS): - $(CPP) -c $(CPPFLAGS) $(SOURCES) \ No newline at end of file diff --git a/src/client_clui/client.cpp b/src/client_clui/client.cpp deleted file mode 100644 index 83f8ef0..0000000 --- a/src/client_clui/client.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include -#include - -#include "../config.hpp" -#include "user.hpp" - -int main(int argc, char *argv[]) -{ - initscr(); - noecho(); - - int rows, columns; - getmaxyx(stdscr, rows, columns); - if(rows != 24 || columns != 80) { - endwin(); - printf("Please use terminal with size 24x80\n"); - return 1; - } - - Client *user = Client::Start(SERVER_IP, SERVER_PORT); - if(!user) { - endwin(); - perror("server"); - return 1; - } - - ChatRoom *room = new ChatRoom(); - user->Run(room); - delete room; - - endwin(); - return 0; -} \ No newline at end of file diff --git a/src/client_clui/clui.cpp b/src/client_clui/clui.cpp deleted file mode 100644 index 78fd226..0000000 --- a/src/client_clui/clui.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include -#include - -#include "clui.hpp" - -#define CHAT_HEIGHT 20 -#define CHAT_WIDTH 59 -#define PLAYERS_WIDTH 20 -#define PLAYERS_HEIGHT 20 -#define INPUT_HEIGHT 4 -#define INPUT_WIDTH 80 - -Interface_wc::Interface_wc(int num_y, int num_x, int by, - int bx, char ch) : ny(num_y), nx(num_x), beg_y(by), - beg_x(bx), ch_line(ch) -{ - w = newwin(ny, nx, beg_y, beg_x); - box(w, ch_line, ch_line); - this->Update(); -} - -void Interface_wc::Hide() -{ - this->Clear(true); - this->Update(); - this->Delete(); -} - -void Interface_wc::Clear(bool full) -{ - werase(this->GetWindow()); - if(!full) - box(this->GetWindow(), ch_line, ch_line); -} - -//////////////////////////////////////////////////////////////////////// - -ChatRoom::ChatRoom() : first(0) -{ - chat = new Interface_wc(CHAT_HEIGHT, CHAT_WIDTH, 0, 0, 0); - players = new Interface_wc(PLAYERS_HEIGHT, PLAYERS_WIDTH, 0, 60, 0); - input = new Interface_wc(INPUT_HEIGHT, INPUT_WIDTH, 20, 0, 0); - nodelay(input->GetWindow(), true); - keypad(input->GetWindow(), true); - i_nx = 1; - i_ny = 1; -} - -ChatRoom::~ChatRoom() -{ - if(chat) - delete chat; - if(players) - delete players; - if(input) - delete input; - - // #TODO: - /* if(first) ... delete message */ -} - -void ChatRoom::AddMessage(char *msg, int type) -{ - message *recent_msg = new message; - - int lines = 1; - int len = strlen(msg); - if(len > CHAT_WIDTH-2 + CHAT_WIDTH-2) lines = 3; - else if(len > CHAT_WIDTH-2) lines = 2; - - strcpy(recent_msg->msg, msg); - recent_msg->num_lines = lines; - recent_msg->type = type; - - recent_msg->prev = first; - first = recent_msg; - - ChatRedraw(); -} - -void ChatRoom::ChatRedraw() -{ - if(!first) - return; - - chat->Clear(false); - int available_lines = CHAT_HEIGHT - 2; - bool remove = false; - message *tmp; - - message *last; - for(message *m = first; m; m = m->prev) { - if(available_lines-1 >= m->num_lines) { - PrintMessage(available_lines, m); - available_lines -= m->num_lines; - last = m; - } - else { - tmp = m; - remove = true; - break; - } - } - - if(remove) { - last->prev = 0; - while(tmp) { - message *m = tmp; - tmp = tmp->prev; - delete m; - } - } - - SetInputCursor(i_ny, i_nx); - chat->Update(); -} - -void ChatRoom::PrintMessage(int line, message *m) -{ - WINDOW *win = this->chat->GetWindow(); - int need_print = m->num_lines; - int maxlen_oneline = CHAT_WIDTH-2; - - while(need_print != 0) { - if(m->type == system_msg) wattron(win, A_ITALIC); - else wattron(win, A_BOLD); - - wmove(win, line-need_print+1, 1); - - char *tmp = new char[maxlen_oneline]; - int str = maxlen_oneline * (m->num_lines - need_print); - memcpy(tmp, m->msg + str, maxlen_oneline); - - wprintw(win, tmp); - need_print--; - - if(m->type == system_msg) wattroff(win, A_ITALIC); - else wattroff(win, A_BOLD); - - delete[] tmp; - } -} - -bool ChatRoom::AddCharToSendMsg(char ch) -{ - if(i_ny == 2 && i_nx == max_usermsg_len/2-1) - return 0; - - mvwaddch(input->GetWindow(), i_ny, i_nx, ch); - i_nx++; - if(i_nx >= max_usermsg_len/2-1) { - if(i_ny == 1) { - i_ny++; - i_nx = 1; - } - else if(i_ny == 2) - i_nx--; - wmove(input->GetWindow(), i_ny, i_nx); - } - - input->Update(); - return 1; -} - -bool ChatRoom::RemoveCharFromMsg() -{ - if(i_ny == 1 && i_nx == 1) - return 0; - - i_nx--; - if(i_nx < 1) { - i_ny--; - i_nx = max_usermsg_len/2-1; - } - mvwaddch(input->GetWindow(), i_ny, i_nx, ' '); - wmove(input->GetWindow(), i_ny, i_nx); - - input->Update(); - return 1; -} - -void ChatRoom::SetInputCursor(int y, int x) -{ - input->SetCursor(y, x); - i_ny = y; - i_nx = x; -} \ No newline at end of file diff --git a/src/client_clui/clui.hpp b/src/client_clui/clui.hpp deleted file mode 100644 index 0373f95..0000000 --- a/src/client_clui/clui.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// CLUI - Command Line User Interface - -#ifndef COMMANDLINEUI_H -#define COMMANDLINEUI_H - -#include -#include "../const_vars.hpp" - -class Interface_wc { - WINDOW *w; - int ny, nx; - int beg_y, beg_x; - int ch_line; -public: - Interface_wc(int num_y, int num_x, int by, int bx, char ch); - - WINDOW *GetWindow() { return w; } - void SetCursor(int y, int x) { wmove(w, y, x); } - void Clear(bool full); - void Update() { wrefresh(w); } - void Delete() { delwin(w); } - - void Hide(); -}; - -class ChatRoom { - Interface_wc *chat; - Interface_wc *players; - Interface_wc *input; - int i_nx, i_ny; - - struct message { - char msg[max_msg_len]; - int num_lines; // number of lines - int type; - message *prev; - }; - message *first; -public: - ChatRoom(); - ~ChatRoom(); - - // for chat: - void AddMessage(char *msg, int type); - - // for players: - //void AddPlayer() - - // for input: - int InputGetch() { return wgetch(input->GetWindow()); } - bool AddCharToSendMsg(char ch); - bool RemoveCharFromMsg(); - void InputClear() { input->Clear(false); } - void SetInputCursor(int y, int x); -private: - // for chat: - void ChatRedraw(); - void PrintMessage(int line, message *m); -}; - -#endif \ No newline at end of file diff --git a/src/client_clui/user.cpp b/src/client_clui/user.cpp deleted file mode 100644 index d075751..0000000 --- a/src/client_clui/user.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include -#include -#include // for sockaddr_in -#include // for iten_aton -#include // for bind, connect -#include // for bind, connect -#include -#include -#include - -#include "user.hpp" - -const int key_enter = 10; -const int key_escape = 27; -const int key_backspace = 127; - -Client *Client::Start(const char* ip, int port) -{ - int client; - client = socket(AF_INET, SOCK_STREAM, 0); - if(client == -1) return 0; - - // remove "port sticking" aka socket in TIME_WAIT - int opt = 1; - setsockopt(client, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - - /* call bind optional, the system chooses - the address automatically */ - - struct sockaddr_in server_adress; - server_adress.sin_family = AF_INET; - server_adress.sin_port = htons(port); - if(!inet_aton(ip, &(server_adress.sin_addr))) return 0; - - int res = connect(client, (struct sockaddr*) &server_adress, - sizeof(server_adress)); - if(res == -1) return 0; - - return new Client(client); -} - -void Client::Run(ChatRoom *room) -{ - unsigned int usecs = 0100000; - int flags = fcntl(fd, F_GETFL, 0); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - - int cls = false; - do { - this->HandleButton(room); - - int recive = read(fd, out_buffer+out_buf_used, - sizeof(out_buffer)-out_buf_used); - - if(recive < 0) { - if(errno != EINTR && errno != EAGAIN) - break; - } - else if(recive > 0) - out_buf_used += recive; - else { - if(!cls) { - strcpy(out_buffer, "Server closed the connection. Use ESC to exit."); - room->AddMessage(out_buffer, system_msg); - cls = true; - } - } - - if(out_buf_used > 0) { - /* warning: if we get a (message without '\n') > max_msg_len then - this code will not work */ - for(int i = 0; i < out_buf_used; i++) { - if(out_buffer[i] == '\n') { - out_buffer[i] = 0; - - // in first char have may spec-symbol, check it: - int spec_msg = usual_msg; - char *buf = out_buffer; - if(out_buffer[0] == system_char) { - spec_msg = system_msg; - buf += 1; - } - - room->AddMessage(buf, spec_msg); - memmove(out_buffer, out_buffer + i + 1, out_buf_used - i - 1); - out_buf_used -= i + 1; - break; - } - } - } - - usleep(usecs); - } while (!exit_flag); -} - -void Client::HandleButton(ChatRoom *room) -{ - int key = room->InputGetch(); - switch(key) - { - case key_escape: { - this->BreakLoop(); - break; - } - case ' '...'~': { // ascii table 32...126 - AddCharToBuffer(key); - room->AddCharToSendMsg(key); - break; - } - case '\n': { // send message - SendMessage(); - room->InputClear(); - room->SetInputCursor(1, 1); - break; - } - case key_backspace: { - RemoveCharFromBuffer(); - room->RemoveCharFromMsg(); - break; - } - default: break; - } -} - -void Client::AddCharToBuffer(char ch) -{ - if(in_buf_used >= max_usermsg_len-1) - return; - - in_buffer[in_buf_used] = ch; - in_buf_used++; -} - -void Client::RemoveCharFromBuffer() -{ - if(in_buf_used <= 0) - return; - - in_buffer[in_buf_used] = '\0'; - in_buf_used--; -} - -void Client::SendMessage() -{ - if(in_buf_used <= 0) - return; - - in_buffer[in_buf_used] = '\n'; - - write(fd, in_buffer, (in_buf_used+1)*sizeof(char)); - memset(in_buffer, 0, (in_buf_used+1)*sizeof(char)); - in_buf_used = 0; -} \ No newline at end of file diff --git a/src/client_clui/user.hpp b/src/client_clui/user.hpp deleted file mode 100644 index a203320..0000000 --- a/src/client_clui/user.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef USER_H -#define USER_H - -#include "clui.hpp" -#include "../const_vars.hpp" - -class Client { - int fd; - char in_buffer[max_usermsg_len]; // for input - int in_buf_used; - - char out_buffer[max_msg_len]; // for message - int out_buf_used; - - bool exit_flag; - - Client(int i_fd) : fd(i_fd), in_buf_used(0), - out_buf_used(0), exit_flag(false) {} -public: - ~Client() { close(fd); } - - static Client *Start(const char* ip, int port); - void Run(ChatRoom *room); - void BreakLoop() { exit_flag = true; } - void HandleButton(ChatRoom *room); - - void AddCharToBuffer(char ch); - void RemoveCharFromBuffer(); - void SendMessage(); -}; - -#endif \ No newline at end of file -- cgit v1.2.3-18-g5258