summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd-choose-buffer.c4
-rw-r--r--cmd-list-buffers.c2
-rw-r--r--format.c10
-rw-r--r--paste.c23
-rw-r--r--tmux.12
-rw-r--r--tmux.h7
-rw-r--r--utf8.c43
7 files changed, 70 insertions, 21 deletions
diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c
index 359de068..1e0edaa6 100644
--- a/cmd-choose-buffer.c
+++ b/cmd-choose-buffer.c
@@ -49,6 +49,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
char *action, *action_data;
const char *template;
u_int idx;
+ int utf8flag;
if ((c = cmd_current_client(cmdq)) == NULL) {
cmdq_error(cmdq, "no client available");
@@ -60,6 +61,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
+ utf8flag = options_get_number(&wl->window->options, "utf8");
if (paste_get_top(&global_buffers) == NULL)
return (CMD_RETURN_NORMAL);
@@ -79,7 +81,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
cdata->ft_template = xstrdup(template);
format_add(cdata->ft, "line", "%u", idx - 1);
- format_paste_buffer(cdata->ft, pb);
+ format_paste_buffer(cdata->ft, pb, utf8flag);
xasprintf(&action_data, "%u", idx - 1);
cdata->command = cmd_template_replace(action, action_data, 1);
diff --git a/cmd-list-buffers.c b/cmd-list-buffers.c
index e36a7cd0..7051eae8 100644
--- a/cmd-list-buffers.c
+++ b/cmd-list-buffers.c
@@ -55,7 +55,7 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq)
while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
ft = format_create();
format_add(ft, "line", "%u", idx - 1);
- format_paste_buffer(ft, pb);
+ format_paste_buffer(ft, pb, 0);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);
diff --git a/format.c b/format.c
index 1dca6011..5fc76b2b 100644
--- a/format.c
+++ b/format.c
@@ -601,12 +601,14 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
/* Set default format keys for paste buffer. */
void
-format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
+format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb,
+ int utf8flag)
{
- char *pb_print = paste_print(pb, 50);
+ char *s;
format_add(ft, "buffer_size", "%zu", pb->size);
- format_add(ft, "buffer_sample", "%s", pb_print);
- free(pb_print);
+ s = paste_make_sample(pb, utf8flag);
+ format_add(ft, "buffer_sample", "%s", s);
+ free(s);
}
diff --git a/paste.c b/paste.c
index 4ec87f35..98d71a07 100644
--- a/paste.c
+++ b/paste.c
@@ -148,25 +148,26 @@ paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size)
return (0);
}
-/* Convert a buffer into a visible string. */
+/* Convert start of buffer into a nice string. */
char *
-paste_print(struct paste_buffer *pb, size_t width)
+paste_make_sample(struct paste_buffer *pb, int utf8flag)
{
- char *buf;
- size_t len, used;
-
- if (width < 3)
- width = 3;
- buf = xmalloc(width * 4 + 1);
+ char *buf;
+ size_t len, used;
+ const int flags = VIS_OCTAL|VIS_TAB|VIS_NL;
+ const size_t width = 200;
len = pb->size;
if (len > width)
len = width;
+ buf = xmalloc(len * 4 + 4);
- used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
+ if (utf8flag)
+ used = utf8_strvis(buf, pb->data, len, flags);
+ else
+ used = strvisx(buf, pb->data, len, flags);
if (pb->size > width || used > width)
- strlcpy(buf + width - 3, "...", 4);
-
+ strlcpy(buf + width, "...", 4);
return (buf);
}
diff --git a/tmux.1 b/tmux.1
index eb0be916..8205e026 100644
--- a/tmux.1
+++ b/tmux.1
@@ -3087,7 +3087,7 @@ The following variables are available, where appropriate:
.It Li "alternate_on" Ta "" Ta "If pane is in alternate screen"
.It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen"
.It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen"
-.It Li "buffer_sample" Ta "" Ta "First 50 characters from buffer"
+.It Li "buffer_sample" Ta "" Ta "Sample of start of buffer"
.It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes"
.It Li "client_activity" Ta "" Ta "Integer time client last had activity"
.It Li "client_activity_string" Ta "" Ta "String time client last had activity"
diff --git a/tmux.h b/tmux.h
index 6b35e175..7e541458 100644
--- a/tmux.h
+++ b/tmux.h
@@ -85,7 +85,7 @@ extern char **environ;
/* Default template for choose-buffer. */
#define CHOOSE_BUFFER_TEMPLATE \
- "#{line}: #{buffer_size} bytes: \"#{buffer_sample}\""
+ "#{line}: #{buffer_size} bytes: #{buffer_sample}"
/* Default template for choose-client. */
#define CHOOSE_CLIENT_TEMPLATE \
@@ -1544,7 +1544,7 @@ void format_winlink(struct format_tree *, struct session *,
void format_window_pane(struct format_tree *,
struct window_pane *);
void format_paste_buffer(struct format_tree *,
- struct paste_buffer *);
+ struct paste_buffer *, int);
/* mode-key.c */
extern const struct mode_key_table mode_key_tables[];
@@ -1714,7 +1714,7 @@ int paste_free_top(struct paste_stack *);
int paste_free_index(struct paste_stack *, u_int);
void paste_add(struct paste_stack *, char *, size_t, u_int);
int paste_replace(struct paste_stack *, u_int, char *, size_t);
-char *paste_print(struct paste_buffer *, size_t);
+char *paste_make_sample(struct paste_buffer *, int);
void paste_send_pane(struct paste_buffer *, struct window_pane *,
const char *, int);
@@ -2326,6 +2326,7 @@ int utf8_open(struct utf8_data *, u_char);
int utf8_append(struct utf8_data *, u_char);
u_int utf8_combine(const struct utf8_data *);
u_int utf8_split2(u_int, u_char *);
+int utf8_strvis(char *, const char *, size_t, int);
/* procname.c */
char *get_proc_name(int, char *);
diff --git a/utf8.c b/utf8.c
index 85889dcb..082683e8 100644
--- a/utf8.c
+++ b/utf8.c
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <string.h>
+#include <vis.h>
#include "tmux.h"
@@ -350,3 +351,45 @@ utf8_width(const struct utf8_data *utf8data)
}
return (1);
}
+
+/*
+ * Encode len characters from src into dst, which is guaranteed to have four
+ * bytes available for each character from src (for \abc or UTF-8) plus space
+ * for \0.
+ */
+int
+utf8_strvis(char *dst, const char *src, size_t len, int flag)
+{
+ struct utf8_data utf8data;
+ const char *start, *end;
+ int more;
+ size_t i;
+
+ start = dst;
+ end = src + len;
+
+ while (src < end) {
+ if (utf8_open(&utf8data, *src)) {
+ more = 1;
+ while (++src < end && more)
+ more = utf8_append(&utf8data, *src);
+ if (!more) {
+ /* UTF-8 character finished. */
+ for (i = 0; i < utf8data.size; i++)
+ *dst++ = utf8data.data[i];
+ continue;
+ } else if (utf8data.have > 0) {
+ /* Not a complete UTF-8 character. */
+ src -= utf8data.have;
+ }
+ }
+ if (src < end - 1)
+ dst = vis(dst, src[0], flag, src[1]);
+ else if (src < end)
+ dst = vis(dst, src[0], flag, '\0');
+ src++;
+ }
+
+ *dst = '\0';
+ return (dst - start);
+}