| 365 | } |
| 366 | |
| 367 | void strbuf_utf8_replace(struct strbuf *sb_src, int pos, int width, |
| 368 | const char *subst) |
| 369 | { |
| 370 | const char *src = sb_src->buf, *end = sb_src->buf + sb_src->len; |
| 371 | struct strbuf dst; |
| 372 | int w = 0; |
| 373 | |
| 374 | strbuf_init(&dst, sb_src->len); |
| 375 | |
| 376 | while (src < end) { |
| 377 | const char *old; |
| 378 | int glyph_width; |
| 379 | size_t n; |
| 380 | |
| 381 | while ((n = display_mode_esc_sequence_len(src))) { |
| 382 | strbuf_add(&dst, src, n); |
| 383 | src += n; |
| 384 | } |
| 385 | |
| 386 | if (src >= end) |
| 387 | break; |
| 388 | |
| 389 | old = src; |
| 390 | glyph_width = utf8_width((const char**)&src, NULL); |
| 391 | if (!src) /* broken utf-8, do nothing */ |
| 392 | goto out; |
| 393 | |
| 394 | /* |
| 395 | * In case we see a control character we copy it into the |
| 396 | * buffer, but don't add it to the width. |
| 397 | */ |
| 398 | if (glyph_width < 0) |
| 399 | glyph_width = 0; |
| 400 | |
| 401 | if (glyph_width && w >= pos && w < pos + width) { |
| 402 | if (subst) { |
| 403 | strbuf_addstr(&dst, subst); |
| 404 | subst = NULL; |
| 405 | } |
| 406 | } else { |
| 407 | strbuf_add(&dst, old, src - old); |
| 408 | } |
| 409 | |
| 410 | w += glyph_width; |
| 411 | } |
| 412 | |
| 413 | strbuf_swap(sb_src, &dst); |
| 414 | out: |
| 415 | strbuf_release(&dst); |
| 416 | } |
| 417 | |
| 418 | /* |
| 419 | * Returns true (1) if the src encoding name matches the dst encoding |
no test coverage detected