=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/format.c,v retrieving revision 1.196 retrieving revision 1.197 diff -u -r1.196 -r1.197 --- src/usr.bin/tmux/format.c 2019/05/26 12:02:42 1.196 +++ src/usr.bin/tmux/format.c 2019/05/26 17:34:45 1.197 @@ -1,4 +1,4 @@ -/* $OpenBSD: format.c,v 1.196 2019/05/26 12:02:42 nicm Exp $ */ +/* $OpenBSD: format.c,v 1.197 2019/05/26 17:34:45 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -84,6 +84,12 @@ "New After,w,new-window -a|" \ "New At End,W,new-window" #define DEFAULT_PANE_MENU \ + "#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},},,copy-mode -t=; send -Xt= search-backward \"#{q:mouse_word}\"|" \ + "#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},},,send-keys -l \"#{q:mouse_word}\"|" \ + "|" \ + "#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},},c,set-buffer \"#{q:mouse_word}\"|" \ + "#{?mouse_line,Copy Line,},l,set-buffer \"#{q:mouse_line}\"|" \ + "|" \ "Horizontal Split,h,split-window -h|" \ "Vertical Split,v,split-window -v|" \ "|" \ @@ -170,6 +176,8 @@ time_t time; u_int loop; + struct mouse_event m; + RB_HEAD(format_entry_tree, format_entry) tree; }; static int format_entry_cmp(struct format_entry *, struct format_entry *); @@ -743,6 +751,121 @@ xasprintf(&fe->value, "%.*s", (int)gc.data.size, gc.data.data); } +/* Callback for mouse_word. */ +static void +format_cb_mouse_word(struct format_tree *ft, struct format_entry *fe) +{ + struct window_pane *wp; + u_int x, y, end; + struct grid *gd; + struct grid_line *gl; + struct grid_cell gc; + const char *ws; + struct utf8_data *ud = NULL; + size_t size = 0; + int found = 0; + + if (!ft->m.valid) + return; + wp = cmd_mouse_pane(&ft->m, NULL, NULL); + if (wp == NULL) + return; + if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0) + return; + gd = wp->base.grid; + ws = options_get_string(global_s_options, "word-separators"); + + y = gd->hsize + y; + for (;;) { + grid_get_cell(gd, x, y, &gc); + if (gc.flags & GRID_FLAG_PADDING) + break; + if (utf8_cstrhas(ws, &gc.data)) { + found = 1; + break; + } + + if (x == 0) { + if (y == 0) + break; + gl = &gd->linedata[y - 1]; + if (~gl->flags & GRID_LINE_WRAPPED) + break; + y--; + x = grid_line_length(gd, y); + if (x == 0) + break; + } + x--; + } + for (;;) { + if (found) { + end = grid_line_length(gd, y); + if (end == 0 || x == end - 1) { + if (y == gd->hsize + gd->sy - 1) + break; + gl = &gd->linedata[y]; + if (~gl->flags & GRID_LINE_WRAPPED) + break; + y++; + x = 0; + } else + x++; + } + found = 1; + + grid_get_cell(gd, x, y, &gc); + if (gc.flags & GRID_FLAG_PADDING) + break; + if (utf8_cstrhas(ws, &gc.data)) + break; + + ud = xreallocarray(ud, size + 2, sizeof *ud); + memcpy(&ud[size++], &gc.data, sizeof *ud); + } + if (size != 0) { + ud[size].size = 0; + fe->value = utf8_tocstr(ud); + free(ud); + } +} + +/* Callback for mouse_line. */ +static void +format_cb_mouse_line(struct format_tree *ft, struct format_entry *fe) +{ + struct window_pane *wp; + u_int x, y; + struct grid *gd; + struct grid_cell gc; + struct utf8_data *ud = NULL; + size_t size = 0; + + if (!ft->m.valid) + return; + wp = cmd_mouse_pane(&ft->m, NULL, NULL); + if (wp == NULL) + return; + if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0) + return; + gd = wp->base.grid; + + y = gd->hsize + y; + for (x = 0; x < grid_line_length(gd, y); x++) { + grid_get_cell(gd, x, y, &gc); + if (gc.flags & GRID_FLAG_PADDING) + break; + + ud = xreallocarray(ud, size + 2, sizeof *ud); + memcpy(&ud[size++], &gc.data, sizeof *ud); + } + if (size != 0) { + ud[size].size = 0; + fe->value = utf8_tocstr(ud); + free(ud); + } +} + /* Merge a format tree. */ static void format_merge(struct format_tree *ft, struct format_tree *from) @@ -759,10 +882,29 @@ static void format_create_add_item(struct format_tree *ft, struct cmdq_item *item) { + struct mouse_event *m; + struct window_pane *wp; + u_int x, y; + if (item->cmd != NULL) format_add(ft, "command", "%s", item->cmd->entry->name); - if (item->shared != NULL && item->shared->formats != NULL) + + if (item->shared == NULL) + return; + if (item->shared->formats != NULL) format_merge(ft, item->shared->formats); + + m = &item->shared->mouse; + if (m->valid && ((wp = cmd_mouse_pane(m, NULL, NULL)) != NULL)) { + format_add(ft, "mouse_pane", "%%%u", wp->id); + if (cmd_mouse_at(wp, m, &x, &y, 0) == 0) { + format_add(ft, "mouse_x", "%u", x); + format_add(ft, "mouse_y", "%u", y); + format_add_cb(ft, "mouse_word", format_cb_mouse_word); + format_add_cb(ft, "mouse_line", format_cb_mouse_line); + } + } + memcpy(&ft->m, m, sizeof ft->m); } /* Create a new tree. */