merge/upstream-full #105
@@ -109,19 +109,26 @@ static gboolean _cmd_execute_alias(ProfWin* window, const char* const inp, gbool
|
||||
static gboolean
|
||||
_download_install_plugin(ProfWin* window, gchar* url, gchar* path);
|
||||
|
||||
static void
|
||||
_vcard_editor_finished_cb(gchar* message, void* user_data)
|
||||
{
|
||||
if (message) {
|
||||
char** field = user_data;
|
||||
if (*field) {
|
||||
free(*field);
|
||||
}
|
||||
*field = g_strdup(message);
|
||||
cons_show("Field updated. Remember to call /me save to apply changes.");
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_update_vcard_field(char** field, char* value)
|
||||
{
|
||||
if (!value) {
|
||||
gchar* editor_value;
|
||||
if (get_message_from_editor(*field, &editor_value)) {
|
||||
if (launch_editor(*field, _vcard_editor_finished_cb, field)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (*field) {
|
||||
free(*field);
|
||||
}
|
||||
*field = editor_value;
|
||||
} else {
|
||||
if (*field) {
|
||||
free(*field);
|
||||
@@ -1640,6 +1647,51 @@ cmd_help(ProfWin* window, const char* const command, gchar** args)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cmd_editor_finished_cb(gchar* message, void* user_data)
|
||||
{
|
||||
if (message) {
|
||||
rl_insert_text(message);
|
||||
rl_point = rl_end;
|
||||
rl_forced_update_display();
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ProfWin* window;
|
||||
char* roomjid;
|
||||
} EditorFinishedContext;
|
||||
|
||||
static void
|
||||
_cmd_room_editor_finished_cb(gchar* message, void* user_data)
|
||||
{
|
||||
EditorFinishedContext* ctx = user_data;
|
||||
if (message && ctx->roomjid) {
|
||||
message_send_groupchat_subject(ctx->roomjid, message);
|
||||
}
|
||||
if (ctx) {
|
||||
g_free(ctx->roomjid);
|
||||
g_free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cmd_correct_editor_finished_cb(gchar* message, void* user_data)
|
||||
{
|
||||
EditorFinishedContext* ctx = user_data;
|
||||
if (message && ctx->window) {
|
||||
if (ctx->window->type == WIN_CHAT) {
|
||||
ProfChatWin* chatwin = (ProfChatWin*)ctx->window;
|
||||
cl_ev_send_msg_correct(chatwin, message, FALSE, TRUE);
|
||||
} else if (ctx->window->type == WIN_MUC) {
|
||||
ProfMucWin* mucwin = (ProfMucWin*)ctx->window;
|
||||
cl_ev_send_muc_msg_corrected(mucwin, message, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
g_free(ctx);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cmd_about(ProfWin* window, const char* const command, gchar** args)
|
||||
{
|
||||
@@ -4033,18 +4085,13 @@ cmd_subject(ProfWin* window, const char* const command, gchar** args)
|
||||
}
|
||||
|
||||
if (g_strcmp0(args[0], "editor") == 0) {
|
||||
gchar* message = NULL;
|
||||
char* subject = muc_subject(mucwin->roomjid);
|
||||
|
||||
if (get_message_from_editor(subject, &message)) {
|
||||
return TRUE;
|
||||
}
|
||||
EditorFinishedContext* ctx = g_new0(EditorFinishedContext, 1);
|
||||
ctx->roomjid = g_strdup(mucwin->roomjid);
|
||||
|
||||
launch_editor(subject, _cmd_room_editor_finished_cb, ctx);
|
||||
|
||||
if (message) {
|
||||
message_send_groupchat_subject(mucwin->roomjid, message);
|
||||
} else {
|
||||
cons_bad_cmd_usage(command);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -9567,16 +9614,7 @@ cmd_change_password(ProfWin* window, const char* const command, gchar** args)
|
||||
gboolean
|
||||
cmd_editor(ProfWin* window, const char* const command, gchar** args)
|
||||
{
|
||||
auto_gchar gchar* message = NULL;
|
||||
|
||||
if (get_message_from_editor(NULL, &message)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rl_insert_text(message);
|
||||
ui_resize();
|
||||
rl_point = rl_end;
|
||||
rl_forced_update_display();
|
||||
launch_editor(NULL, _cmd_editor_finished_cb, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -9590,20 +9628,10 @@ cmd_correct_editor(ProfWin* window, const char* const command, gchar** args)
|
||||
|
||||
gchar* initial_message = win_get_last_sent_message(window);
|
||||
|
||||
auto_gchar gchar* message = NULL;
|
||||
if (get_message_from_editor(initial_message, &message)) {
|
||||
return TRUE;
|
||||
}
|
||||
EditorFinishedContext* ctx = g_new0(EditorFinishedContext, 1);
|
||||
ctx->window = window;
|
||||
|
||||
if (window->type == WIN_CHAT) {
|
||||
ProfChatWin* chatwin = (ProfChatWin*)window;
|
||||
|
||||
cl_ev_send_msg_correct(chatwin, message, FALSE, TRUE);
|
||||
} else if (window->type == WIN_MUC) {
|
||||
ProfMucWin* mucwin = (ProfMucWin*)window;
|
||||
|
||||
cl_ev_send_muc_msg_corrected(mucwin, message, FALSE, TRUE);
|
||||
}
|
||||
launch_editor(initial_message, _cmd_correct_editor_finished_cb, ctx);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -20,14 +20,52 @@
|
||||
#include "log.h"
|
||||
#include "common.h"
|
||||
#include "xmpp/xmpp.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
typedef struct EditorContext
|
||||
{
|
||||
gchar* filename;
|
||||
void (*callback)(gchar* content, void* user_data);
|
||||
void* user_data;
|
||||
} EditorContext;
|
||||
|
||||
static void
|
||||
_editor_exit_cb(GPid pid, gint status, gpointer data)
|
||||
{
|
||||
EditorContext* ctx = data;
|
||||
gchar* contents = NULL;
|
||||
GError* error = NULL;
|
||||
|
||||
ui_resume();
|
||||
ui_resize();
|
||||
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||
if (g_file_get_contents(ctx->filename, &contents, NULL, &error)) {
|
||||
g_strchomp(contents);
|
||||
ctx->callback(contents, ctx->user_data);
|
||||
g_free(contents);
|
||||
} else {
|
||||
log_error("[Editor] could not read from %s: %s", ctx->filename, error->message);
|
||||
cons_show_error("Could not read edited content: %s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
} else {
|
||||
cons_show_error("Editor exited with error status %d", WEXITSTATUS(status));
|
||||
}
|
||||
|
||||
if (remove(ctx->filename) != 0) {
|
||||
log_error("[Editor] error during file deletion of %s", ctx->filename);
|
||||
}
|
||||
|
||||
g_free(ctx->filename);
|
||||
g_free(ctx);
|
||||
g_spawn_close_pid(pid);
|
||||
}
|
||||
|
||||
// Returns true if an error occurred
|
||||
gboolean
|
||||
get_message_from_editor(gchar* message, gchar** returned_message)
|
||||
launch_editor(gchar* initial_content, void (*callback)(gchar* content, void* data), void* user_data)
|
||||
{
|
||||
/* Make sure that there's no junk in the return-pointer in error cases */
|
||||
*returned_message = NULL;
|
||||
|
||||
auto_gchar gchar* filename = NULL;
|
||||
auto_gerror GError* glib_error = NULL;
|
||||
const char* jid = connection_get_barejid();
|
||||
@@ -37,64 +75,65 @@ get_message_from_editor(gchar* message, gchar** returned_message)
|
||||
log_debug("[Editor] could not get JID");
|
||||
auto_gchar gchar* data_dir = files_get_data_path(DIR_EDITOR);
|
||||
if (!create_dir(data_dir)) {
|
||||
cons_show_error("Could not create editor directory.");
|
||||
return TRUE;
|
||||
}
|
||||
filename = g_strdup_printf("%s/compose.md", data_dir);
|
||||
}
|
||||
if (!filename) {
|
||||
log_error("[Editor] something went wrong while creating compose file");
|
||||
cons_show_error("Could not create compose file.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gsize messagelen = 0;
|
||||
if (message != NULL) {
|
||||
messagelen = strlen(message);
|
||||
if (initial_content != NULL) {
|
||||
messagelen = strlen(initial_content);
|
||||
}
|
||||
|
||||
if (!g_file_set_contents(filename, message, messagelen, &glib_error)) {
|
||||
if (!g_file_set_contents(filename, initial_content, messagelen, &glib_error)) {
|
||||
log_error("[Editor] could not write to %s: %s", filename, PROF_GERROR_MESSAGE(glib_error));
|
||||
cons_show_error("Could not write to compose file: %s", PROF_GERROR_MESSAGE(glib_error));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
auto_gchar gchar* editor = prefs_get_string(PREF_COMPOSE_EDITOR);
|
||||
auto_gchar gchar* editor_with_filename = g_strdup_printf("%s %s", editor, filename);
|
||||
auto_gcharv gchar** editor_argv = g_strsplit(editor_with_filename, " ", 0);
|
||||
gchar** editor_argv = NULL;
|
||||
GError* error = NULL;
|
||||
|
||||
if (!editor_argv || !editor_argv[0]) {
|
||||
log_error("[Editor] Failed to parse editor command: %s", editor);
|
||||
auto_gchar gchar* full_cmd = g_strdup_printf("%s %s", editor, filename);
|
||||
if (!g_shell_parse_argv(full_cmd, NULL, &editor_argv, &error)) {
|
||||
log_error("[Editor] Failed to parse editor command: %s", error->message);
|
||||
cons_show_error("Failed to parse editor command: %s", error->message);
|
||||
g_error_free(error);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Fork / exec
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
if (editor_argv && editor_argv[0]) {
|
||||
int x = execvp(editor_argv[0], editor_argv);
|
||||
if (x == -1)
|
||||
log_error("[Editor] Failed to exec %s", editor);
|
||||
}
|
||||
_exit(EXIT_FAILURE);
|
||||
} else {
|
||||
if (pid == -1) {
|
||||
return TRUE;
|
||||
}
|
||||
waitpid(pid, NULL, 0);
|
||||
EditorContext* ctx = g_new0(EditorContext, 1);
|
||||
ctx->filename = g_steal_pointer(&filename);
|
||||
ctx->callback = callback;
|
||||
ctx->user_data = user_data;
|
||||
|
||||
gchar* contents;
|
||||
gsize length;
|
||||
if (!g_file_get_contents(filename, &contents, &length, &glib_error)) {
|
||||
log_error("[Editor] could not read from %s: %s", filename, PROF_GERROR_MESSAGE(glib_error));
|
||||
return TRUE;
|
||||
}
|
||||
/* Remove all trailing new-line characters */
|
||||
g_strchomp(contents);
|
||||
*returned_message = contents;
|
||||
if (remove(filename) != 0) {
|
||||
log_error("[Editor] error during file deletion of %s", filename);
|
||||
} else {
|
||||
log_debug("[Editor] deleted file: %s", filename);
|
||||
}
|
||||
ui_suspend();
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
log_error("[Editor] Failed to fork: %s", strerror(errno));
|
||||
ui_resume();
|
||||
ui_resize();
|
||||
cons_show_error("Failed to start editor: %s", strerror(errno));
|
||||
g_strfreev(editor_argv);
|
||||
g_free(ctx->filename);
|
||||
g_free(ctx);
|
||||
return TRUE;
|
||||
} else if (pid == 0) {
|
||||
// Child process: Inherits TTY from parent
|
||||
execvp(editor_argv[0], editor_argv);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Parent process: Watch the child asynchronously
|
||||
g_child_watch_add((GPid)pid, _editor_exit_cb, ctx);
|
||||
g_strfreev(editor_argv);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
gboolean get_message_from_editor(gchar* message, gchar** returned_message);
|
||||
gboolean launch_editor(gchar* initial_content, void (*callback)(gchar* content, void* data), void* user_data);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -120,6 +120,11 @@ ui_sigwinch_handler(int sig)
|
||||
void
|
||||
ui_update(void)
|
||||
{
|
||||
// UI is suspended
|
||||
if (isendwin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProfWin* current = wins_get_current();
|
||||
if (current->layout->paged == 0) {
|
||||
win_move_to_end(current);
|
||||
@@ -186,6 +191,11 @@ ui_resume(void)
|
||||
void
|
||||
ui_resize(void)
|
||||
{
|
||||
// UI is suspended
|
||||
if (isendwin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct winsize w;
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
erase();
|
||||
@@ -204,6 +214,11 @@ ui_resize(void)
|
||||
void
|
||||
ui_redraw(void)
|
||||
{
|
||||
// UI is suspended
|
||||
if (isendwin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
title_bar_resize();
|
||||
wins_resize_all();
|
||||
status_bar_resize();
|
||||
|
||||
@@ -171,6 +171,12 @@ _inp_slashguard_check(void)
|
||||
char*
|
||||
inp_readline(void)
|
||||
{
|
||||
// UI is suspended
|
||||
if (isendwin()) {
|
||||
g_usleep(100000); // 100ms
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p_rl_timeout.tv_sec = inp_timeout / 1000;
|
||||
p_rl_timeout.tv_usec = inp_timeout % 1000 * 1000;
|
||||
FD_ZERO(&fds);
|
||||
@@ -996,6 +1002,16 @@ _inp_rl_down_arrow_handler(int count, int key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_editor_finished_cb(gchar* message, void* user_data)
|
||||
{
|
||||
if (message) {
|
||||
rl_replace_line(message, 0);
|
||||
rl_point = rl_end;
|
||||
rl_forced_update_display();
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_inp_rl_send_to_editor(int count, int key)
|
||||
{
|
||||
@@ -1003,16 +1019,7 @@ _inp_rl_send_to_editor(int count, int key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto_gchar gchar* message = NULL;
|
||||
|
||||
if (get_message_from_editor(rl_line_buffer, &message)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rl_replace_line(message, 0);
|
||||
ui_resize();
|
||||
rl_point = rl_end;
|
||||
rl_forced_update_display();
|
||||
launch_editor(rl_line_buffer, _editor_finished_cb, NULL);
|
||||
|
||||
return 0;
|
||||
|
jabber.developer marked this conversation as resolved
Outdated
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user
note: we should also clean it up its definition later
Done — switched to
auto_gchar(4401e817d).I mean
get_message_from_editor_asyncfunction is rendered obsolete by new editor function from upsteam.Removed