Coverage Report

Created: 2026-07-16 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tmux/window-buffer.c
Line
Count
Source
1
/* $OpenBSD: window-buffer.c,v 1.51 2026/07/15 12:45:39 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
21
#include <stdio.h>
22
#include <ctype.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <time.h>
26
#include <unistd.h>
27
28
#include "tmux.h"
29
30
static struct screen  *window_buffer_init(struct window_mode_entry *,
31
           struct cmdq_item *, struct cmd_find_state *,
32
           struct args *);
33
static void    window_buffer_free(struct window_mode_entry *);
34
static void    window_buffer_resize(struct window_mode_entry *, u_int,
35
           u_int);
36
static void    window_buffer_update(struct window_mode_entry *);
37
static void    window_buffer_key(struct window_mode_entry *,
38
           struct client *, struct session *,
39
           struct winlink *, key_code, struct mouse_event *);
40
41
0
#define WINDOW_BUFFER_DEFAULT_COMMAND "paste-buffer -p -b '%%'"
42
43
#define WINDOW_BUFFER_DEFAULT_FORMAT \
44
0
  "#{t/p:buffer_created}: #{buffer_sample}"
45
46
#define WINDOW_BUFFER_DEFAULT_KEY_FORMAT \
47
0
  "#{?#{e|<:#{line},10}," \
48
0
    "#{line}" \
49
0
  ",#{e|<:#{line},36}," \
50
0
    "M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \
51
0
  "}"
52
53
static const struct menu_item window_buffer_menu_items[] = {
54
  { "Paste", 'p', NULL },
55
  { "Paste Tagged", 'P', NULL },
56
  { "", KEYC_NONE, NULL },
57
  { "Tag", 't', NULL },
58
  { "Tag All", '\024', NULL },
59
  { "Tag None", 'T', NULL },
60
  { "", KEYC_NONE, NULL },
61
  { "Delete", 'd', NULL },
62
  { "Delete Tagged", 'D', NULL },
63
  { "", KEYC_NONE, NULL },
64
  { "Cancel", 'q', NULL },
65
66
  { NULL, KEYC_NONE, NULL }
67
};
68
69
const struct window_mode window_buffer_mode = {
70
  .name = "buffer-mode",
71
  .default_format = WINDOW_BUFFER_DEFAULT_FORMAT,
72
73
  .init = window_buffer_init,
74
  .free = window_buffer_free,
75
  .resize = window_buffer_resize,
76
  .update = window_buffer_update,
77
  .key = window_buffer_key,
78
};
79
80
struct window_buffer_itemdata {
81
  const char  *name;
82
  u_int    order;
83
  size_t     size;
84
};
85
86
struct window_buffer_modedata {
87
  struct window_pane     *wp;
88
  struct cmd_find_state     fs;
89
90
  struct mode_tree_data    *data;
91
  struct spawn_editor_state  *editor;
92
  struct window_buffer_editdata  *edit;
93
  char         *command;
94
  char         *format;
95
  char         *key_format;
96
97
  struct window_buffer_itemdata **item_list;
98
  u_int         item_size;
99
};
100
101
struct window_buffer_editdata {
102
  u_int      wp_id;
103
  char      *name;
104
  struct paste_buffer *pb;
105
  struct spawn_editor_state *editor;
106
};
107
108
static void window_buffer_finish_edit(struct window_buffer_editdata *);
109
static void window_buffer_draw_waiting(struct window_buffer_modedata *);
110
111
static enum sort_order window_buffer_order_seq[] = {
112
  SORT_CREATION,
113
  SORT_NAME,
114
  SORT_SIZE,
115
  SORT_END,
116
};
117
118
static struct window_buffer_itemdata *
119
window_buffer_add_item(struct window_buffer_modedata *data)
120
0
{
121
0
  struct window_buffer_itemdata *item;
122
123
0
  data->item_list = xreallocarray(data->item_list, data->item_size + 1,
124
0
      sizeof *data->item_list);
125
0
  item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
126
0
  return (item);
127
0
}
128
129
static void
130
window_buffer_free_item(struct window_buffer_itemdata *item)
131
0
{
132
0
  free((void *)item->name);
133
0
  free(item);
134
0
}
135
136
static void
137
window_buffer_build(void *modedata, struct sort_criteria *sort_crit,
138
    __unused uint64_t *tag, const char *filter)
139
0
{
140
0
  struct window_buffer_modedata *data = modedata;
141
0
  struct window_buffer_itemdata *item;
142
0
  u_int        i, n;
143
0
  struct paste_buffer   *pb, **l;
144
0
  char        *text, *cp;
145
0
  struct format_tree    *ft;
146
0
  struct session      *s = NULL;
147
0
  struct winlink      *wl = NULL;
148
0
  struct window_pane    *wp = NULL;
149
150
0
  for (i = 0; i < data->item_size; i++)
151
0
    window_buffer_free_item(data->item_list[i]);
152
0
  free(data->item_list);
153
0
  data->item_list = NULL;
154
0
  data->item_size = 0;
155
156
0
  l = sort_get_buffers(&n, sort_crit);
157
0
  for (i = 0; i < n; i++) {
158
0
    item = window_buffer_add_item(data);
159
0
    item->name = xstrdup(paste_buffer_name(l[i]));
160
0
    paste_buffer_data(l[i], &item->size);
161
0
    item->order = paste_buffer_order(l[i]);
162
0
  }
163
164
0
  if (cmd_find_valid_state(&data->fs)) {
165
0
    s = data->fs.s;
166
0
    wl = data->fs.wl;
167
0
    wp = data->fs.wp;
168
0
  }
169
170
0
  for (i = 0; i < data->item_size; i++) {
171
0
    item = data->item_list[i];
172
173
0
    pb = paste_get_name(item->name);
174
0
    if (pb == NULL)
175
0
      continue;
176
0
    ft = format_create(NULL, NULL, FORMAT_NONE, 0);
177
0
    format_defaults(ft, NULL, s, wl, wp);
178
0
    format_defaults_paste_buffer(ft, pb);
179
180
0
    if (filter != NULL) {
181
0
      cp = format_expand(ft, filter);
182
0
      if (!format_true(cp)) {
183
0
        free(cp);
184
0
        format_free(ft);
185
0
        continue;
186
0
      }
187
0
      free(cp);
188
0
    }
189
190
0
    text = format_expand(ft, data->format);
191
0
    mode_tree_add(data->data, NULL, item, item->order, item->name,
192
0
        text, -1);
193
0
    free(text);
194
195
0
    format_free(ft);
196
0
  }
197
0
}
198
199
static void
200
window_buffer_draw(__unused void *modedata, void *itemdata,
201
    struct screen_write_ctx *ctx, u_int sx, u_int sy)
202
0
{
203
0
  struct window_buffer_itemdata *item = itemdata;
204
0
  struct paste_buffer   *pb;
205
0
  const char      *pdata, *start, *end;
206
0
  char        *buf = NULL;
207
0
  size_t         psize;
208
0
  u_int        i, cx = ctx->s->cx, cy = ctx->s->cy;
209
210
0
  pb = paste_get_name(item->name);
211
0
  if (pb == NULL)
212
0
    return;
213
214
0
  pdata = end = paste_buffer_data(pb, &psize);
215
0
  for (i = 0; i < sy; i++) {
216
0
    start = end;
217
0
    while (end != pdata + psize && *end != '\n')
218
0
      end++;
219
0
    buf = xreallocarray(buf, 4, end - start + 1);
220
0
    utf8_strvis(buf, start, end - start,
221
0
        VIS_OCTAL|VIS_CSTYLE|VIS_TAB);
222
0
    if (*buf != '\0') {
223
0
      screen_write_cursormove(ctx, cx, cy + i, 0);
224
0
      screen_write_nputs(ctx, sx, &grid_default_cell, "%s",
225
0
          buf);
226
0
    }
227
228
0
    if (end == pdata + psize)
229
0
      break;
230
0
    end++;
231
0
  }
232
0
  free(buf);
233
0
}
234
235
static int
236
window_buffer_find(const void *data, size_t datalen, const void *find,
237
    size_t findlen, int icase)
238
0
{
239
0
  const u_char  *udata = data, *ufind = find;
240
0
  size_t     i, j;
241
242
0
  if (findlen == 0 || datalen < findlen)
243
0
    return (0);
244
0
  for (i = 0; i + findlen <= datalen; i++) {
245
0
    for (j = 0; j < findlen; j++) {
246
0
      if (!icase && udata[i + j] != ufind[j])
247
0
        break;
248
0
      if (icase && tolower(udata[i + j]) != tolower(ufind[j]))
249
0
        break;
250
0
    }
251
0
    if (j == findlen)
252
0
      return (1);
253
0
  }
254
0
  return (0);
255
0
}
256
257
static int
258
window_buffer_search(__unused void *modedata, void *itemdata, const char *ss,
259
    int icase)
260
0
{
261
0
  struct window_buffer_itemdata *item = itemdata;
262
0
  struct paste_buffer   *pb;
263
0
  const char      *bufdata;
264
0
  size_t         bufsize;
265
266
0
  if ((pb = paste_get_name(item->name)) == NULL)
267
0
    return (0);
268
0
  if (icase) {
269
0
    if (strcasestr(item->name, ss) != NULL)
270
0
      return (1);
271
0
    bufdata = paste_buffer_data(pb, &bufsize);
272
0
    return (window_buffer_find(bufdata, bufsize, ss, strlen(ss),
273
0
        icase));
274
0
  } else {
275
0
    if (strstr(item->name, ss) != NULL)
276
0
      return (1);
277
0
    bufdata = paste_buffer_data(pb, &bufsize);
278
0
    return (window_buffer_find(bufdata, bufsize, ss, strlen(ss),
279
0
        icase));
280
0
  }
281
0
}
282
283
static void
284
window_buffer_menu(void *modedata, struct client *c, key_code key)
285
0
{
286
0
  struct window_buffer_modedata *data = modedata;
287
0
  struct window_pane    *wp = data->wp;
288
0
  struct window_mode_entry  *wme;
289
290
0
  wme = TAILQ_FIRST(&wp->modes);
291
0
  if (wme == NULL || wme->data != modedata)
292
0
    return;
293
0
  window_buffer_key(wme, c, NULL, NULL, key, NULL);
294
0
}
295
296
static key_code
297
window_buffer_get_key(void *modedata, void *itemdata, u_int line)
298
0
{
299
0
  struct window_buffer_modedata *data = modedata;
300
0
  struct window_buffer_itemdata *item = itemdata;
301
0
  struct format_tree    *ft;
302
0
  struct session      *s = NULL;
303
0
  struct winlink      *wl = NULL;
304
0
  struct window_pane    *wp = NULL;
305
0
  struct paste_buffer   *pb;
306
0
  char        *expanded;
307
0
  key_code       key;
308
309
0
  if (cmd_find_valid_state(&data->fs)) {
310
0
    s = data->fs.s;
311
0
    wl = data->fs.wl;
312
0
    wp = data->fs.wp;
313
0
  }
314
0
  pb = paste_get_name(item->name);
315
0
  if (pb == NULL)
316
0
    return (KEYC_NONE);
317
318
0
  ft = format_create(NULL, NULL, FORMAT_NONE, 0);
319
0
  format_defaults(ft, NULL, NULL, 0, NULL);
320
0
  format_defaults(ft, NULL, s, wl, wp);
321
0
  format_defaults_paste_buffer(ft, pb);
322
0
  format_add(ft, "line", "%u", line);
323
324
0
  expanded = format_expand(ft, data->key_format);
325
0
  key = key_string_lookup_string(expanded);
326
0
  free(expanded);
327
0
  format_free(ft);
328
0
  return (key);
329
0
}
330
331
static void
332
window_buffer_sort(struct sort_criteria *sort_crit)
333
0
{
334
0
  sort_crit->order_seq = window_buffer_order_seq;
335
0
  if (sort_crit->order == SORT_END)
336
0
    sort_crit->order = sort_crit->order_seq[0];
337
0
}
338
339
static const char* window_buffer_help_lines[] = {
340
  "#[fg=themelightgrey]"
341
  "      Enter #[#{E:tree-mode-border-style},acs]x#[default] Paste selected %1",
342
  "#[fg=themelightgrey]"
343
  "          p #[#{E:tree-mode-border-style},acs]x#[default] Paste selected %1",
344
  "#[fg=themelightgrey]"
345
  "          P #[#{E:tree-mode-border-style},acs]x#[default] Paste tagged %1s",
346
  "#[fg=themelightgrey]"
347
  "          d #[#{E:tree-mode-border-style},acs]x#[default] Delete selected %1",
348
  "#[fg=themelightgrey]"
349
  "          D #[#{E:tree-mode-border-style},acs]x#[default] Delete tagged %1s",
350
  "#[fg=themelightgrey]"
351
  "          e #[#{E:tree-mode-border-style},acs]x#[default] Open %1 in editor",
352
  "#[fg=themelightgrey]"
353
  "          f #[#{E:tree-mode-border-style},acs]x#[default] Enter a filter",
354
  NULL
355
};
356
357
static const char**
358
window_buffer_help(u_int *width, const char **item)
359
0
{
360
0
  *width = 0;
361
0
  *item = "buffer";
362
0
  return (window_buffer_help_lines);
363
0
}
364
365
static struct screen *
366
window_buffer_init(struct window_mode_entry *wme,
367
    __unused struct cmdq_item *item, struct cmd_find_state *fs,
368
    struct args *args)
369
0
{
370
0
  struct window_pane    *wp = wme->wp;
371
0
  struct window_buffer_modedata *data;
372
0
  struct screen     *s;
373
374
0
  wme->data = data = xcalloc(1, sizeof *data);
375
0
  data->wp = wp;
376
0
  cmd_find_copy_state(&data->fs, fs);
377
378
0
  if (args == NULL || !args_has(args, 'F'))
379
0
    data->format = xstrdup(WINDOW_BUFFER_DEFAULT_FORMAT);
380
0
  else
381
0
    data->format = xstrdup(args_get(args, 'F'));
382
0
  if (args == NULL || !args_has(args, 'K'))
383
0
    data->key_format = xstrdup(WINDOW_BUFFER_DEFAULT_KEY_FORMAT);
384
0
  else
385
0
    data->key_format = xstrdup(args_get(args, 'K'));
386
0
  if (args == NULL || args_count(args) == 0)
387
0
    data->command = xstrdup(WINDOW_BUFFER_DEFAULT_COMMAND);
388
0
  else
389
0
    data->command = xstrdup(args_string(args, 0));
390
391
0
  data->data = mode_tree_start(wp, args, window_buffer_build,
392
0
      window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
393
0
      window_buffer_get_key, NULL, window_buffer_sort, window_buffer_help,
394
0
      data, window_buffer_menu_items, &s);
395
0
  mode_tree_zoom(data->data, args);
396
397
0
  mode_tree_build(data->data);
398
0
  mode_tree_draw(data->data);
399
400
0
  return (s);
401
0
}
402
403
static void
404
window_buffer_free(struct window_mode_entry *wme)
405
0
{
406
0
  struct window_buffer_modedata *data = wme->data;
407
0
  u_int        i;
408
409
0
  if (data == NULL)
410
0
    return;
411
412
0
  if (data->editor != NULL) {
413
0
    spawn_cancel_editor(data->editor);
414
0
    window_buffer_finish_edit(data->edit);
415
0
  }
416
417
0
  mode_tree_free(data->data);
418
419
0
  for (i = 0; i < data->item_size; i++)
420
0
    window_buffer_free_item(data->item_list[i]);
421
0
  free(data->item_list);
422
423
0
  free(data->format);
424
0
  free(data->key_format);
425
0
  free(data->command);
426
427
0
  free(data);
428
0
}
429
430
static void
431
window_buffer_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
432
0
{
433
0
  struct window_buffer_modedata *data = wme->data;
434
435
0
  mode_tree_resize(data->data, sx, sy);
436
0
}
437
438
static void
439
window_buffer_update(struct window_mode_entry *wme)
440
0
{
441
0
  struct window_buffer_modedata *data = wme->data;
442
443
0
  mode_tree_build(data->data);
444
0
  mode_tree_draw(data->data);
445
0
  window_buffer_draw_waiting(data);
446
0
  data->wp->flags |= PANE_REDRAW;
447
0
}
448
449
static void
450
window_buffer_do_delete(void *modedata, void *itemdata,
451
    __unused struct client *c, __unused key_code key)
452
0
{
453
0
  struct window_buffer_modedata *data = modedata;
454
0
  struct window_buffer_itemdata *item = itemdata;
455
0
  struct paste_buffer   *pb;
456
457
0
  if (item == mode_tree_get_current(data->data) &&
458
0
      !mode_tree_down(data->data, 0)) {
459
    /*
460
     *If we were unable to select the item further down we are at
461
     * the end of the list. Move one element up instead, to make
462
     * sure that we preserve a valid selection or we risk having
463
     * the tree build logic reset it to the first item.
464
     */
465
0
    mode_tree_up(data->data, 0);
466
0
  }
467
468
0
  if ((pb = paste_get_name(item->name)) != NULL)
469
0
    paste_free(pb);
470
0
}
471
472
static void
473
window_buffer_do_paste(void *modedata, void *itemdata, struct client *c,
474
    __unused key_code key)
475
0
{
476
0
  struct window_buffer_modedata *data = modedata;
477
0
  struct window_buffer_itemdata *item = itemdata;
478
479
0
  if (paste_get_name(item->name) != NULL)
480
0
    mode_tree_run_command(c, NULL, data->command, item->name);
481
0
}
482
483
static void
484
window_buffer_finish_edit(struct window_buffer_editdata *ed)
485
0
{
486
0
  free(ed->name);
487
0
  free(ed);
488
0
}
489
490
static void
491
window_buffer_draw_waiting(struct window_buffer_modedata *data)
492
0
{
493
0
  struct screen_write_ctx  ctx;
494
0
  struct screen   *s = data->wp->screen;
495
0
  struct grid_cell   gc;
496
0
  char       text[128];
497
0
  u_int      sx, sy, box_w, box_h, x, y, text_x;
498
0
  size_t       textlen;
499
0
  pid_t      pid;
500
501
0
  if (data->editor == NULL)
502
0
    return;
503
0
  sx = screen_size_x(s);
504
0
  sy = screen_size_y(s);
505
0
  if (sx == 0 || sy == 0)
506
0
    return;
507
508
0
  pid = spawn_get_editor_pid(data->editor);
509
0
  if (pid == -1)
510
0
    xsnprintf(text, sizeof text, "WAITING FOR EDITOR");
511
0
  else
512
0
    xsnprintf(text, sizeof text, "WAITING FOR EDITOR (PID %ld)",
513
0
        (long)pid);
514
515
0
  textlen = strlen(text);
516
0
  box_w = textlen + 4;
517
0
  box_h = 3;
518
0
  if (sx < box_w || sy < box_h)
519
0
    return;
520
0
  x = (sx - box_w) / 2;
521
0
  y = (sy - box_h) / 2;
522
0
  text_x = x + (box_w - textlen) / 2;
523
524
0
  memcpy(&gc, &grid_default_cell, sizeof gc);
525
0
  screen_write_start(&ctx, s);
526
0
  screen_write_cursormove(&ctx, x, y, 0);
527
0
  screen_write_box(&ctx, box_w, box_h, BOX_LINES_DEFAULT, &gc, NULL);
528
0
  screen_write_cursormove(&ctx, x + 1, y + 1, 0);
529
0
  screen_write_clearcharacter(&ctx, box_w - 2, gc.bg);
530
0
  screen_write_cursormove(&ctx, text_x, y + 1, 0);
531
0
  screen_write_nputs(&ctx, box_w - 2, &gc, "%s", text);
532
0
  screen_write_stop(&ctx);
533
0
}
534
535
static void
536
window_buffer_edit_close_cb(char *buf, size_t len, void *arg)
537
0
{
538
0
  struct window_buffer_editdata *ed = arg;
539
0
  size_t         oldlen;
540
0
  const char      *oldbuf;
541
0
  struct paste_buffer   *pb;
542
0
  struct window_pane    *wp;
543
0
  struct window_buffer_modedata *data;
544
0
  struct window_mode_entry  *wme;
545
546
0
  wp = window_pane_find_by_id(ed->wp_id);
547
0
  if (wp != NULL) {
548
0
    wme = TAILQ_FIRST(&wp->modes);
549
0
    if (wme != NULL && wme->mode == &window_buffer_mode) {
550
0
      data = wme->data;
551
0
      if (data->editor == ed->editor) {
552
0
        data->editor = NULL;
553
0
        data->edit = NULL;
554
0
      }
555
0
    }
556
0
  }
557
558
0
  if (buf == NULL || len == 0) {
559
0
    window_buffer_finish_edit(ed);
560
0
    return;
561
0
  }
562
563
0
  pb = paste_get_name(ed->name);
564
0
  if (pb == NULL || pb != ed->pb) {
565
0
    window_buffer_finish_edit(ed);
566
0
    return;
567
0
  }
568
569
0
  oldbuf = paste_buffer_data(pb, &oldlen);
570
0
  if (oldlen != '\0' &&
571
0
      oldbuf[oldlen - 1] != '\n' &&
572
0
      buf[len - 1] == '\n')
573
0
    len--;
574
0
  if (len != 0)
575
0
    paste_replace(pb, buf, len);
576
577
0
  wp = window_pane_find_by_id(ed->wp_id);
578
0
  if (wp != NULL) {
579
0
    wme = TAILQ_FIRST(&wp->modes);
580
0
    if (wme != NULL && wme->mode == &window_buffer_mode) {
581
0
      data = wme->data;
582
0
      mode_tree_build(data->data);
583
0
      mode_tree_draw(data->data);
584
0
      window_buffer_draw_waiting(data);
585
0
    }
586
0
    wp->flags |= PANE_REDRAW;
587
0
  }
588
0
  window_buffer_finish_edit(ed);
589
0
}
590
591
static void
592
window_buffer_start_edit(struct window_buffer_modedata *data,
593
    struct window_buffer_itemdata *item, struct client *c)
594
0
{
595
0
  struct paste_buffer   *pb;
596
0
  const char      *buf;
597
0
  size_t         len;
598
0
  struct window_buffer_editdata *ed;
599
600
0
  if (data->editor != NULL)
601
0
    return;
602
0
  if ((pb = paste_get_name(item->name)) == NULL)
603
0
    return;
604
0
  buf = paste_buffer_data(pb, &len);
605
606
0
  ed = xcalloc(1, sizeof *ed);
607
0
  ed->wp_id = data->wp->id;
608
0
  ed->name = xstrdup(paste_buffer_name(pb));
609
0
  ed->pb = pb;
610
611
0
  ed->editor = spawn_editor(c, buf, len, window_buffer_edit_close_cb, ed);
612
0
  if (ed->editor == NULL)
613
0
    window_buffer_finish_edit(ed);
614
0
  else {
615
0
    data->editor = ed->editor;
616
0
    data->edit = ed;
617
0
  }
618
0
}
619
620
static void
621
window_buffer_key(struct window_mode_entry *wme, struct client *c,
622
    __unused struct session *s, __unused struct winlink *wl, key_code key,
623
    struct mouse_event *m)
624
0
{
625
0
  struct window_pane    *wp = wme->wp;
626
0
  struct window_buffer_modedata *data = wme->data;
627
0
  struct mode_tree_data   *mtd = data->data;
628
0
  struct window_buffer_itemdata *item;
629
0
  int        finished;
630
631
0
  if (paste_is_empty()) {
632
0
    finished = 1;
633
0
    goto out;
634
0
  }
635
0
  if (data->editor != NULL) {
636
0
    if (key == 'q' || key == '\033' || key == '\003')
637
0
      finished = 1;
638
0
    else
639
0
      finished = 0;
640
0
    goto out;
641
0
  }
642
643
0
  finished = mode_tree_key(mtd, c, &key, m, NULL, NULL);
644
0
  switch (key) {
645
0
  case 'e':
646
0
    item = mode_tree_get_current(mtd);
647
0
    window_buffer_start_edit(data, item, c);
648
0
    break;
649
0
  case 'd':
650
0
    item = mode_tree_get_current(mtd);
651
0
    window_buffer_do_delete(data, item, c, key);
652
0
    mode_tree_build(mtd);
653
0
    break;
654
0
  case 'D':
655
0
    mode_tree_each_tagged(mtd, window_buffer_do_delete, c, key, 0);
656
0
    mode_tree_build(mtd);
657
0
    break;
658
0
  case 'P':
659
0
    mode_tree_each_tagged(mtd, window_buffer_do_paste, c, key, 0);
660
0
    finished = 1;
661
0
    break;
662
0
  case 'p':
663
0
  case '\r':
664
0
    item = mode_tree_get_current(mtd);
665
0
    window_buffer_do_paste(data, item, c, key);
666
0
    finished = 1;
667
0
    break;
668
0
  }
669
670
0
out:
671
0
  if (finished || paste_is_empty())
672
0
    window_pane_reset_mode(wp);
673
0
  else {
674
0
    mode_tree_draw(mtd);
675
0
    window_buffer_draw_waiting(data);
676
0
    wp->flags |= PANE_REDRAW;
677
0
  }
678
0
}