1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-11-26 16:03:27 +01:00

Merge branch 'mall0c-multiline'

This commit is contained in:
Jfreegman 2016-02-29 19:22:41 -05:00
commit f43f644451
No known key found for this signature in database
GPG Key ID: 3627F3144076AE63
20 changed files with 172 additions and 82 deletions

View File

@ -313,6 +313,11 @@ Key combination to scroll contacts list down\&.
.RS 4
Toggle the peer list on and off\&.
.RE
.PP
\fBtoggle_paste_mode\fR
.RS 4
Toggle treating linebreaks as enter key press\&.
.RE
.RE
.SH "FILES"
.PP

View File

@ -201,6 +201,9 @@ OPTIONS
*toggle_peerlist*;;
Toggle the peer list on and off.
*toggle_paste_mode*;;
Toggle treating linebreaks as enter key press.
FILES
-----

View File

@ -101,5 +101,6 @@ keys = {
peer_list_up="Ctrl+[";
peer_list_down="Ctrl+]";
toggle_peerlist="Ctrl+b";
toggle_paste_mode="Ctrl+T";
};

View File

@ -882,7 +882,6 @@ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
{
ChatContext *ctx = self->chatwin;
StatusBar *statusbar = self->stb;
@ -893,12 +892,15 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (y2 <= 0 || x2 <= 0)
return;
if (ctx->pastemode && key == '\r')
key = '\n';
if (self->help->active) {
help_onKey(self, key);
return;
}
if (ltr) { /* char is printable */
if (ltr || key == '\n') { /* char is printable */
input_new_char(self, key, x, y, x2, y2);
if (ctx->line[0] != '/' && !ctx->self_is_typing && statusbar->connection != TOX_CONNECTION_NONE)
@ -940,38 +942,42 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
sound_notify(self, notif_error, 0, NULL);
}
} else if (key == '\n') {
} else if (key == '\r') {
rm_trailing_spaces_buf(ctx);
char line[MAX_STR_SIZE];
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
memset(&line, 0, sizeof(line));
if (!string_is_empty(line))
if (!wstring_is_empty(ctx->line))
{
add_line_to_hist(ctx);
if (line[0] == '/') {
if (strcmp(line, "/close") == 0) {
kill_chat_window(self, m);
return;
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
send_action(self, ctx, m, line + strlen("/me "));
wstrsubst(ctx->line, L'', L'\n');
char line[MAX_STR_SIZE] = {0};
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
memset(&line, 0, sizeof(line));
if (line[0] == '/') {
if (strcmp(line, "/close") == 0) {
kill_chat_window(self, m);
return;
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
send_action(self, ctx, m, line + strlen("/me "));
} else {
execute(ctx->history, self, m, line, CHAT_COMMAND_MODE);
}
} else {
execute(ctx->history, self, m, line, CHAT_COMMAND_MODE);
char selfname[TOX_MAX_NAME_LENGTH];
tox_self_get_name(m, (uint8_t *) selfname);
size_t len = tox_self_get_name_size(m);
selfname[len] = '\0';
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, selfname, NULL, OUT_MSG, 0, 0, "%s", line);
cqueue_add(ctx->cqueue, line, strlen(line), OUT_MSG, ctx->hst->line_end->id + 1);
}
} else if (!string_is_empty(line)) {
char selfname[TOX_MAX_NAME_LENGTH];
tox_self_get_name(m, (uint8_t *) selfname);
size_t len = tox_self_get_name_size(m);
selfname[len] = '\0';
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, selfname, NULL, OUT_MSG, 0, 0, "%s", line);
cqueue_add(ctx->cqueue, line, strlen(line), OUT_MSG, ctx->hst->line_end->id + 1);
}
wclear(ctx->linewin);

View File

@ -757,7 +757,7 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
return;
switch (key) {
case '\n':
case '\r':
if (blocklist_view)
break;

View File

@ -36,6 +36,7 @@
#include "avatars.h"
#include "name_lookup.h"
#include "qr_code.h"
#include "toxic_strings.h"
extern char *DATA_FILE;
extern ToxWindow *prompt;
@ -513,11 +514,12 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
return;
}
/* remove opening and closing quotes */
/* remove opening and closing quotes and replace linebreaks with spaces */
char msg[MAX_STR_SIZE];
snprintf(msg, sizeof(msg), "%s", &argv[1][1]);
int len = strlen(msg) - 1;
msg[len] = '\0';
strsubst(msg, '\n', ' ');
prompt_update_statusmessage(prompt, m, msg);
}

View File

@ -571,7 +571,10 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
return;
}
if (ltr) { /* char is printable */
if (ctx->pastemode && key == '\r')
key = '\n';
if (ltr || key == '\n') { /* char is printable */
input_new_char(self, key, x, y, x2, y2);
return;
}
@ -615,30 +618,34 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
} else if (key == user_settings->key_peer_list_up) {
if (groupchats[self->num].side_pos > 0)
--groupchats[self->num].side_pos;
} else if (key == '\n') {
} else if (key == '\r') {
rm_trailing_spaces_buf(ctx);
char line[MAX_STR_SIZE];
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
memset(&line, 0, sizeof(line));
if (!string_is_empty(line))
if (!wstring_is_empty(ctx->line))
{
add_line_to_hist(ctx);
if (line[0] == '/') {
if (strcmp(line, "/close") == 0) {
close_groupchat(self, m, self->num);
return;
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
send_group_action(self, ctx, m, line + strlen("/me "));
wstrsubst(ctx->line, L'', L'\n');
char line[MAX_STR_SIZE];
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
memset(&line, 0, sizeof(line));
if (line[0] == '/') {
if (strcmp(line, "/close") == 0) {
close_groupchat(self, m, self->num);
return;
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
send_group_action(self, ctx, m, line + strlen("/me "));
} else {
execute(ctx->history, self, m, line, GROUPCHAT_COMMAND_MODE);
}
} else {
execute(ctx->history, self, m, line, GROUPCHAT_COMMAND_MODE);
}
} else if (!string_is_empty(line)) {
if (tox_group_message_send(m, self->num, (uint8_t *) line, strlen(line)) == -1) {
const char *errmsg = " * Failed to send message.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg);
if (tox_group_message_send(m, self->num, (uint8_t *) line, strlen(line)) == -1) {
const char *errmsg = " * Failed to send message.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg);
}
}
}

View File

@ -245,7 +245,9 @@ static void help_draw_keys(ToxWindow *self)
wprintw(win, " Ctrl+F and Ctrl+V : Scroll window history half a page\n");
wprintw(win, " Ctrl+H : Move to the bottom of window history\n");
wprintw(win, " Ctrl+[ and Ctrl+] : Scroll peer list in groupchats\n");
wprintw(win, " Ctrl+B : Toggle the groupchat peerlist\n\n");
wprintw(win, " Ctrl+B : Toggle the groupchat peerlist\n");
wprintw(win, " Ctrl+J : Insert new line\n");
wprintw(win, " Ctrl+T : Toggle paste mode\n\n");
wprintw(win, " (Note: Custom keybindings override these defaults.)\n\n");
help_draw_bottom_menu(win);
@ -335,7 +337,7 @@ void help_onKey(ToxWindow *self, wint_t key)
break;
case 'k':
help_init_window(self, 13, 80);
help_init_window(self, 15, 80);
self->help->type = HELP_KEYS;
break;

View File

@ -42,9 +42,12 @@ void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_
{
ChatContext *ctx = self->chatwin;
/* this is the only place we need to do this check */
if (key == '\n')
key = L'';
int cur_len = wcwidth(key);
/* this is the only place we need to do this check */
if (cur_len == -1) {
sound_notify(self, notif_error, 0, NULL);
return;
@ -266,15 +269,19 @@ bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y)
/* TODO: this special case is ugly.
maybe convert entire function to if/else and make them all customizable keys? */
if (!match && key == user_settings->key_toggle_peerlist) {
if (self->is_groupchat) {
self->show_peerlist ^= 1;
redraw_groupchat_win(self);
if (!match) {
if (key == user_settings->key_toggle_peerlist) {
if (self->is_groupchat) {
self->show_peerlist ^= 1;
redraw_groupchat_win(self);
}
match = true;
}
else if (key == user_settings->key_toggle_pastemode) {
self->chatwin->pastemode ^= 1;
match = true;
}
match = true;
}
return match;
}

View File

@ -323,17 +323,27 @@ void line_info_print(ToxWindow *self)
wprintw(win, "%s %s: ", user_settings->line_normal, line->name1);
wattroff(win, COLOR_PAIR(nameclr));
if (line->msg[0] == '>')
wattron(win, COLOR_PAIR(GREEN));
else if (line->msg[0] == '<')
wattron(win, COLOR_PAIR(RED));
char* msg = line->msg;
while (msg)
{
char* line = strsep(&msg, "\n");
wprintw(win, "%s", line->msg);
if (line[0] == '>')
wattron(win, COLOR_PAIR(GREEN));
else if (line[0] == '<')
wattron(win, COLOR_PAIR(RED));
if (line->msg[0] == '>')
wattroff(win, COLOR_PAIR(GREEN));
else if (line->msg[0] == '<')
wattroff(win, COLOR_PAIR(RED));
wprintw(win, "%s%c", line, msg ? '\n' : '\0');
if (line[0] == '>')
wattroff(win, COLOR_PAIR(GREEN));
else if (line[0] == '<')
wattroff(win, COLOR_PAIR(RED));
// change the \0 set by strsep back to \n
if (msg)
msg[-1] = '\n';
}
if (type == OUT_MSG && timed_out(line->timestamp, NOREAD_FLAG_TIMEOUT)) {
wattron(win, COLOR_PAIR(RED));

View File

@ -176,6 +176,15 @@ int string_is_empty(const char *string)
return string[0] == '\0';
}
/* Returns 1 if the string is empty, 0 otherwise */
int wstring_is_empty(const wchar_t *string)
{
if (!string)
return true;
return string[0] == L'\0';
}
/* convert a multibyte string to a wide character string and puts in buf. */
int mbs_to_wcs_buf(wchar_t *buf, const char *string, size_t n)
{

View File

@ -78,6 +78,9 @@ void update_unix_time(void);
/* Returns 1 if the string is empty, 0 otherwise */
int string_is_empty(const char *string);
/* Same as above but for wide character strings */
int wstring_is_empty(const wchar_t *string);
/* convert a multibyte string to a wide character string (must provide buffer) */
int char_to_wcs_buf(wchar_t *buf, const char *string, size_t n);

View File

@ -189,13 +189,16 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (x2 <= 0 || y2 <= 0)
return;
if (ctx->pastemode && key == '\r')
key = '\n';
/* ignore non-menu related input if active */
if (self->help->active) {
help_onKey(self, key);
return;
}
if (ltr) { /* char is printable */
if (ltr || key == '\n') { /* char is printable */
input_new_char(self, key, x, y, x2, y2);
return;
}
@ -232,19 +235,22 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
} else {
sound_notify(self, notif_error, 0, NULL);
}
} else if (key == '\n') {
} else if (key == '\r') {
rm_trailing_spaces_buf(ctx);
char line[MAX_STR_SIZE] = {0};
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
memset(&line, 0, sizeof(line));
if (!string_is_empty(line))
if (!wstring_is_empty(ctx->line))
{
add_line_to_hist(ctx);
wstrsubst(ctx->line, L'', L'\n');
line_info_add(self, NULL, NULL, NULL, PROMPT, 0, 0, "%s", line);
execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE);
char line[MAX_STR_SIZE] = {0};
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
memset(&line, 0, sizeof(line));
line_info_add(self, NULL, NULL, NULL, PROMPT, 0, 0, "%s", line);
execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE);
}
wclear(ctx->linewin);
wmove(self->window, y2 - CURS_Y_OFFSET, 0);

View File

@ -127,6 +127,7 @@ static const struct keys_strings {
const char* peer_list_up;
const char* peer_list_down;
const char* toggle_peerlist;
const char* toggle_pastemode;
} key_strings = {
"keys",
"next_tab",
@ -139,6 +140,7 @@ static const struct keys_strings {
"peer_list_up",
"peer_list_down",
"toggle_peerlist",
"toggle_paste_mode",
};
/* defines from toxic.h */
@ -154,6 +156,7 @@ static void key_defaults(struct user_settings* settings)
settings->key_peer_list_up = T_KEY_C_LB;
settings->key_peer_list_down = T_KEY_C_RB;
settings->key_toggle_peerlist = T_KEY_C_B;
settings->key_toggle_pastemode = T_KEY_C_T;
}
static const struct tox_strings {
@ -399,6 +402,8 @@ int settings_load(struct user_settings *s, const char *patharg)
s->key_peer_list_down = key_parse(&tmp);
if (config_setting_lookup_string(setting, key_strings.toggle_peerlist, &tmp))
s->key_toggle_peerlist = key_parse(&tmp);
if (config_setting_lookup_string(setting, key_strings.toggle_pastemode, &tmp))
s->key_toggle_pastemode = key_parse(&tmp);
}
#ifdef AUDIO

View File

@ -68,6 +68,7 @@ struct user_settings {
int key_peer_list_up;
int key_peer_list_down;
int key_toggle_peerlist;
int key_toggle_pastemode;
int mplex_away; /* boolean (1 for reaction to terminal attach/detach) */
char mplex_away_note [TOX_MAX_STATUS_MESSAGE_LENGTH];

View File

@ -200,6 +200,7 @@ static void init_term(void)
cbreak();
keypad(stdscr, 1);
noecho();
nonl();
timeout(100);
if (has_colors()) {

View File

@ -70,6 +70,7 @@
#define T_KEY_C_L 0x0C /* ctrl-l */
#define T_KEY_C_W 0x17 /* ctrl-w */
#define T_KEY_C_B 0x02 /* ctrl-b */
#define T_KEY_C_T 0x14 /* ctrl-t */
#define T_KEY_TAB 0x09 /* TAB key */
#define ONLINE_CHAR "*"

View File

@ -166,19 +166,19 @@ void reset_buf(ChatContext *ctx)
ctx->start = 0;
}
/* Removes trailing spaces from line. */
/* Removes trailing spaces and newlines from line. */
void rm_trailing_spaces_buf(ChatContext *ctx)
{
if (ctx->len <= 0)
return;
if (ctx->line[ctx->len - 1] != ' ')
if (ctx->line[ctx->len - 1] != ' ' && ctx->line[ctx->len - 1] != L'')
return;
int i;
for (i = ctx->len - 1; i >= 0; --i) {
if (ctx->line[i] != ' ')
if (ctx->line[i] != ' ' && ctx->line[i] != L'')
break;
}
@ -242,3 +242,19 @@ void fetch_hist_item(ChatContext *ctx, int key_dir)
ctx->pos = h_len;
ctx->len = h_len;
}
void strsubst(char* str, char old, char new)
{
int i;
for (i = 0; str[i] != '\0'; ++i)
if (str[i] == old)
str[i] = new;
}
void wstrsubst(wchar_t* str, wchar_t old, wchar_t new)
{
int i;
for (i = 0; str[i] != L'\0'; ++i)
if (str[i] == old)
str[i] = new;
}

View File

@ -66,4 +66,8 @@ void add_line_to_hist(ChatContext *ctx);
resets line if at end of history */
void fetch_hist_item(ChatContext *ctx, int key_dir);
/* Substitutes all occurrences of old with new. */
void strsubst(char *str, char old, char new);
void wstrsubst(wchar_t *str, wchar_t old, wchar_t new);
#endif /* #define TOXIC_STRINGS_H */

View File

@ -237,6 +237,7 @@ struct ChatContext {
#endif
uint8_t self_is_typing;
uint8_t pastemode; /* whether to translate \r to \n */
WINDOW *history;
WINDOW *linewin;