1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-11-23 01:53:02 +01:00

Enable multiline input

Adds a nonl() call to avoid translation from \r to \n when pressing
enter.
C-J -> \n
Enter -> \r
To allow multiline input, \n chars (e.g. when pressing C-J) are replaced
with a pilcrow. After hitting enter, every pilcrow is substituted with
\n again.
This commit is contained in:
Marvin Ewald 2015-12-04 20:15:31 +01:00
parent eb02424f8a
commit e6f839f9ac
11 changed files with 112 additions and 64 deletions

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) static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
{ {
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
StatusBar *statusbar = self->stb; StatusBar *statusbar = self->stb;
@ -898,7 +897,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
return; return;
} }
if (ltr) { /* char is printable */ if (ltr || key == '\n') { /* char is printable */
input_new_char(self, key, x, y, x2, y2); input_new_char(self, key, x, y, x2, y2);
if (ctx->line[0] != '/' && !ctx->self_is_typing && statusbar->connection != TOX_CONNECTION_NONE) if (ctx->line[0] != '/' && !ctx->self_is_typing && statusbar->connection != TOX_CONNECTION_NONE)
@ -940,38 +939,42 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
sound_notify(self, notif_error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
} }
} else if (key == '\n') { } else if (key == '\r') {
rm_trailing_spaces_buf(ctx); rm_trailing_spaces_buf(ctx);
char line[MAX_STR_SIZE]; if (!wstring_is_empty(ctx->line))
{
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
memset(&line, 0, sizeof(line));
if (!string_is_empty(line))
add_line_to_hist(ctx); add_line_to_hist(ctx);
if (line[0] == '/') { wstrsubst(ctx->line, L'', L'\n');
if (strcmp(line, "/close") == 0) {
kill_chat_window(self, m); char line[MAX_STR_SIZE] = {0};
return;
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) { if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
send_action(self, ctx, m, line + strlen("/me ")); 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 { } 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); wclear(ctx->linewin);

View File

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

View File

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

View File

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

@ -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; 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); int cur_len = wcwidth(key);
/* this is the only place we need to do this check */
if (cur_len == -1) { if (cur_len == -1) {
sound_notify(self, notif_error, 0, NULL); sound_notify(self, notif_error, 0, NULL);
return; return;

View File

@ -176,6 +176,15 @@ int string_is_empty(const char *string)
return string[0] == '\0'; 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. */ /* 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) 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 */ /* Returns 1 if the string is empty, 0 otherwise */
int string_is_empty(const char *string); 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) */ /* 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); int char_to_wcs_buf(wchar_t *buf, const char *string, size_t n);

View File

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

View File

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

View File

@ -166,19 +166,19 @@ void reset_buf(ChatContext *ctx)
ctx->start = 0; ctx->start = 0;
} }
/* Removes trailing spaces from line. */ /* Removes trailing spaces and newlines from line. */
void rm_trailing_spaces_buf(ChatContext *ctx) void rm_trailing_spaces_buf(ChatContext *ctx)
{ {
if (ctx->len <= 0) if (ctx->len <= 0)
return; return;
if (ctx->line[ctx->len - 1] != ' ') if (ctx->line[ctx->len - 1] != ' ' && ctx->line[ctx->len - 1] != L'')
return; return;
int i; int i;
for (i = ctx->len - 1; i >= 0; --i) { for (i = ctx->len - 1; i >= 0; --i) {
if (ctx->line[i] != ' ') if (ctx->line[i] != ' ' && ctx->line[i] != L'')
break; break;
} }
@ -242,3 +242,19 @@ void fetch_hist_item(ChatContext *ctx, int key_dir)
ctx->pos = h_len; ctx->pos = h_len;
ctx->len = 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 */ resets line if at end of history */
void fetch_hist_item(ChatContext *ctx, int key_dir); 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 */ #endif /* #define TOXIC_STRINGS_H */