mirror of
https://github.com/Tha14/toxic.git
synced 2024-11-22 21:13:02 +01:00
refactor chat history to allow scrolling
This commit is contained in:
parent
7384440a3d
commit
e5b6e0ad9f
@ -29,7 +29,9 @@ toxic_SOURCES = $(top_srcdir)/src/main.c \
|
|||||||
$(top_srcdir)/src/log.c \
|
$(top_srcdir)/src/log.c \
|
||||||
$(top_srcdir)/src/log.h \
|
$(top_srcdir)/src/log.h \
|
||||||
$(top_srcdir)/src/file_senders.c \
|
$(top_srcdir)/src/file_senders.c \
|
||||||
$(top_srcdir)/src/file_senders.h
|
$(top_srcdir)/src/file_senders.h \
|
||||||
|
$(top_srcdir)/src/line_info.c \
|
||||||
|
$(top_srcdir)/src/line_info.h
|
||||||
|
|
||||||
toxic_CFLAGS = -I$(top_srcdir) \
|
toxic_CFLAGS = -I$(top_srcdir) \
|
||||||
$(NCURSES_CFLAGS) \
|
$(NCURSES_CFLAGS) \
|
||||||
|
@ -252,7 +252,6 @@ void terminate_audio()
|
|||||||
toxav_kill(ASettins.av);
|
toxav_kill(ASettins.av);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int errors()
|
int errors()
|
||||||
{
|
{
|
||||||
return ASettins.errors;
|
return ASettins.errors;
|
||||||
|
243
src/chat.c
243
src/chat.c
@ -34,6 +34,7 @@
|
|||||||
#include "friendlist.h"
|
#include "friendlist.h"
|
||||||
#include "toxic_strings.h"
|
#include "toxic_strings.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "line_info.h"
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _SUPPORT_AUDIO
|
||||||
#include "audio_call.h"
|
#include "audio_call.h"
|
||||||
@ -98,6 +99,7 @@ void kill_chat_window(ToxWindow *self)
|
|||||||
StatusBar *statusbar = self->stb;
|
StatusBar *statusbar = self->stb;
|
||||||
|
|
||||||
log_disable(ctx->log);
|
log_disable(ctx->log);
|
||||||
|
line_info_cleanup(ctx->hst);
|
||||||
|
|
||||||
int f_num = self->num;
|
int f_num = self->num;
|
||||||
delwin(ctx->linewin);
|
delwin(ctx->linewin);
|
||||||
@ -106,6 +108,7 @@ void kill_chat_window(ToxWindow *self)
|
|||||||
disable_chatwin(f_num);
|
disable_chatwin(f_num);
|
||||||
|
|
||||||
free(ctx->log);
|
free(ctx->log);
|
||||||
|
free(ctx->hst);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
free(statusbar);
|
free(statusbar);
|
||||||
}
|
}
|
||||||
@ -121,17 +124,10 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, uint8_t *msg, u
|
|||||||
tox_get_name(m, num, nick);
|
tox_get_name(m, num, nick);
|
||||||
nick[TOXIC_MAX_NAME_LENGTH] = '\0';
|
nick[TOXIC_MAX_NAME_LENGTH] = '\0';
|
||||||
|
|
||||||
print_time(ctx->history);
|
uint8_t timefrmt[TIME_STR_SIZE];
|
||||||
wattron(ctx->history, COLOR_PAIR(CYAN));
|
get_time_str(timefrmt);
|
||||||
wprintw(ctx->history, "%s: ", nick);
|
|
||||||
wattroff(ctx->history, COLOR_PAIR(CYAN));
|
|
||||||
|
|
||||||
if (msg[0] == '>') {
|
line_info_add(self, timefrmt, nick, NULL, msg, IN_MSG, 0, 0);
|
||||||
wattron(ctx->history, COLOR_PAIR(GREEN));
|
|
||||||
wprintw(ctx->history, "%s\n", msg);
|
|
||||||
wattroff(ctx->history, COLOR_PAIR(GREEN));
|
|
||||||
} else
|
|
||||||
wprintw(ctx->history, "%s\n", msg);
|
|
||||||
|
|
||||||
write_to_log(msg, nick, ctx->log, false);
|
write_to_log(msg, nick, ctx->log, false);
|
||||||
alert_window(self, WINDOW_ALERT_1, true);
|
alert_window(self, WINDOW_ALERT_1, true);
|
||||||
@ -172,11 +168,10 @@ static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, uint8_t *action,
|
|||||||
tox_get_name(m, num, nick);
|
tox_get_name(m, num, nick);
|
||||||
nick[TOXIC_MAX_NAME_LENGTH] = '\0';
|
nick[TOXIC_MAX_NAME_LENGTH] = '\0';
|
||||||
|
|
||||||
print_time(ctx->history);
|
uint8_t timefrmt[TIME_STR_SIZE];
|
||||||
wattron(ctx->history, COLOR_PAIR(YELLOW));
|
get_time_str(timefrmt);
|
||||||
wprintw(ctx->history, "* %s %s\n", nick, action);
|
|
||||||
wattroff(ctx->history, COLOR_PAIR(YELLOW));
|
|
||||||
|
|
||||||
|
line_info_add(self, timefrmt, nick, NULL, action, ACTION, 0, 0);
|
||||||
write_to_log(action, nick, ctx->log, true);
|
write_to_log(action, nick, ctx->log, true);
|
||||||
alert_window(self, WINDOW_ALERT_1, true);
|
alert_window(self, WINDOW_ALERT_1, true);
|
||||||
}
|
}
|
||||||
@ -216,16 +211,19 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
|||||||
if (self->num != num)
|
if (self->num != num)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t msg[MAX_STR_SIZE];
|
||||||
|
uint8_t *errmsg;
|
||||||
|
|
||||||
uint8_t filename[MAX_STR_SIZE];
|
uint8_t filename[MAX_STR_SIZE];
|
||||||
get_file_name(pathname, filename);
|
get_file_name(pathname, filename);
|
||||||
|
|
||||||
wprintw(ctx->history, "File transfer request for '%s' (%llu bytes).\n", filename,
|
snprintf(msg, sizeof(msg), "File transfer request for '%s' (%llu bytes).", filename,
|
||||||
(long long unsigned int)filesize);
|
(long long unsigned int)filesize);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
|
|
||||||
if (filenum >= MAX_FILES) {
|
if (filenum >= MAX_FILES) {
|
||||||
wprintw(ctx->history, "Too many pending file requests; discarding.\n");
|
errmsg = "Too many pending file requests; discarding.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,12 +240,14 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
|||||||
filename[len + strlen(d)] = '\0';
|
filename[len + strlen(d)] = '\0';
|
||||||
|
|
||||||
if (count > 999) {
|
if (count > 999) {
|
||||||
wprintw(ctx->history, "Error saving file to disk.\n");
|
errmsg = "Error saving file to disk.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wprintw(ctx->history, "Type '/savefile %d' to accept the file transfer.\n", filenum);
|
snprintf(msg, sizeof(msg), "Type '/savefile %d' to accept the file transfer.", filenum);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
|
|
||||||
friends[num].file_receiver.pending[filenum] = true;
|
friends[num].file_receiver.pending[filenum] = true;
|
||||||
strcpy(friends[num].file_receiver.filenames[filenum], filename);
|
strcpy(friends[num].file_receiver.filenames[filenum], filename);
|
||||||
@ -270,8 +270,8 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
|
|||||||
if (self->num != num)
|
if (self->num != num)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
|
||||||
const uint8_t *filename;
|
const uint8_t *filename;
|
||||||
|
uint8_t msg[MAX_STR_SIZE] = {0};
|
||||||
|
|
||||||
if (receive_send == 0)
|
if (receive_send == 0)
|
||||||
filename = friends[num].file_receiver.filenames[filenum];
|
filename = friends[num].file_receiver.filenames[filenum];
|
||||||
@ -280,25 +280,23 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
|
|||||||
|
|
||||||
switch (control_type) {
|
switch (control_type) {
|
||||||
case TOX_FILECONTROL_ACCEPT:
|
case TOX_FILECONTROL_ACCEPT:
|
||||||
wprintw(ctx->history, "File transfer for '%s' accepted.\n", filename);
|
snprintf(msg, sizeof(msg), "File transfer for '%s' accepted.", filename);
|
||||||
break;
|
break;
|
||||||
/*case TOX_FILECONTROL_PAUSE:
|
/*case TOX_FILECONTROL_PAUSE:
|
||||||
wprintw(ctx->history, "File transfer for '%s' paused.\n", filename);
|
wprintw(ctx->history, "File transfer for '%s' paused.\n", filename);
|
||||||
break; */
|
break; */
|
||||||
case TOX_FILECONTROL_KILL:
|
case TOX_FILECONTROL_KILL:
|
||||||
wprintw(ctx->history, "File transfer for '%s' failed.\n", filename);
|
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename);
|
||||||
|
|
||||||
if (receive_send == 0)
|
if (receive_send == 0)
|
||||||
chat_close_file_receiver(num, filenum);
|
chat_close_file_receiver(num, filenum);
|
||||||
else
|
|
||||||
chat_close_file_receiver(num, filenum);
|
|
||||||
break;
|
break;
|
||||||
case TOX_FILECONTROL_FINISHED:
|
case TOX_FILECONTROL_FINISHED:
|
||||||
wprintw(ctx->history, "File transfer for '%s' complete.\n", filename);
|
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
|
||||||
chat_close_file_receiver(num, filenum);
|
chat_close_file_receiver(num, filenum);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
alert_window(self, WINDOW_ALERT_2, true);
|
alert_window(self, WINDOW_ALERT_2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,12 +306,9 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu
|
|||||||
if (self->num != num)
|
if (self->num != num)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
|
||||||
|
|
||||||
if (fwrite(data, length, 1, friends[num].file_receiver.files[filenum]) != 1) {
|
if (fwrite(data, length, 1, friends[num].file_receiver.files[filenum]) != 1) {
|
||||||
wattron(ctx->history, COLOR_PAIR(RED));
|
uint8_t *msg = " * Error writing to file.";
|
||||||
wprintw(ctx->history, "* Error writing to file.\n");
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
|
||||||
wattroff(ctx->history, COLOR_PAIR(RED));
|
|
||||||
|
|
||||||
tox_file_send_control(m, num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
|
tox_file_send_control(m, num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
|
||||||
chat_close_file_receiver(num, filenum);
|
chat_close_file_receiver(num, filenum);
|
||||||
@ -325,16 +320,17 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, ui
|
|||||||
if (self->num != friendnumber)
|
if (self->num != friendnumber)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t name[TOX_MAX_NAME_LENGTH];
|
||||||
uint8_t name[TOX_MAX_NAME_LENGTH] = {'\0'};
|
uint8_t msg[MAX_STR_SIZE];
|
||||||
|
|
||||||
if (tox_get_name(m, friendnumber, name) == -1)
|
if (tox_get_name(m, friendnumber, name) == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wprintw(ctx->history, "%s has invited you to a group chat.\n", name);
|
snprintf(msg, sizeof(msg), "%s has invited you to a group chat.\n"
|
||||||
|
"Type \"/join\" to join the chat.", name);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
|
|
||||||
memcpy(friends[friendnumber].pending_groupchat, group_pub_key, TOX_CLIENT_ID_SIZE);
|
memcpy(friends[friendnumber].pending_groupchat, group_pub_key, TOX_CLIENT_ID_SIZE);
|
||||||
wprintw(ctx->history, "Type \"/join\" to join the chat.\n");
|
|
||||||
alert_window(self, WINDOW_ALERT_2, true);
|
alert_window(self, WINDOW_ALERT_2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,144 +341,140 @@ void chat_onInvite (ToxWindow *self, ToxAv *av)
|
|||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg = "Incoming audio call!\nType: \"/answer\" or \"/cancel\"";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
wprintw(ctx->history, "Incoming audio call!\n"
|
|
||||||
"Answer: \"/answer\" \"/cancel\"\n");
|
|
||||||
|
|
||||||
alert_window(self, WINDOW_ALERT_0, true);
|
alert_window(self, WINDOW_ALERT_0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onRinging (ToxWindow *self, ToxAv *av)
|
void chat_onRinging (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg = "Ringing...\n\"/cancel\" ?";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
wprintw(ctx->history, "Ringing...\n"
|
|
||||||
"\"/cancel\" ?\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onStarting (ToxWindow *self, ToxAv *av)
|
void chat_onStarting (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg;
|
||||||
|
|
||||||
if ( 0 != start_transmission() ) {/* YEAH! */
|
if ( 0 != start_transmission() ) {/* YEAH! */
|
||||||
wprintw(ctx->history, "Error starting transmission!\n");
|
msg = "Error starting transmission!";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wprintw(ctx->history, "Call started! \n"
|
msg = "Call started!\nType: \"/hangup\" to end it.";
|
||||||
"Type: \"/hangup\" to end it.\n");
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onEnding (ToxWindow *self, ToxAv *av)
|
void chat_onEnding (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg = "Call ended!";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
|
|
||||||
toxav_kill_transmission(av);
|
toxav_kill_transmission(av);
|
||||||
|
|
||||||
wprintw(ctx->history, "Call ended! \n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onError (ToxWindow *self, ToxAv *av)
|
void chat_onError (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg = "Error!";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
wprintw(ctx->history, "Error! \n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onStart (ToxWindow *self, ToxAv *av)
|
void chat_onStart (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg;
|
||||||
|
|
||||||
if ( 0 != start_transmission() ) {/* YEAH! */
|
if ( 0 != start_transmission() ) {/* YEAH! */
|
||||||
wprintw(ctx->history, "Error starting transmission!\n");
|
msg = "Error starting transmission!";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wprintw(ctx->history, "Call started! \n"
|
msg = "Call started!\nType: \"/hangup\" to end it.";
|
||||||
"Type: \"/hangup\" to end it.\n");
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onCancel (ToxWindow *self, ToxAv *av)
|
void chat_onCancel (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg = "Call canceled!";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
wprintw(ctx->history, "Call canceled! \n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onReject (ToxWindow *self, ToxAv *av)
|
void chat_onReject (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg = "Rejected!";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
wprintw(ctx->history, "Rejected! \n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onEnd (ToxWindow *self, ToxAv *av)
|
void chat_onEnd (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
|
||||||
|
|
||||||
toxav_kill_transmission(av);
|
toxav_kill_transmission(av);
|
||||||
|
|
||||||
wprintw(ctx->history, "Call ended! \n");
|
uint8_t *msg = "Call ended!";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onRequestTimeout (ToxWindow *self, ToxAv *av)
|
void chat_onRequestTimeout (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg = "No answer!";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
wprintw(ctx->history, "No answer! \n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chat_onPeerTimeout (ToxWindow *self, ToxAv *av)
|
void chat_onPeerTimeout (ToxWindow *self, ToxAv *av)
|
||||||
{
|
{
|
||||||
if (self->num != toxav_get_peer_id(av, 0))
|
if (self->num != toxav_get_peer_id(av, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
uint8_t *msg = "Peer disconnected; call ended!";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
wprintw(ctx->history, "Peer disconnected; call ended! \n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _SUPPORT_AUDIO */
|
||||||
|
|
||||||
static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, uint8_t *action) {
|
static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, uint8_t *action) {
|
||||||
if (action == NULL) {
|
if (action == NULL)
|
||||||
wprintw(ctx->history, "Invalid syntax.\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t selfname[TOX_MAX_NAME_LENGTH];
|
uint8_t selfname[TOX_MAX_NAME_LENGTH];
|
||||||
tox_get_self_name(m, selfname);
|
tox_get_self_name(m, selfname);
|
||||||
|
|
||||||
print_time(ctx->history);
|
uint8_t timefrmt[TIME_STR_SIZE];
|
||||||
wattron(ctx->history, COLOR_PAIR(YELLOW));
|
get_time_str(timefrmt);
|
||||||
wprintw(ctx->history, "* %s %s\n", selfname, action);
|
|
||||||
wattroff(ctx->history, COLOR_PAIR(YELLOW));
|
line_info_add(self, timefrmt, selfname, NULL, action, ACTION, 0, 0);
|
||||||
|
|
||||||
if (tox_send_action(m, self->num, action, strlen(action) + 1) == 0) {
|
if (tox_send_action(m, self->num, action, strlen(action) + 1) == 0) {
|
||||||
wattron(ctx->history, COLOR_PAIR(RED));
|
uint8_t *errmsg = " * Failed to send action.";
|
||||||
wprintw(ctx->history, " * Failed to send action\n");
|
line_info_add(self, NULL, selfname, NULL, errmsg, SYS_MSG, 0, RED);
|
||||||
wattroff(ctx->history, COLOR_PAIR(RED));
|
|
||||||
} else {
|
} else {
|
||||||
write_to_log(action, selfname, ctx->log, true);
|
write_to_log(action, selfname, ctx->log, true);
|
||||||
}
|
}
|
||||||
@ -498,7 +490,18 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
|
|||||||
getmaxyx(self->window, y2, x2);
|
getmaxyx(self->window, y2, x2);
|
||||||
int cur_len = 0;
|
int cur_len = 0;
|
||||||
|
|
||||||
if (key == 0x107 || key == 0x8 || key == 0x7f) { /* BACKSPACE key: Remove character behind pos */
|
if (key == T_KEY_ESC) { /* ESC key: Toggle history scroll mode */
|
||||||
|
bool scroll = ctx->hst->scroll_mode ? false : true;
|
||||||
|
line_info_toggle_scroll(self, scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're in scroll mode ignore rest of function */
|
||||||
|
if (ctx->hst->scroll_mode) {
|
||||||
|
line_info_onKey(self, key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == 0x107 || key == 0x8 || key == 0x7f) { /* BACKSPACE key */
|
||||||
if (ctx->pos > 0) {
|
if (ctx->pos > 0) {
|
||||||
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos - 1]));
|
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos - 1]));
|
||||||
del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
|
del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
|
||||||
@ -579,13 +582,13 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
|
|||||||
|
|
||||||
else if (key == KEY_UP) { /* fetches previous item in history */
|
else if (key == KEY_UP) { /* fetches previous item in history */
|
||||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||||
&ctx->hst_pos, LN_HIST_MV_UP);
|
&ctx->hst_pos, MOVE_UP);
|
||||||
mv_curs_end(self->window, ctx->len, y2, x2);
|
mv_curs_end(self->window, ctx->len, y2, x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (key == KEY_DOWN) { /* fetches next item in history */
|
else if (key == KEY_DOWN) { /* fetches next item in history */
|
||||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||||
&ctx->hst_pos, LN_HIST_MV_DWN);
|
&ctx->hst_pos, MOVE_DOWN);
|
||||||
mv_curs_end(self->window, ctx->len, y2, x2);
|
mv_curs_end(self->window, ctx->len, y2, x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,7 +640,6 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
|
|||||||
|
|
||||||
wclear(ctx->linewin);
|
wclear(ctx->linewin);
|
||||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||||
wclrtobot(self->window);
|
|
||||||
|
|
||||||
if (!string_is_empty(line))
|
if (!string_is_empty(line))
|
||||||
add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos);
|
add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos);
|
||||||
@ -658,22 +660,14 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
|
|||||||
uint8_t selfname[TOX_MAX_NAME_LENGTH];
|
uint8_t selfname[TOX_MAX_NAME_LENGTH];
|
||||||
tox_get_self_name(m, selfname);
|
tox_get_self_name(m, selfname);
|
||||||
|
|
||||||
print_time(ctx->history);
|
uint8_t timefrmt[TIME_STR_SIZE];
|
||||||
wattron(ctx->history, COLOR_PAIR(GREEN));
|
get_time_str(timefrmt);
|
||||||
wprintw(ctx->history, "%s: ", selfname);
|
|
||||||
wattroff(ctx->history, COLOR_PAIR(GREEN));
|
|
||||||
|
|
||||||
if (line[0] == '>') {
|
line_info_add(self, timefrmt, selfname, NULL, line, OUT_MSG, 0, 0);
|
||||||
wattron(ctx->history, COLOR_PAIR(GREEN));
|
|
||||||
wprintw(ctx->history, "%s\n", line);
|
|
||||||
wattroff(ctx->history, COLOR_PAIR(GREEN));
|
|
||||||
} else
|
|
||||||
wprintw(ctx->history, "%s\n", line);
|
|
||||||
|
|
||||||
if (!statusbar->is_online || tox_send_message(m, self->num, line, strlen(line) + 1) == 0) {
|
if (!statusbar->is_online || tox_send_message(m, self->num, line, strlen(line) + 1) == 0) {
|
||||||
wattron(ctx->history, COLOR_PAIR(RED));
|
uint8_t *errmsg = " * Failed to send message.";
|
||||||
wprintw(ctx->history, " * Failed to send message.\n");
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
|
||||||
wattroff(ctx->history, COLOR_PAIR(RED));
|
|
||||||
} else {
|
} else {
|
||||||
write_to_log(line, selfname, ctx->log, false);
|
write_to_log(line, selfname, ctx->log, false);
|
||||||
}
|
}
|
||||||
@ -688,13 +682,13 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
|
|||||||
|
|
||||||
static void chat_onDraw(ToxWindow *self, Tox *m)
|
static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||||
{
|
{
|
||||||
curs_set(1);
|
|
||||||
int x2, y2;
|
int x2, y2;
|
||||||
getmaxyx(self->window, y2, x2);
|
getmaxyx(self->window, y2, x2);
|
||||||
|
|
||||||
ChatContext *ctx = self->chatwin;
|
ChatContext *ctx = self->chatwin;
|
||||||
|
|
||||||
wclear(ctx->linewin);
|
wclear(ctx->linewin);
|
||||||
|
line_info_print(self);
|
||||||
|
|
||||||
if (ctx->len > 0) {
|
if (ctx->len > 0) {
|
||||||
uint8_t line[MAX_STR_SIZE];
|
uint8_t line[MAX_STR_SIZE];
|
||||||
@ -796,6 +790,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
|||||||
|
|
||||||
static void chat_onInit(ToxWindow *self, Tox *m)
|
static void chat_onInit(ToxWindow *self, Tox *m)
|
||||||
{
|
{
|
||||||
|
curs_set(1);
|
||||||
int x2, y2;
|
int x2, y2;
|
||||||
getmaxyx(self->window, y2, x2);
|
getmaxyx(self->window, y2, x2);
|
||||||
self->x = x2;
|
self->x = x2;
|
||||||
@ -817,20 +812,23 @@ static void chat_onInit(ToxWindow *self, Tox *m)
|
|||||||
scrollok(ctx->history, 1);
|
scrollok(ctx->history, 1);
|
||||||
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2-CHATBOX_HEIGHT, 0);
|
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2-CHATBOX_HEIGHT, 0);
|
||||||
|
|
||||||
|
ctx->hst = malloc(sizeof(struct history));
|
||||||
ctx->log = malloc(sizeof(struct chatlog));
|
ctx->log = malloc(sizeof(struct chatlog));
|
||||||
|
|
||||||
if (ctx->log == NULL) {
|
if (ctx->log == NULL || ctx->hst == NULL) {
|
||||||
endwin();
|
endwin();
|
||||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(ctx->hst, 0, sizeof(struct history));
|
||||||
memset(ctx->log, 0, sizeof(struct chatlog));
|
memset(ctx->log, 0, sizeof(struct chatlog));
|
||||||
|
|
||||||
|
line_info_init(ctx->hst);
|
||||||
|
|
||||||
if (friends[self->num].logging_on)
|
if (friends[self->num].logging_on)
|
||||||
log_enable(self->name, friends[self->num].pub_key, ctx->log);
|
log_enable(self->name, friends[self->num].pub_key, ctx->log);
|
||||||
|
|
||||||
wprintw(ctx->history, "\n\n");
|
|
||||||
execute(ctx->history, self, m, "/help", CHAT_COMMAND_MODE);
|
execute(ctx->history, self, m, "/help", CHAT_COMMAND_MODE);
|
||||||
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
|
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
|
||||||
|
|
||||||
@ -880,7 +878,10 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
|
|||||||
ret.name[TOXIC_MAX_NAME_LENGTH] = '\0';
|
ret.name[TOXIC_MAX_NAME_LENGTH] = '\0';
|
||||||
|
|
||||||
ChatContext *chatwin = calloc(1, sizeof(ChatContext));
|
ChatContext *chatwin = calloc(1, sizeof(ChatContext));
|
||||||
|
memset(chatwin, 0, sizeof(ChatContext));
|
||||||
|
|
||||||
StatusBar *stb = calloc(1, sizeof(StatusBar));
|
StatusBar *stb = calloc(1, sizeof(StatusBar));
|
||||||
|
memset(stb, 0, sizeof(StatusBar));
|
||||||
|
|
||||||
if (stb != NULL && chatwin != NULL) {
|
if (stb != NULL && chatwin != NULL) {
|
||||||
ret.chatwin = chatwin;
|
ret.chatwin = chatwin;
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "misc_tools.h"
|
#include "misc_tools.h"
|
||||||
#include "friendlist.h"
|
#include "friendlist.h"
|
||||||
#include "execute.h"
|
#include "execute.h"
|
||||||
|
#include "line_info.h"
|
||||||
|
|
||||||
extern ToxWindow *prompt;
|
extern ToxWindow *prompt;
|
||||||
|
|
||||||
@ -48,80 +49,103 @@ void cmd_chat_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wattron(window, COLOR_PAIR(CYAN) | A_BOLD);
|
uint8_t *msg = "Chat commands:";
|
||||||
wprintw(window, "Chat commands:\n");
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||||
wattroff(window, COLOR_PAIR(CYAN) | A_BOLD);
|
|
||||||
|
#ifdef _SUPPORT_AUDIO
|
||||||
|
#define NUMLINES 11
|
||||||
|
#else
|
||||||
|
#define NUMLINES 7
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
|
||||||
|
|
||||||
#ifdef _SUPPORT_AUDIO
|
#ifdef _SUPPORT_AUDIO
|
||||||
|
|
||||||
wprintw(window, " /call : Audio call\n");
|
{ " /call : Audio call" },
|
||||||
wprintw(window, " /cancel : Cancel call\n");
|
{ " /cancel : Cancel call" },
|
||||||
wprintw(window, " /answer : Answer incomming call\n");
|
{ " /answer : Answer incomming call" },
|
||||||
wprintw(window, " /hangup : Hangup active call\n");
|
{ " /hangup : Hangup active call" },
|
||||||
|
|
||||||
#endif /* _SUPPORT_AUDIO */
|
#endif /* _SUPPORT_AUDIO */
|
||||||
|
|
||||||
wprintw(window, " /invite <n> : Invite friend to a group chat\n");
|
{ " /invite <n> : Invite friend to a group chat" },
|
||||||
wprintw(window, " /join : Join a pending group chat\n");
|
{ " /join : Join a pending group chat" },
|
||||||
wprintw(window, " /log <on> or <off> : Enable/disable logging\n");
|
{ " /log <on> or <off> : Enable/disable logging" },
|
||||||
wprintw(window, " /sendfile <filepath> : Send a file\n");
|
{ " /sendfile <filepath> : Send a file" },
|
||||||
wprintw(window, " /savefile <n> : Receive a file\n");
|
{ " /savefile <n> : Receive a file" },
|
||||||
wprintw(window, " /close : Close the current chat window\n");
|
{ " /close : Close the current chat window" },
|
||||||
wprintw(window, " /help : Print this message again\n");
|
{ " /help : Print this message again" },
|
||||||
wprintw(window, " /help global : Show a list of global commands\n");
|
//{ " /help global : Show a list of global commands" },
|
||||||
|
};
|
||||||
wattron(window, COLOR_PAIR(CYAN) | A_BOLD);
|
|
||||||
wprintw(window, " * Argument messages must be enclosed in quotation marks.\n\n");
|
int i;
|
||||||
wattroff(window, COLOR_PAIR(CYAN) | A_BOLD);
|
|
||||||
|
for (i = 0; i < NUMLINES; ++i)
|
||||||
|
line_info_add(self, NULL, NULL, NULL, lines[i], SYS_MSG, 0, 0);
|
||||||
|
|
||||||
|
msg = " * Use ESC key to toggle history scroll mode";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
|
uint8_t *errmsg;
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
wprintw(window, "Invalid syntax.\n");
|
errmsg = "Invalid syntax";
|
||||||
return;
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int groupnum = atoi(argv[1]);
|
int groupnum = atoi(argv[1]);
|
||||||
|
|
||||||
if (groupnum == 0 && strcmp(argv[1], "0")) { /* atoi returns 0 value on invalid input */
|
if (groupnum == 0 && strcmp(argv[1], "0")) { /* atoi returns 0 value on invalid input */
|
||||||
wprintw(window, "Invalid syntax.\n");
|
errmsg = "Invalid syntax.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tox_invite_friend(m, self->num, groupnum) == -1) {
|
if (tox_invite_friend(m, self->num, groupnum) == -1) {
|
||||||
wprintw(window, "Failed to invite friend.\n");
|
errmsg = "Failed to invite friend.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wprintw(window, "Invited friend to group chat %d.\n", groupnum);
|
uint8_t msg[MAX_STR_SIZE];
|
||||||
|
snprintf(msg, sizeof(msg), "Invited friend to Room #%d.", groupnum);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
|
uint8_t *errmsg;
|
||||||
|
|
||||||
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
|
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
|
||||||
wattron(window, COLOR_PAIR(RED));
|
errmsg = " * Warning: Too many windows are open.";
|
||||||
wprintw(window, " * Warning: Too many windows are open.\n");
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
|
||||||
wattron(window, COLOR_PAIR(RED));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *groupkey = friends[self->num].pending_groupchat;
|
uint8_t *groupkey = friends[self->num].pending_groupchat;
|
||||||
|
|
||||||
if (groupkey[0] == '\0') {
|
if (groupkey[0] == '\0') {
|
||||||
wprintw(window, "No pending group chat invite.\n");
|
errmsg = "No pending group chat invite.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int groupnum = tox_join_groupchat(m, self->num, groupkey);
|
int groupnum = tox_join_groupchat(m, self->num, groupkey);
|
||||||
|
|
||||||
if (groupnum == -1) {
|
if (groupnum == -1) {
|
||||||
wprintw(window, "Group chat instance failed to initialize.\n");
|
errmsg = "Group chat instance failed to initialize.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_groupchat_win(prompt, m, groupnum) == -1) {
|
if (init_groupchat_win(prompt, m, groupnum) == -1) {
|
||||||
wprintw(window, "Group chat window failed to initialize.\n");
|
errmsg = "Group chat window failed to initialize.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
tox_del_groupchat(m, groupnum);
|
tox_del_groupchat(m, groupnum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -129,36 +153,43 @@ void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
|
|||||||
|
|
||||||
void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
|
uint8_t *errmsg;
|
||||||
|
|
||||||
if (argc != 1) {
|
if (argc != 1) {
|
||||||
wprintw(window, "Invalid syntax.\n");
|
errmsg = "Invalid syntax.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t filenum = atoi(argv[1]);
|
uint8_t filenum = atoi(argv[1]);
|
||||||
|
|
||||||
if ((filenum == 0 && strcmp(argv[1], "0")) || filenum >= MAX_FILES) {
|
if ((filenum == 0 && strcmp(argv[1], "0")) || filenum >= MAX_FILES) {
|
||||||
wprintw(window, "No pending file transfers with that number.\n");
|
errmsg = "No pending file transfers with that number.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!friends[self->num].file_receiver.pending[filenum]) {
|
if (!friends[self->num].file_receiver.pending[filenum]) {
|
||||||
wprintw(window, "No pending file transfers with that number.\n");
|
errmsg = "No pending file transfers with that number.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *filename = friends[self->num].file_receiver.filenames[filenum];
|
uint8_t *filename = friends[self->num].file_receiver.filenames[filenum];
|
||||||
|
|
||||||
if (tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_ACCEPT, 0, 0) == 0) {
|
if (tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_ACCEPT, 0, 0) == 0) {
|
||||||
wprintw(window, "Accepted file transfer %u. Saving file as: '%s'\n", filenum, filename);
|
uint8_t msg[MAX_STR_SIZE];
|
||||||
|
snprintf(msg, sizeof(msg), "Accepted file transfer %u. Saving file as: '%s'", filenum, filename);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
|
|
||||||
if ((friends[self->num].file_receiver.files[filenum] = fopen(filename, "a")) == NULL) {
|
if ((friends[self->num].file_receiver.files[filenum] = fopen(filename, "a")) == NULL) {
|
||||||
wattron(window, COLOR_PAIR(RED));
|
errmsg = "* Error writing to file.";
|
||||||
wprintw(window, "* Error writing to file.\n");
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
|
||||||
wattroff(window, COLOR_PAIR(RED));
|
|
||||||
tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
|
tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wprintw(window, "File transfer failed.\n");
|
errmsg = "File transfer failed.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
friends[self->num].file_receiver.pending[filenum] = false;
|
friends[self->num].file_receiver.pending[filenum] = false;
|
||||||
@ -166,20 +197,25 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
|||||||
|
|
||||||
void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
|
uint8_t *errmsg;
|
||||||
|
|
||||||
if (max_file_senders_index >= (MAX_FILES-1)) {
|
if (max_file_senders_index >= (MAX_FILES-1)) {
|
||||||
wprintw(window,"Please wait for some of your outgoing file transfers to complete.\n");
|
errmsg = "Please wait for some of your outgoing file transfers to complete.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
wprintw(window, "Invalid syntax.\n");
|
errmsg = "Invalid syntax.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *path = argv[1];
|
uint8_t *path = argv[1];
|
||||||
|
|
||||||
if (path[0] != '\"') {
|
if (path[0] != '\"') {
|
||||||
wprintw(window, "File path must be enclosed in quotes.\n");
|
errmsg = "File path must be enclosed in quotes.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,14 +223,16 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
|||||||
int path_len = strlen(path);
|
int path_len = strlen(path);
|
||||||
|
|
||||||
if (path_len > MAX_STR_SIZE) {
|
if (path_len > MAX_STR_SIZE) {
|
||||||
wprintw(window, "File path exceeds character limit.\n");
|
errmsg = "File path exceeds character limit.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *file_to_send = fopen(path, "r");
|
FILE *file_to_send = fopen(path, "r");
|
||||||
|
|
||||||
if (file_to_send == NULL) {
|
if (file_to_send == NULL) {
|
||||||
wprintw(window, "File '%s' not found.\n", path);
|
errmsg = "File not found.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +245,8 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
|||||||
int filenum = tox_new_file_sender(m, self->num, filesize, filename, strlen(filename) + 1);
|
int filenum = tox_new_file_sender(m, self->num, filesize, filename, strlen(filename) + 1);
|
||||||
|
|
||||||
if (filenum == -1) {
|
if (filenum == -1) {
|
||||||
wprintw(window, "Error sending file.\n");
|
errmsg = "Error sending file.";
|
||||||
|
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +264,9 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
|||||||
file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1,
|
file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1,
|
||||||
tox_file_data_size(m, self->num), file_to_send);
|
tox_file_data_size(m, self->num), file_to_send);
|
||||||
|
|
||||||
wprintw(window, "Sending file: '%s'\n", path);
|
uint8_t msg[MAX_STR_SIZE];
|
||||||
|
snprintf(msg, sizeof(msg), "Sending file: '%s'", path);
|
||||||
|
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||||
|
|
||||||
if (i == max_file_senders_index)
|
if (i == max_file_senders_index)
|
||||||
++max_file_senders_index;
|
++max_file_senders_index;
|
||||||
|
@ -427,13 +427,13 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key)
|
|||||||
|
|
||||||
else if (key == KEY_UP) { /* fetches previous item in history */
|
else if (key == KEY_UP) { /* fetches previous item in history */
|
||||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||||
&ctx->hst_pos, LN_HIST_MV_UP);
|
&ctx->hst_pos, MOVE_UP);
|
||||||
mv_curs_end(self->window, ctx->len, y2, x2);
|
mv_curs_end(self->window, ctx->len, y2, x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (key == KEY_DOWN) { /* fetches next item in history */
|
else if (key == KEY_DOWN) { /* fetches next item in history */
|
||||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||||
&ctx->hst_pos, LN_HIST_MV_DWN);
|
&ctx->hst_pos, MOVE_DOWN);
|
||||||
mv_curs_end(self->window, ctx->len, y2, x2);
|
mv_curs_end(self->window, ctx->len, y2, x2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
321
src/line_info.c
Normal file
321
src/line_info.c
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
/* line_info.c
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Toxic All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Toxic.
|
||||||
|
*
|
||||||
|
* Toxic is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Toxic is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "toxic_windows.h"
|
||||||
|
#include "line_info.h"
|
||||||
|
|
||||||
|
void line_info_init(struct history *hst)
|
||||||
|
{
|
||||||
|
hst->line_root = malloc(sizeof(struct line_info));
|
||||||
|
memset(hst->line_root, 0, sizeof(struct line_info));
|
||||||
|
|
||||||
|
if (hst->line_root == NULL) {
|
||||||
|
endwin();
|
||||||
|
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
hst->line_start = hst->line_root;
|
||||||
|
hst->line_end = hst->line_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* resets line_start when scroll mode is disabled */
|
||||||
|
static void line_info_reset_start(struct history *hst)
|
||||||
|
{
|
||||||
|
struct line_info *line = hst->line_end;
|
||||||
|
uint32_t start_id = hst->start_id;
|
||||||
|
|
||||||
|
while (line) {
|
||||||
|
if (line->id == start_id) {
|
||||||
|
hst->line_start = line;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void line_info_toggle_scroll(ToxWindow *self, bool scroll)
|
||||||
|
{
|
||||||
|
ChatContext *ctx = self->chatwin;
|
||||||
|
struct history *hst = self->chatwin->hst;
|
||||||
|
|
||||||
|
if (scroll) {
|
||||||
|
hst->scroll_mode = true;
|
||||||
|
scrollok(ctx->history, 0);
|
||||||
|
curs_set(0);
|
||||||
|
} else {
|
||||||
|
hst->scroll_mode = false;
|
||||||
|
scrollok(ctx->history, 1);
|
||||||
|
line_info_reset_start(hst);
|
||||||
|
curs_set(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void line_info_cleanup(struct history *hst)
|
||||||
|
{
|
||||||
|
struct line_info *tmp1 = hst->line_root;
|
||||||
|
|
||||||
|
while (tmp1) {
|
||||||
|
struct line_info *tmp2 = tmp1->next;
|
||||||
|
free(tmp1);
|
||||||
|
tmp1 = tmp2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg,
|
||||||
|
uint8_t msgtype, uint8_t bold, uint8_t colour)
|
||||||
|
{
|
||||||
|
ChatContext *ctx = self->chatwin;
|
||||||
|
struct history *hst = self->chatwin->hst;
|
||||||
|
struct line_info *new_line = malloc(sizeof(struct line_info));
|
||||||
|
memset(new_line, 0, sizeof(struct line_info));
|
||||||
|
|
||||||
|
if (new_line == NULL) {
|
||||||
|
endwin();
|
||||||
|
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = 1; /* there will always be a newline */
|
||||||
|
|
||||||
|
/* for type-specific formatting in print function */
|
||||||
|
switch (msgtype) {
|
||||||
|
case OUT_MSG:
|
||||||
|
case IN_MSG:
|
||||||
|
len += 2;
|
||||||
|
break;
|
||||||
|
case ACTION:
|
||||||
|
len += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
memcpy(new_line->msg, msg, MAX_STR_SIZE);
|
||||||
|
len += strlen(msg);
|
||||||
|
} if (tmstmp) {
|
||||||
|
memcpy(new_line->timestamp, tmstmp, TIME_STR_SIZE);
|
||||||
|
len += strlen(tmstmp);
|
||||||
|
} if (name1) {
|
||||||
|
memcpy(new_line->name1, name1, TOXIC_MAX_NAME_LENGTH);
|
||||||
|
len += strlen(name1);
|
||||||
|
} if (name2) {
|
||||||
|
memcpy(new_line->name2, name2, TOXIC_MAX_NAME_LENGTH);
|
||||||
|
len += strlen(name2);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_line->len = len;
|
||||||
|
new_line->msgtype = msgtype;
|
||||||
|
new_line->bold = bold;
|
||||||
|
new_line->colour = colour;
|
||||||
|
new_line->id = hst->line_end->id + 1;
|
||||||
|
|
||||||
|
new_line->prev = hst->line_end;
|
||||||
|
hst->line_end->next = new_line;
|
||||||
|
hst->line_end = new_line;
|
||||||
|
|
||||||
|
/* If chat history exceeds limit move root forward and free old root */
|
||||||
|
if (++(hst->line_items) >= MAX_HISTORY) {
|
||||||
|
--hst->line_items;
|
||||||
|
struct line_info *tmp = hst->line_root->next;
|
||||||
|
tmp->prev = NULL;
|
||||||
|
|
||||||
|
if (hst->line_start->prev == NULL) { /* if line_start is root move it forward as well */
|
||||||
|
hst->line_start = hst->line_start->next;
|
||||||
|
hst->line_start->prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(hst->line_root);
|
||||||
|
hst->line_root = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int y, y2, x, x2;
|
||||||
|
getmaxyx(self->window, y2, x2);
|
||||||
|
getyx(ctx->history, y, x);
|
||||||
|
|
||||||
|
/* move line_start forward proportionate to the number of new rows */
|
||||||
|
if (y >= y2 - CHATBOX_HEIGHT) {
|
||||||
|
int i;
|
||||||
|
int lines = 1 + (len / x2);
|
||||||
|
|
||||||
|
while (lines > 0 && hst->line_start->next) {
|
||||||
|
lines -= (1 + hst->line_start->len / x2);
|
||||||
|
hst->line_start = hst->line_start->next;
|
||||||
|
++hst->start_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void line_info_print(ToxWindow *self)
|
||||||
|
{
|
||||||
|
ChatContext *ctx = self->chatwin;
|
||||||
|
wclear(ctx->history);
|
||||||
|
wmove(ctx->history, 1, 0);
|
||||||
|
int y2, x2;
|
||||||
|
getmaxyx(self->window, y2, x2);
|
||||||
|
|
||||||
|
struct line_info *line = ctx->hst->line_start;
|
||||||
|
int numlines = 0;
|
||||||
|
|
||||||
|
while(line && numlines <= x2) {
|
||||||
|
uint8_t type = line->msgtype;
|
||||||
|
numlines += line->len / x2;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case OUT_MSG:
|
||||||
|
case IN_MSG:
|
||||||
|
wattron(ctx->history, COLOR_PAIR(BLUE));
|
||||||
|
wprintw(ctx->history, "%s", line->timestamp);
|
||||||
|
wattroff(ctx->history, COLOR_PAIR(BLUE));
|
||||||
|
|
||||||
|
int nameclr = GREEN;
|
||||||
|
|
||||||
|
if (type == IN_MSG)
|
||||||
|
nameclr = CYAN;
|
||||||
|
if (line->colour)
|
||||||
|
nameclr = line->colour;
|
||||||
|
|
||||||
|
wattron(ctx->history, COLOR_PAIR(nameclr));
|
||||||
|
wprintw(ctx->history, "%s: ", line->name1);
|
||||||
|
wattroff(ctx->history, COLOR_PAIR(nameclr));
|
||||||
|
|
||||||
|
if (line->msg[0] == '>')
|
||||||
|
wattron(ctx->history, COLOR_PAIR(GREEN));
|
||||||
|
|
||||||
|
wprintw(ctx->history, "%s\n", line->msg);
|
||||||
|
|
||||||
|
if (line->msg[0] == '>')
|
||||||
|
wattroff(ctx->history, COLOR_PAIR(GREEN));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACTION:
|
||||||
|
wattron(ctx->history, COLOR_PAIR(BLUE));
|
||||||
|
wprintw(ctx->history, "%s", line->timestamp);
|
||||||
|
wattroff(ctx->history, COLOR_PAIR(BLUE));
|
||||||
|
|
||||||
|
wattron(ctx->history, COLOR_PAIR(YELLOW));
|
||||||
|
wprintw(ctx->history, "* %s %s\n", line->name1, line->msg);
|
||||||
|
wattroff(ctx->history, COLOR_PAIR(YELLOW));
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYS_MSG:
|
||||||
|
if (line->timestamp[0]) {
|
||||||
|
wattron(ctx->history, COLOR_PAIR(BLUE));
|
||||||
|
wprintw(ctx->history, "%s", line->timestamp);
|
||||||
|
wattroff(ctx->history, COLOR_PAIR(BLUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line->bold)
|
||||||
|
wattron(ctx->history, A_BOLD);
|
||||||
|
if (line->colour)
|
||||||
|
wattron(ctx->history, COLOR_PAIR(line->colour));
|
||||||
|
|
||||||
|
wprintw(ctx->history, "%s\n", line->msg);
|
||||||
|
|
||||||
|
if (line->bold)
|
||||||
|
wattroff(ctx->history, A_BOLD);
|
||||||
|
if (line->colour)
|
||||||
|
wattroff(ctx->history, COLOR_PAIR(line->colour));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void line_info_goto_root(struct history *hst)
|
||||||
|
{
|
||||||
|
hst->line_start = hst->line_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void line_info_scroll_up(struct history *hst)
|
||||||
|
{
|
||||||
|
if (hst->line_start->prev)
|
||||||
|
hst->line_start = hst->line_start->prev;
|
||||||
|
else beep();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void line_info_scroll_down(struct history *hst)
|
||||||
|
{
|
||||||
|
if (hst->line_start->next)
|
||||||
|
hst->line_start = hst->line_start->next;
|
||||||
|
else beep();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void line_info_page_up(ToxWindow *self, struct history *hst)
|
||||||
|
{
|
||||||
|
int x2, y2;
|
||||||
|
getmaxyx(self->window, y2, x2);
|
||||||
|
int jump_dist = y2 / 2;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < jump_dist && hst->line_start->prev; ++i)
|
||||||
|
hst->line_start = hst->line_start->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void line_info_page_down(ToxWindow *self, struct history *hst)
|
||||||
|
{
|
||||||
|
int x2, y2;
|
||||||
|
getmaxyx(self->window, y2, x2);
|
||||||
|
int jump_dist = y2 / 2;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < jump_dist && hst->line_start->next; ++i)
|
||||||
|
hst->line_start = hst->line_start->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void line_info_onKey(ToxWindow *self, wint_t key)
|
||||||
|
{
|
||||||
|
struct history *hst = self->chatwin->hst;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case KEY_PPAGE:
|
||||||
|
line_info_page_up(self, hst);
|
||||||
|
break;
|
||||||
|
case KEY_NPAGE:
|
||||||
|
line_info_page_down(self, hst);
|
||||||
|
break;
|
||||||
|
case KEY_UP:
|
||||||
|
line_info_scroll_up(hst);
|
||||||
|
break;
|
||||||
|
case KEY_DOWN:
|
||||||
|
line_info_scroll_down(hst);
|
||||||
|
break;
|
||||||
|
case KEY_HOME:
|
||||||
|
line_info_goto_root(hst);
|
||||||
|
break;
|
||||||
|
case KEY_END:
|
||||||
|
line_info_reset_start(hst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
64
src/line_info.h
Normal file
64
src/line_info.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* line_info.h
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Toxic All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Toxic.
|
||||||
|
*
|
||||||
|
* Toxic is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Toxic is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_HISTORY 50
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SYS_MSG,
|
||||||
|
IN_MSG,
|
||||||
|
OUT_MSG,
|
||||||
|
ACTION,
|
||||||
|
CONNECTION,
|
||||||
|
} LINE_TYPE;
|
||||||
|
|
||||||
|
struct line_info {
|
||||||
|
uint8_t timestamp[TIME_STR_SIZE];
|
||||||
|
uint8_t name1[TOXIC_MAX_NAME_LENGTH];
|
||||||
|
uint8_t name2[TOXIC_MAX_NAME_LENGTH];
|
||||||
|
uint8_t msg[MAX_STR_SIZE];
|
||||||
|
uint8_t msgtype;
|
||||||
|
uint8_t bold;
|
||||||
|
uint8_t colour;
|
||||||
|
uint32_t id;
|
||||||
|
int len; /* combined len of all strings */
|
||||||
|
|
||||||
|
struct line_info *prev;
|
||||||
|
struct line_info *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Linked list containing chat history lines */
|
||||||
|
struct history {
|
||||||
|
struct line_info *line_root;
|
||||||
|
struct line_info *line_start; /* the first line we want to start printing at */
|
||||||
|
struct line_info *line_end;
|
||||||
|
uint32_t start_id; /* keeps track of where line_start should be when at bottom of history */
|
||||||
|
uint32_t line_items;
|
||||||
|
bool scroll_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg,
|
||||||
|
uint8_t msgtype, uint8_t bold, uint8_t colour);
|
||||||
|
void line_info_cleanup(struct history *hst);
|
||||||
|
void line_info_toggle_scroll(ToxWindow *self, bool scroll);
|
||||||
|
void line_info_init(struct history *hst);
|
||||||
|
void line_info_print(ToxWindow *self);
|
||||||
|
void line_info_onKey(ToxWindow *self, wint_t key);
|
@ -51,9 +51,7 @@ void init_logging_session(uint8_t *name, uint8_t *key, struct chatlog *log)
|
|||||||
sprintf(&ident[2], "%02X", key[1] & 0xff);
|
sprintf(&ident[2], "%02X", key[1] & 0xff);
|
||||||
ident[KEY_IDENT_DIGITS*2+1] = '\0';
|
ident[KEY_IDENT_DIGITS*2+1] = '\0';
|
||||||
} else {
|
} else {
|
||||||
uint8_t s[MAX_STR_SIZE];
|
strftime(ident, sizeof(ident), "%Y-%m-%d[%H:%M:%S]", get_time());
|
||||||
strftime(s, MAX_STR_SIZE, "%Y-%m-%d[%H:%M:%S]", get_time());
|
|
||||||
snprintf(ident, sizeof(ident), "%s", s);
|
|
||||||
path_len += strlen(ident) + 1;
|
path_len += strlen(ident) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include "toxic_windows.h"
|
#include "toxic_windows.h"
|
||||||
|
#include "misc_tools.h"
|
||||||
|
|
||||||
extern ToxWindow *prompt;
|
extern ToxWindow *prompt;
|
||||||
|
|
||||||
@ -65,6 +66,11 @@ void print_time(WINDOW *window)
|
|||||||
wattroff(window,COLOR_PAIR(BLUE));
|
wattroff(window,COLOR_PAIR(BLUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_time_str(uint8_t *buf)
|
||||||
|
{
|
||||||
|
strftime(buf, TIME_STR_SIZE, "[%H:%M:%S] ", get_time());
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX: FIX */
|
/* XXX: FIX */
|
||||||
unsigned char *hex_string_to_bin(char hex_string[])
|
unsigned char *hex_string_to_bin(char hex_string[])
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ int qsort_strcasecmp_hlpr(const void *nick1, const void *nick2);
|
|||||||
- cannot be empty
|
- cannot be empty
|
||||||
- cannot start with a space
|
- cannot start with a space
|
||||||
- must not contain contiguous spaces */
|
- must not contain contiguous spaces */
|
||||||
bool valid_nick(uint8_t *nick);
|
int valid_nick(uint8_t *nick);
|
||||||
|
|
||||||
/* Moves the cursor to the end of the line in given window */
|
/* Moves the cursor to the end of the line in given window */
|
||||||
void mv_curs_end(WINDOW *w, size_t len, int max_y, int max_x);
|
void mv_curs_end(WINDOW *w, size_t len, int max_y, int max_x);
|
||||||
|
@ -208,7 +208,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key)
|
|||||||
else if (key == KEY_UP) { /* fetches previous item in history */
|
else if (key == KEY_UP) { /* fetches previous item in history */
|
||||||
wmove(self->window, prt->orig_y, X_OFST);
|
wmove(self->window, prt->orig_y, X_OFST);
|
||||||
fetch_hist_item(prt->line, &prt->pos, &prt->len, prt->ln_history, prt->hst_tot,
|
fetch_hist_item(prt->line, &prt->pos, &prt->len, prt->ln_history, prt->hst_tot,
|
||||||
&prt->hst_pos, LN_HIST_MV_UP);
|
&prt->hst_pos, MOVE_UP);
|
||||||
|
|
||||||
/* adjust line y origin appropriately when window scrolls down */
|
/* adjust line y origin appropriately when window scrolls down */
|
||||||
if (prt->at_bottom && prt->len >= x2 - X_OFST) {
|
if (prt->at_bottom && prt->len >= x2 - X_OFST) {
|
||||||
@ -230,7 +230,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key)
|
|||||||
else if (key == KEY_DOWN) { /* fetches next item in history */
|
else if (key == KEY_DOWN) { /* fetches next item in history */
|
||||||
wmove(self->window, prt->orig_y, X_OFST);
|
wmove(self->window, prt->orig_y, X_OFST);
|
||||||
fetch_hist_item(prt->line, &prt->pos, &prt->len, prt->ln_history, prt->hst_tot,
|
fetch_hist_item(prt->line, &prt->pos, &prt->len, prt->ln_history, prt->hst_tot,
|
||||||
&prt->hst_pos, LN_HIST_MV_DWN);
|
&prt->hst_pos, MOVE_DOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (key == '\t') { /* TAB key: completes command */
|
else if (key == '\t') { /* TAB key: completes command */
|
||||||
|
@ -148,7 +148,7 @@ void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZ
|
|||||||
void fetch_hist_item(wchar_t *buf, size_t *pos, size_t *len, wchar_t (*hst)[MAX_STR_SIZE],
|
void fetch_hist_item(wchar_t *buf, size_t *pos, size_t *len, wchar_t (*hst)[MAX_STR_SIZE],
|
||||||
int hst_tot, int *hst_pos, int key_dir)
|
int hst_tot, int *hst_pos, int key_dir)
|
||||||
{
|
{
|
||||||
if (key_dir == LN_HIST_MV_UP) {
|
if (key_dir == MOVE_UP) {
|
||||||
if (--(*hst_pos) < 0) {
|
if (--(*hst_pos) < 0) {
|
||||||
*hst_pos = 0;
|
*hst_pos = 0;
|
||||||
beep();
|
beep();
|
||||||
|
@ -48,11 +48,6 @@ void reset_buf(wchar_t *buf, size_t *pos, size_t *len);
|
|||||||
Returns the difference between the old len and new len of buf on success, -1 if error */
|
Returns the difference between the old len and new len of buf on success, -1 if error */
|
||||||
int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int n_items, int size);
|
int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int n_items, int size);
|
||||||
|
|
||||||
enum {
|
|
||||||
LN_HIST_MV_UP,
|
|
||||||
LN_HIST_MV_DWN,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* adds a line to the ln_history buffer at hst_pos and sets hst_pos to last history item. */
|
/* adds a line to the ln_history buffer at hst_pos and sets hst_pos to last history item. */
|
||||||
void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot,
|
void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot,
|
||||||
int *hst_pos);
|
int *hst_pos);
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#define CURS_Y_OFFSET 3 /* y-axis cursor offset for chat contexts */
|
#define CURS_Y_OFFSET 3 /* y-axis cursor offset for chat contexts */
|
||||||
#define CHATBOX_HEIGHT 4
|
#define CHATBOX_HEIGHT 4
|
||||||
#define KEY_IDENT_DIGITS 2 /* number of hex digits to display for the pub-key based identifier */
|
#define KEY_IDENT_DIGITS 2 /* number of hex digits to display for the pub-key based identifier */
|
||||||
|
#define TIME_STR_SIZE 16
|
||||||
|
|
||||||
#define EXIT_SUCCESS 0
|
#define EXIT_SUCCESS 0
|
||||||
#define EXIT_FAILURE 1
|
#define EXIT_FAILURE 1
|
||||||
@ -60,6 +61,7 @@
|
|||||||
#define T_KEY_PREV 0x0F /* ctrl-o */
|
#define T_KEY_PREV 0x0F /* ctrl-o */
|
||||||
#define T_KEY_C_E 0x05 /* ctrl-e */
|
#define T_KEY_C_E 0x05 /* ctrl-e */
|
||||||
#define T_KEY_C_A 0x01 /* ctrl-a */
|
#define T_KEY_C_A 0x01 /* ctrl-a */
|
||||||
|
#define T_KEY_ESC 0x1B /* ESC key */
|
||||||
|
|
||||||
/* Curses foreground colours (background is black) */
|
/* Curses foreground colours (background is black) */
|
||||||
enum {
|
enum {
|
||||||
@ -80,6 +82,11 @@ enum {
|
|||||||
WINDOW_ALERT_2,
|
WINDOW_ALERT_2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MOVE_UP,
|
||||||
|
MOVE_DOWN,
|
||||||
|
};
|
||||||
|
|
||||||
/* Fixes text color problem on some terminals.
|
/* Fixes text color problem on some terminals.
|
||||||
Uncomment if necessary */
|
Uncomment if necessary */
|
||||||
/* #define URXVT_FIX */
|
/* #define URXVT_FIX */
|
||||||
@ -176,13 +183,13 @@ struct ChatContext {
|
|||||||
size_t pos;
|
size_t pos;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
wchar_t ln_history[MAX_LINE_HIST][MAX_STR_SIZE];
|
wchar_t ln_history[MAX_LINE_HIST][MAX_STR_SIZE]; /* history for input lines/commands */
|
||||||
int hst_pos;
|
int hst_pos;
|
||||||
int hst_tot;
|
int hst_tot;
|
||||||
|
|
||||||
uint8_t self_is_typing;
|
struct history *hst;
|
||||||
|
|
||||||
struct chatlog *log;
|
struct chatlog *log;
|
||||||
|
uint8_t self_is_typing;
|
||||||
|
|
||||||
WINDOW *history;
|
WINDOW *history;
|
||||||
WINDOW *linewin;
|
WINDOW *linewin;
|
||||||
@ -203,7 +210,9 @@ struct PromptBuf {
|
|||||||
int hst_pos;
|
int hst_pos;
|
||||||
int hst_tot;
|
int hst_tot;
|
||||||
|
|
||||||
|
struct history *hst;
|
||||||
struct chatlog *log;
|
struct chatlog *log;
|
||||||
|
|
||||||
WINDOW *linewin;
|
WINDOW *linewin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user