summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoursoir <chat@joursoir.net>2020-11-22 18:46:56 +0300
committerJoursoir <chat@joursoir.net>2020-11-22 18:46:56 +0300
commita2ee75888739b66b3bd20d2a1f1e465947f1fbc4 (patch)
tree2e6591b2406227c06e3d1bb8a06b798b108260e9
parent3db205de39289ee249cd4587ede88249963201f7 (diff)
downloadwant-chat-a2ee75888739b66b3bd20d2a1f1e465947f1fbc4.tar.gz
want-chat-a2ee75888739b66b3bd20d2a1f1e465947f1fbc4.tar.bz2
want-chat-a2ee75888739b66b3bd20d2a1f1e465947f1fbc4.zip
add chat move, fix some bugs
-rw-r--r--src/client/clui.cpp141
-rw-r--r--src/client/clui.hpp21
-rw-r--r--src/client/user.cpp86
-rw-r--r--src/client/user.hpp13
4 files changed, 175 insertions, 86 deletions
diff --git a/src/client/clui.cpp b/src/client/clui.cpp
index 4ae6a5a..e0b528b 100644
--- a/src/client/clui.cpp
+++ b/src/client/clui.cpp
@@ -1,33 +1,42 @@
#include <string.h>
#include <ncurses.h>
+#include <unistd.h>
#include "clui.hpp"
-#define CHAT_WIDTH 20
-#define CHAT_HEIGHT 59
+#define CHAT_HEIGHT 20
+#define CHAT_WIDTH 59
#define PLAYERS_WIDTH 20
#define PLAYERS_HEIGHT 20
-#define INPUT_WIDTH 4
-#define INPUT_HEIGHT 80
+#define INPUT_HEIGHT 4
+#define INPUT_WIDTH 80
-#define MAXLEN_MSG 158
+const int maxlen_msg_input = (INPUT_WIDTH - 2) * 2;
+const int maxlen_msg_chat = (CHAT_WIDTH - 4) * 2;
Interface_wc::Interface_wc(int num_y, int num_x, int by,
- int bx, char ch)
+ int bx, char ch) : ny(num_y), nx(num_x), beg_y(by),
+ beg_x(bx), ch_line(ch)
{
- w = newwin(num_y, num_x, by, bx);
- box(w, ch, ch);
+ w = newwin(ny, nx, beg_y, beg_x);
+ box(w, ch_line, ch_line);
this->Update();
}
void Interface_wc::Hide()
{
- werase(this->GetWindow()); // clear
-
+ 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);
+}
+
////////////////////////////////////////////////////////////////////////
SelectionMenu::SelectionMenu(char const *i_title, const char**i_choises, int choises_num,
@@ -71,27 +80,13 @@ int SelectionMenu::Handling()
////////////////////////////////////////////////////////////////////////
-ChatRoom::ChatRoom()
+ChatRoom::ChatRoom() : first(0)
{
- chat = new Interface_wc(CHAT_WIDTH, CHAT_HEIGHT, 0, 0, 0);
- players = new Interface_wc(PLAYERS_WIDTH, PLAYERS_HEIGHT, 0, 60, 0);
- input = new Interface_wc(INPUT_WIDTH, INPUT_HEIGHT, 20, 0, 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);
i_nx = 1;
i_ny = 1;
-
- /* WINDOW *newwin(int nlines, int ncols, int begin_y, int begin_x) */
- /*WINDOW *chat = newwin(20, 59, 0, 0);
- box(chat, 0, 0);
- wrefresh(chat);
-
- WINDOW *players = newwin(20, 20, 0, 60);
- box(players, 0, 0);
- wrefresh(players);
-
- WINDOW *input = newwin(4, 80, 20, 0);
- box(input, 0, 0);
- wmove(input, 1, 1);
- wrefresh(input);*/
}
ChatRoom::~ChatRoom()
@@ -102,27 +97,92 @@ ChatRoom::~ChatRoom()
delete players;
if(input)
delete input;
+
+ // #TODO:
+ /* if(first) ... delete message */
}
-void ChatRoom::PrintMessage(const char *msg)
+void ChatRoom::AddMessage(char *msg)
{
- // если msg <= **, то одна строка
- // иначе 2 строки
- WINDOW *win = chat->GetWindow();
- wmove(win, 1, 2);
- wprintw(win, msg);
+ message *recent_msg = new message;
+
+ int lines = 1;
+ if(strlen(msg) > maxlen_msg_chat/2)
+ lines = 2;
+
+ strcpy(recent_msg->msg, msg);
+ recent_msg->num_lines = lines;
+
+ recent_msg->prev = first;
+ first = recent_msg;
+
+ ChatRedraw();
+}
+
+void ChatRoom::ChatRedraw()
+{
+ if(!first)
+ return;
+
+ /*wprintw(chat->GetWindow(), "redraw");
+ chat->Update();
+ sleep(3);*/
+
+ chat->Clear(false);
+ int available_lines = CHAT_HEIGHT - 2;
+ bool remove = 0;
+ message *tmp;
+
+ for(tmp = first; tmp; tmp = tmp->prev) {
+ if(available_lines >= tmp->num_lines) {
+ PrintMessage(available_lines, tmp);
+ available_lines -= tmp->num_lines;
+ }
+ // #TODO:
+ /* delete */
+
+ }
chat->Update();
}
+void ChatRoom::PrintMessage(int line, message *m)
+{
+ WINDOW *win = this->GetChatWin();
+ if(m->num_lines == 1) {
+ wmove(win, line, 2);
+ wprintw(win, m->msg);
+ }
+ else {
+ wmove(win, line-1, 2);
+ // print a half of message:
+ int len_fline = maxlen_msg_chat/2;
+
+
+ char *temp = new char[len_fline+1];
+ // memccpy(void *restrict s1, const void *restrict s2, int c, size_t n);
+ memcpy(temp, m->msg, sizeof(char) * len_fline);
+ temp[len_fline] = '\0';
+ wprintw(win, temp);
+
+ int last_len_msg = strlen(m->msg) - len_fline;
+ memcpy(temp, m->msg, sizeof(char) * (last_len_msg+1));
+ temp[last_len_msg] = '\0';
+ wmove(win, line, 2);
+ wprintw(win, temp);
+
+ delete[] temp;
+ }
+}
+
bool ChatRoom::AddCharToSendMsg(char ch)
{
- if(i_ny == 2 && i_nx == MAXLEN_MSG/2-1)
+ if(i_ny == 2 && i_nx == maxlen_msg_input/2-1)
return 0;
mvwaddch(input->GetWindow(), i_ny, i_nx, ch);
i_nx++;
- if(i_nx >= MAXLEN_MSG/2) {
+ if(i_nx >= maxlen_msg_input/2-1) {
if(i_ny == 1) {
i_ny++;
i_nx = 1;
@@ -144,11 +204,18 @@ bool ChatRoom::RemoveCharFromMsg()
i_nx--;
if(i_nx < 1) {
i_ny--;
- i_nx = MAXLEN_MSG/2-1;
+ i_nx = maxlen_msg_input/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.hpp b/src/client/clui.hpp
index ff447ef..3ebefda 100644
--- a/src/client/clui.hpp
+++ b/src/client/clui.hpp
@@ -9,10 +9,13 @@ 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); }
@@ -37,12 +40,19 @@ class ChatRoom {
Interface_wc *players;
Interface_wc *input;
int i_nx, i_ny;
+
+ struct message {
+ char msg[300];
+ int num_lines; // number of lines
+ message *prev;
+ };
+ message *first;
public:
ChatRoom();
~ChatRoom();
// for chat:
- void PrintMessage(const char *msg);
+ void AddMessage(char *msg);
// for players:
//void AddPlayer()
@@ -50,8 +60,15 @@ public:
// for input:
bool AddCharToSendMsg(char ch);
bool RemoveCharFromMsg();
+ void InputClear() { input->Clear(false); }
+ void SetInputCursor(int y, int x);
- WINDOW *GetWin() { return input->GetWindow(); }
+ WINDOW *GetInputWin() { return input->GetWindow(); }
+ WINDOW *GetChatWin() { return chat->GetWindow(); }
+private:
+ // for chat:
+ void ChatRedraw();
+ void PrintMessage(int line, message *m);
};
#endif \ No newline at end of file
diff --git a/src/client/user.cpp b/src/client/user.cpp
index 1a60891..85b626e 100644
--- a/src/client/user.cpp
+++ b/src/client/user.cpp
@@ -41,82 +41,82 @@ Client *Client::Start(const char* ip, int port)
void Client::Run(ChatRoom *room)
{
- /*int fd_stdin = STDIN_FILENO;
- const int flags = fcntl(fd_stdin, F_GETFL, 0);
- fcntl(fd_stdin, F_SETFL, flags | O_NONBLOCK);*/
-
- const int flags = fcntl(fd, F_GETFL, 0);
+ unsigned int usecs = 0125000;
+ int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
- nodelay(room->GetWin(), true);
+ nodelay(room->GetInputWin(), true);
curs_set(true);
do {
this->HandleButton(room);
int recive = read(fd, out_buffer, sizeof(out_buffer));
+
if(recive < 0) {
- if(errno == EINTR || errno == EAGAIN) continue;
- else break;
+ if(errno != EINTR && errno != EAGAIN)
+ break;
}
else if(recive > 0) {
- room->PrintMessage(out_buffer);
+ room->AddMessage(out_buffer);
}
- unsigned int usecs = 0125000;
usleep(usecs);
-
- /*struct timeval timeout = { 0 };
- timeout.tv_usec = 5000000;
-
- fd_set rds, wrs;
- FD_ZERO(&rds);
- FD_ZERO(&wrs);
-
- FD_SET(fd, &rds);
-
- int val = read(fd_stdin, buffer, sizeof(buffer));
- if(val > 0) FD_SET(fd_stdin, &wrs);
-
- res = select(fd+1, &rds, &wrs, 0, &timeout);
- if(res < 0) {
- if(errno == EINTR) continue;
- else break;
- }
- else if(res > 0) {
- if(FD_ISSET(fd_stdin, &wrs)) // if client want to send any message
- {
- if(buffer[0] == '#') // exit
- exit_flag = true;
- else write(fd, buffer, strlen(buffer)*sizeof(char));
- }
- if(FD_ISSET(fd, &rds)) // if server want to send any message
- {
- read(fd, buffer, sizeof(buffer));
- //getchar();
- }
- }*/
} while (!exit_flag);
}
void Client::HandleButton(ChatRoom *room)
{
- int key = wgetch(room->GetWin());
+ int key = wgetch(room->GetInputWin());
switch(key)
{
// ascii table 32...126
case ' '...'~': {
+ AddCharToBuffer(key);
room->AddCharToSendMsg(key);
break;
}
case '\n': { // send message
- // some code
+ 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_line_length-2) // we reserve 1 byte for '\0'
+ 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';
+ // if(max_line_length-2 < 0)
+ write(fd, in_buffer, (in_buf_used+1)*sizeof(char));
+ memset(in_buffer, 0, sizeof(in_buffer));
+ in_buf_used = 0;
} \ No newline at end of file
diff --git a/src/client/user.hpp b/src/client/user.hpp
index a6e6c15..45fb5e3 100644
--- a/src/client/user.hpp
+++ b/src/client/user.hpp
@@ -8,14 +8,15 @@ const int max_line_length = 156;
class Client {
int fd;
char in_buffer[max_line_length]; // мы готовим к отправке
- char in_buf_used;
+ int in_buf_used;
+
char out_buffer[max_line_length]; // нам пришло
- char out_buf_used;
- bool ignoring;
+ int out_buf_used;
+
bool exit_flag;
Client(int i_fd)
- : fd(i_fd), in_buf_used(0), out_buf_used(0), ignoring(false) { }
+ : fd(i_fd), in_buf_used(0), out_buf_used(0) { }
public:
~Client() { close(fd); }
@@ -23,6 +24,10 @@ public:
void Run(ChatRoom *room);
void HandleButton(ChatRoom *room);
+ void AddCharToBuffer(char ch);
+ void RemoveCharFromBuffer();
+ void SendMessage();
+
int getFd() const { return fd; } // not used
};