diff --git a/src/report.c b/src/report.c index fe3aec1de..0644df62b 100644 --- a/src/report.c +++ b/src/report.c @@ -510,59 +510,6 @@ static void nr_spell(stream *out, spellbook_entry * sbe, const struct locale *la newline(out); } -void sparagraph(strlist ** SP, const char *s, unsigned int indent, char mark) -{ - - /* Die Liste SP wird mit dem String s aufgefuellt, mit indent und einer - * mark, falls angegeben. SP wurde also auf 0 gesetzt vor dem Aufruf. - * Vgl. spunit (). */ - - unsigned int width; - int firstline; - static char buf[REPORTWIDTH + 1]; // FIXME: static return value - - width = REPORTWIDTH - indent; - firstline = 1; - - while (s[0]) { - unsigned int j = 0, i; - - for (i=0; s[j]; j=i) { - while (s[j] && s[j] != ' ') - j++; - if (j > width) { - - /* j zeigt auf das ende der aktuellen zeile, i zeigt auf den anfang der - * nächsten zeile. existiert ein wort am anfang der zeile, welches - * länger als eine zeile ist, muss dieses hier abgetrennt werden. */ - - if (i == 0) - i = width - 1; - break; - } - i = j + 1; - } - - for (j = 0; j != indent; j++) - buf[j] = ' '; - - if (firstline && mark) - buf[indent - 2] = mark; - - for (j = 0; j != i - 1; j++) - buf[indent + j] = s[j]; - buf[indent + j] = 0; - - addstrlist(SP, buf); - - if (s[i - 1] == 0) - break; - - s += i; - firstline = 0; - } -} - static void nr_curses_i(stream *out, int indent, const faction *viewer, objtype_t typ, const void *obj, attrib *a, int self) { diff --git a/src/reports.c b/src/reports.c index 8ec48c3e9..4d71d29b0 100644 --- a/src/reports.c +++ b/src/reports.c @@ -956,9 +956,60 @@ const struct unit * u, struct skill * sv, int *dh, int days) return tsize; } -void lparagraph(struct strlist **SP, char *s, unsigned int indent, char mark) +void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark) { + /* Die Liste SP wird mit dem String s aufgefuellt, mit indent und einer + * mark, falls angegeben. SP wurde also auf 0 gesetzt vor dem Aufruf. + * Vgl. spunit (). */ + bool firstline; + static char buf[REPORTWIDTH + 1]; // FIXME: static buffer, artificial limit + size_t len = strlen(s); + + assert(width <= REPORTWIDTH); + width -= indent; + firstline = (mark!=0 && indent>2); + *SP = 0; + + while (len > 0) { + unsigned int j; + const char *cut = 0, *space = strchr(s, ' '); + while (space && *space && (space - s) <= (ptrdiff_t)width) { + cut = space; + space = strchr(space + 1, ' '); + if (!space && len < width) { + cut = space = s + len; + } + } + + for (j = 0; j != indent; j++) + buf[j] = ' '; + + if (firstline) { + buf[indent - 2] = mark; + firstline = false; + } + if (!cut) { + cut = s + _min(len, REPORTWIDTH); + } + strncpy(buf+indent, s, cut - s); + buf[indent + (cut - s)] = 0; + addstrlist(SP, buf); // TODO: too much string copying, cut out this function + while (*cut == ' ') { + ++cut; + } + len -= (cut - s); + s = cut; + } +} + +void sparagraph(strlist ** SP, const char *s, unsigned int indent, char mark) +{ + split_paragraph(SP, s, indent, REPORTWIDTH, mark); +} + +void lparagraph(struct strlist **SP, char *s, unsigned int indent, char mark) +{ /* Die Liste SP wird mit dem String s aufgefuellt, mit indent und einer * mark, falls angegeben. SP wurde also auf 0 gesetzt vor dem Aufruf. * Vgl. spunit (). */ diff --git a/src/reports.h b/src/reports.h index 2a33d47bd..93b3ab122 100644 --- a/src/reports.h +++ b/src/reports.h @@ -151,6 +151,7 @@ extern "C" { void addstrlist(strlist ** SP, const char *s); void freestrlist(strlist * s); + void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark); #define GR_PLURAL 0x01 /* grammar: plural */ diff --git a/src/reports.test.c b/src/reports.test.c index 29f7ae5aa..9dd9f0913 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -131,6 +131,30 @@ static void test_write_many_spaces(CuTest *tc) { mstream_done(&out); } +static void test_sparagraph(CuTest *tc) { + strlist *sp = 0; + split_paragraph(&sp, "Hello World", 0, 16, 0); + CuAssertPtrNotNull(tc, sp); + CuAssertStrEquals(tc, "Hello World", sp->s); + CuAssertPtrEquals(tc, 0, sp->next); + split_paragraph(&sp, "Hello World", 4, 16, 0); + CuAssertPtrNotNull(tc, sp); + CuAssertStrEquals(tc, " Hello World", sp->s); + CuAssertPtrEquals(tc, 0, sp->next); + split_paragraph(&sp, "Hello World", 4, 16, '*'); + CuAssertPtrNotNull(tc, sp); + CuAssertStrEquals(tc, " * Hello World", sp->s); + CuAssertPtrEquals(tc, 0, sp->next); + split_paragraph(&sp, "12345678 90 12345678", 0, 8, '*'); + CuAssertPtrNotNull(tc, sp); + CuAssertStrEquals(tc, "12345678", sp->s); + CuAssertPtrNotNull(tc, sp->next); + CuAssertStrEquals(tc, "90", sp->next->s); + CuAssertPtrNotNull(tc, sp->next->next); + CuAssertStrEquals(tc, "12345678", sp->next->next->s); + CuAssertPtrEquals(tc, 0, sp->next->next->next); +} + CuSuite *get_reports_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -139,5 +163,6 @@ CuSuite *get_reports_suite(void) SUITE_ADD_TEST(suite, test_regionid); SUITE_ADD_TEST(suite, test_write_spaces); SUITE_ADD_TEST(suite, test_write_many_spaces); + SUITE_ADD_TEST(suite, test_sparagraph); return suite; }