diff --git a/CHANGELOG.md b/CHANGELOG.md index 48655ebe..592ad2ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,9 @@ (https://codeberg.org/dnkl/foot/issues/270) * Combining characters not being rendered when composed with colored bitmap glyphs (i.e. colored emojis). +* Pasting URIs from the clipboard when the source has not + newline-terminated the last URI + (https://codeberg.org/dnkl/foot/issues/291). ### Security diff --git a/selection.c b/selection.c index e922db53..de8b06e7 100644 --- a/selection.c +++ b/selection.c @@ -1422,6 +1422,7 @@ struct clipboard_receive { struct itimerspec timeout; void (*decoder)(struct clipboard_receive *ctx, char *data, size_t size); + void (*finish)(struct clipboard_receive *ctx); /* URI state */ bool add_space; @@ -1479,6 +1480,42 @@ fdm_receive_decoder_plain(struct clipboard_receive *ctx, char *data, size_t size ctx->cb(data, size, ctx->user); } +static void +fdm_receive_finish_plain(struct clipboard_receive *ctx) +{ +} + +static bool +decode_one_uri(struct clipboard_receive *ctx, char *uri, size_t len) +{ + LOG_DBG("URI: \"%.*s\"", (int)len, uri); + + if (len == 0) + return false; + + char *scheme, *host, *path; + if (!uri_parse(uri, len, &scheme, NULL, NULL, &host, NULL, &path, NULL, NULL)) { + LOG_ERR("drag-and-drop: invalid URI: %.*s", (int)len, uri); + return false; + } + + if (ctx->add_space) + ctx->cb(" ", 1, ctx->user); + ctx->add_space = true; + + if (strcmp(scheme, "file") == 0 && hostname_is_localhost(host)) { + ctx->cb("'", 1, ctx->user); + ctx->cb(path, strlen(path), ctx->user); + ctx->cb("'", 1, ctx->user); + } else + ctx->cb(uri, len, ctx->user); + + free(scheme); + free(host); + free(path); + return true; +} + static void fdm_receive_decoder_uri(struct clipboard_receive *ctx, char *data, size_t size) { @@ -1495,34 +1532,8 @@ fdm_receive_decoder_uri(struct clipboard_receive *ctx, char *data, size_t size) char *end = NULL; while ((end = memchr(start, '\n', ctx->buf.idx - (start - ctx->buf.data))) != NULL) { - const size_t len = end - start; - - LOG_DBG("URI: \"%.*s\"", (int)len, start); - - char *scheme, *host, *path; - if (!uri_parse(start, len, &scheme, NULL, NULL, &host, NULL, &path, NULL, NULL)) { - LOG_ERR("drag-and-drop: invalid URI: %.*s", (int)len, start); - start = end + 1; - continue; - } - - if (ctx->add_space) - ctx->cb(" ", 1, ctx->user); - ctx->add_space = true; - - - if (strcmp(scheme, "file") == 0 && hostname_is_localhost(host)) { - ctx->cb("'", 1, ctx->user); - ctx->cb(path, strlen(path), ctx->user); - ctx->cb("'", 1, ctx->user); - } else - ctx->cb(start, len, ctx->user); - + decode_one_uri(ctx, start, end - start); start = end + 1; - - free(scheme); - free(host); - free(path); } const size_t ofs = start - ctx->buf.data; @@ -1532,6 +1543,13 @@ fdm_receive_decoder_uri(struct clipboard_receive *ctx, char *data, size_t size) ctx->buf.idx = left; } +static void +fdm_receive_finish_uri(struct clipboard_receive *ctx) +{ + LOG_DBG("finish: %.*s", (int)ctx->buf.idx, ctx->buf.data); + decode_one_uri(ctx, ctx->buf.data, ctx->buf.idx); +} + static bool fdm_receive(struct fdm *fdm, int fd, int events, void *data) { @@ -1582,6 +1600,7 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data) } done: + ctx->finish(ctx); clipboard_receive_done(fdm, ctx); return true; } @@ -1623,6 +1642,9 @@ begin_receive_clipboard(struct terminal *term, int read_fd, .decoder = (mime_type == DATA_OFFER_MIME_URI_LIST ? &fdm_receive_decoder_uri : &fdm_receive_decoder_plain), + .finish = (mime_type == DATA_OFFER_MIME_URI_LIST + ? &fdm_receive_finish_uri + : &fdm_receive_finish_plain), .cb = cb, .done = done, .user = user, @@ -1664,6 +1686,9 @@ text_from_clipboard(struct seat *seat, struct terminal *term, return; } + LOG_DBG("receive from clipboard: mime-type=%s", + mime_type_map[clipboard->mime_type]); + int read_fd = fds[0]; int write_fd = fds[1]; @@ -1808,6 +1833,9 @@ text_from_primary( return; } + LOG_DBG("receive from primary: mime-type=%s", + mime_type_map[primary->mime_type]); + int read_fd = fds[0]; int write_fd = fds[1];