X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Flibpspp%2Fu8-line.c;h=1374314a11fb377c8f6e7e95b751738426f16c8d;hb=9666b94fcb0fe0230371d85a951ed18d1a34d538;hp=33442ba287644fe09f7e2458bc113147cebecd75;hpb=b2518c70cc5b55bb630b07ddcda5dfd7a3613da4;p=pspp diff --git a/src/libpspp/u8-line.c b/src/libpspp/u8-line.c index 33442ba287..1374314a11 100644 --- a/src/libpspp/u8-line.c +++ b/src/libpspp/u8-line.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 2011, 2012, 2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -96,8 +96,8 @@ struct u8_pos size_t ofs1; }; -static void -u8_line_find_pos (struct u8_line *line, int target_x, struct u8_pos *c) +static bool +u8_line_find_pos (const struct u8_line *line, int target_x, struct u8_pos *c) { const uint8_t *s = CHAR_CAST (const uint8_t *, ds_cstr (&line->s)); size_t length = ds_length (&line->s); @@ -106,21 +106,28 @@ u8_line_find_pos (struct u8_line *line, int target_x, struct u8_pos *c) int x; x = 0; - for (ofs = 0; ; ofs += mblen) + c->x0 = 0; + c->ofs0 = 0; + for (ofs = 0; ofs <= length; ofs += mblen) { int w; - + c->x0 = x; + c->ofs0 = ofs; mblen = u8_mb_to_display (&w, s + ofs, length - ofs); if (x + w > target_x) { - c->x0 = x; c->x1 = x + w; - c->ofs0 = ofs; c->ofs1 = ofs + mblen; - return; + return true; } x += w; } + + /* This can happen if there are non-printable characters + in the line. */ + c->x1 = x; + c->ofs1 = ofs; + return false; } /* Prepares LINE to write N bytes of characters that comprise X1-X0 column @@ -129,6 +136,7 @@ u8_line_find_pos (struct u8_line *line, int target_x, struct u8_pos *c) char * u8_line_reserve (struct u8_line *line, int x0, int x1, int n) { + assert (x1 >= x0); if (x0 >= line->width) { /* The common case: adding new characters at the end of a line. */ @@ -179,9 +187,11 @@ u8_line_reserve (struct u8_line *line, int x0, int x1, int n) p1.x0++; } while (p1.x0 < x1); + assert (p1.ofs1 >= p0.ofs0); return ds_splice_uninit (&line->s, p0.ofs0, p1.ofs1 - p0.ofs0, n); } + assert (p1.ofs0 >= p0.ofs0); return ds_splice_uninit (&line->s, p0.ofs0, p1.ofs0 - p0.ofs0, n); } } @@ -193,3 +203,29 @@ u8_line_put (struct u8_line *line, int x0, int x1, const char *s, int n) { memcpy (u8_line_reserve (line, x0, x1, n), s, n); } + +/* Changes the width of LINE to X column widths. If X is longer than LINE's + previous width, LINE is extended by appending spaces. If X is shorter than + LINE's previous width, LINE is shortened by removing trailing characters. */ +void +u8_line_set_length (struct u8_line *line, int x) +{ + if (x > line->width) + { + ds_put_byte_multiple (&line->s, ' ', x - line->width); + line->width = x; + } + else if (x < line->width) + { + struct u8_pos pos; + + u8_line_find_pos (line, x, &pos); + ds_truncate (&line->s, pos.ofs0); + line->width = pos.x0; + if (x > line->width) + { + ds_put_byte_multiple (&line->s, '?', x - line->width); + line->width = x; + } + } +}