mirror of
https://github.com/Tha14/toxic.git
synced 2024-11-26 15:03:27 +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:
parent
eb02424f8a
commit
e6f839f9ac
19
src/chat.c
19
src/chat.c
@ -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,17 +939,20 @@ 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))
|
||||||
|
{
|
||||||
|
add_line_to_hist(ctx);
|
||||||
|
|
||||||
|
wstrsubst(ctx->line, L'¶', L'\n');
|
||||||
|
|
||||||
|
char line[MAX_STR_SIZE] = {0};
|
||||||
|
|
||||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
|
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
|
||||||
memset(&line, 0, sizeof(line));
|
memset(&line, 0, sizeof(line));
|
||||||
|
|
||||||
if (!string_is_empty(line))
|
|
||||||
add_line_to_hist(ctx);
|
|
||||||
|
|
||||||
if (line[0] == '/') {
|
if (line[0] == '/') {
|
||||||
if (strcmp(line, "/close") == 0) {
|
if (strcmp(line, "/close") == 0) {
|
||||||
kill_chat_window(self, m);
|
kill_chat_window(self, m);
|
||||||
@ -960,7 +962,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
} else {
|
} else {
|
||||||
execute(ctx->history, self, m, line, CHAT_COMMAND_MODE);
|
execute(ctx->history, self, m, line, CHAT_COMMAND_MODE);
|
||||||
}
|
}
|
||||||
} else if (!string_is_empty(line)) {
|
} else {
|
||||||
char selfname[TOX_MAX_NAME_LENGTH];
|
char selfname[TOX_MAX_NAME_LENGTH];
|
||||||
tox_self_get_name(m, (uint8_t *) selfname);
|
tox_self_get_name(m, (uint8_t *) selfname);
|
||||||
|
|
||||||
@ -973,6 +975,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
line_info_add(self, timefrmt, selfname, NULL, OUT_MSG, 0, 0, "%s", line);
|
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);
|
cqueue_add(ctx->cqueue, line, strlen(line), OUT_MSG, ctx->hst->line_end->id + 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wclear(ctx->linewin);
|
wclear(ctx->linewin);
|
||||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,17 +615,20 @@ 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);
|
||||||
|
|
||||||
|
if (!wstring_is_empty(ctx->line))
|
||||||
|
{
|
||||||
|
add_line_to_hist(ctx);
|
||||||
|
|
||||||
|
wstrsubst(ctx->line, L'¶', L'\n');
|
||||||
|
|
||||||
char line[MAX_STR_SIZE];
|
char line[MAX_STR_SIZE];
|
||||||
|
|
||||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
|
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
|
||||||
memset(&line, 0, sizeof(line));
|
memset(&line, 0, sizeof(line));
|
||||||
|
|
||||||
if (!string_is_empty(line))
|
|
||||||
add_line_to_hist(ctx);
|
|
||||||
|
|
||||||
if (line[0] == '/') {
|
if (line[0] == '/') {
|
||||||
if (strcmp(line, "/close") == 0) {
|
if (strcmp(line, "/close") == 0) {
|
||||||
close_groupchat(self, m, self->num);
|
close_groupchat(self, m, self->num);
|
||||||
@ -635,12 +638,13 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
} else {
|
} else {
|
||||||
execute(ctx->history, self, m, line, GROUPCHAT_COMMAND_MODE);
|
execute(ctx->history, self, m, line, GROUPCHAT_COMMAND_MODE);
|
||||||
}
|
}
|
||||||
} else if (!string_is_empty(line)) {
|
} else {
|
||||||
if (tox_group_message_send(m, self->num, (uint8_t *) line, strlen(line)) == -1) {
|
if (tox_group_message_send(m, self->num, (uint8_t *) line, strlen(line)) == -1) {
|
||||||
const char *errmsg = " * Failed to send message.";
|
const char *errmsg = " * Failed to send message.";
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg);
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wclear(ctx->linewin);
|
wclear(ctx->linewin);
|
||||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
13
src/prompt.c
13
src/prompt.c
@ -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);
|
||||||
|
|
||||||
|
if (!wstring_is_empty(ctx->line))
|
||||||
|
{
|
||||||
|
add_line_to_hist(ctx);
|
||||||
|
wstrsubst(ctx->line, L'¶', L'\n');
|
||||||
|
|
||||||
char line[MAX_STR_SIZE] = {0};
|
char line[MAX_STR_SIZE] = {0};
|
||||||
|
|
||||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
|
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
|
||||||
memset(&line, 0, sizeof(line));
|
memset(&line, 0, sizeof(line));
|
||||||
|
|
||||||
if (!string_is_empty(line))
|
|
||||||
add_line_to_hist(ctx);
|
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, PROMPT, 0, 0, "%s", line);
|
line_info_add(self, NULL, NULL, NULL, PROMPT, 0, 0, "%s", line);
|
||||||
execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE);
|
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);
|
||||||
|
@ -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()) {
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user