=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/window-buffer.c,v retrieving revision 1.27 retrieving revision 1.28 diff -c -r1.27 -r1.28 *** src/usr.bin/tmux/window-buffer.c 2020/05/16 14:10:29 1.27 --- src/usr.bin/tmux/window-buffer.c 2020/05/16 15:24:28 1.28 *************** *** 1,4 **** ! /* $OpenBSD: window-buffer.c,v 1.27 2020/05/16 14:10:29 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: window-buffer.c,v 1.28 2020/05/16 15:24:28 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott *************** *** 18,26 **** --- 18,29 ---- #include + #include + #include #include #include #include + #include #include #include "tmux.h" *************** *** 95,100 **** --- 98,110 ---- u_int item_size; }; + struct window_buffer_editdata { + u_int wp_id; + char *path; + char *name; + struct paste_buffer *pb; + }; + static struct window_buffer_itemdata * window_buffer_add_item(struct window_buffer_modedata *data) { *************** *** 354,359 **** --- 364,489 ---- } static void + window_buffer_finish_edit(struct window_buffer_editdata *ed) + { + unlink(ed->path); + free(ed->path); + free(ed->name); + free(ed); + } + + static void + window_buffer_edit_close_cb(int status, void *arg) + { + struct window_buffer_editdata *ed = arg; + FILE *f; + off_t len; + char *buf; + size_t oldlen; + const char *oldbuf; + struct paste_buffer *pb; + struct window_pane *wp; + struct window_buffer_modedata *data; + struct window_mode_entry *wme; + + if (status != 0) { + window_buffer_finish_edit(ed); + return; + } + + pb = paste_get_name(ed->name); + if (pb == NULL || pb != ed->pb) { + window_buffer_finish_edit(ed); + return; + } + + f = fopen(ed->path, "r"); + if (f != NULL) { + fseeko(f, 0, SEEK_END); + len = ftello(f); + fseeko(f, 0, SEEK_SET); + + if (len > 0 && + (uintmax_t)len <= (uintmax_t)SIZE_MAX && + (buf = malloc(len)) != NULL && + fread(buf, len, 1, f) == 1) { + oldbuf = paste_buffer_data(pb, &oldlen); + if (oldlen != '\0' && + oldbuf[oldlen - 1] != '\n' && + buf[len - 1] == '\n') + len--; + if (len != 0) + paste_replace(pb, buf, len); + } + fclose(f); + } + + wp = window_pane_find_by_id(ed->wp_id); + if (wp != NULL) { + wme = TAILQ_FIRST(&wp->modes); + if (wme->mode == &window_buffer_mode) { + data = wme->data; + mode_tree_build(data->data); + mode_tree_draw(data->data); + } + wp->flags |= PANE_REDRAW; + } + window_buffer_finish_edit(ed); + } + + static void + window_buffer_start_edit(struct window_buffer_modedata *data, + struct window_buffer_itemdata *item, struct client *c) + { + struct paste_buffer *pb; + int fd; + FILE *f; + const char *buf; + size_t len; + struct window_buffer_editdata *ed; + char *cmd; + char path[] = _PATH_TMP "tmux.XXXXXXXX"; + const char *editor; + u_int px, py, sx, sy; + + if ((pb = paste_get_name(item->name)) == NULL) + return; + buf = paste_buffer_data(pb, &len); + + editor = options_get_string(global_options, "editor"); + if (*editor == '\0') + return; + + fd = mkstemp(path); + if (fd == -1) + return; + f = fdopen(fd, "w"); + if (fwrite(buf, len, 1, f) != 1) { + fclose(f); + return; + } + fclose(f); + + ed = xcalloc(1, sizeof *ed); + ed->wp_id = data->wp->id; + ed->path = xstrdup(path); + ed->name = xstrdup(paste_buffer_name(pb)); + ed->pb = pb; + + sx = c->tty.sx * 9 / 10; + sy = c->tty.sy * 9 / 10; + px = (c->tty.sx / 2) - (sx / 2); + py = (c->tty.sy / 2) - (sy / 2); + + xasprintf(&cmd, "%s %s", editor, path); + if (popup_display(POPUP_WRITEKEYS|POPUP_CLOSEEXIT, NULL, px, py, sx, sy, + 0, NULL, cmd, NULL, _PATH_TMP, c, NULL, window_buffer_edit_close_cb, + ed) != 0) + window_buffer_finish_edit(ed); + free(cmd); + } + + static void window_buffer_key(struct window_mode_entry *wme, struct client *c, __unused struct session *s, __unused struct winlink *wl, key_code key, struct mouse_event *m) *************** *** 366,371 **** --- 496,505 ---- finished = mode_tree_key(mtd, c, &key, m, NULL, NULL); switch (key) { + case 'e': + item = mode_tree_get_current(mtd); + window_buffer_start_edit(data, item, c); + break; case 'd': item = mode_tree_get_current(mtd); window_buffer_do_delete(data, item, c, key);