very messy first steps towards making report_plaintext use filestream instead of FILE (lots of hacks)

This commit is contained in:
Enno Rehling 2015-05-12 19:25:50 -07:00
parent 9b9e038438
commit e048b82ad2
3 changed files with 377 additions and 297 deletions

@ -1 +1 @@
Subproject commit 61989d93368022602a2a7ac4218c83f254701f0f Subproject commit a2c6fad825e498abc2b36c8b2ed5a1ad9acf743e

View File

@ -81,6 +81,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/nrmessage.h> #include <util/nrmessage.h>
#include <quicklist.h> #include <quicklist.h>
#include <util/rng.h> #include <util/rng.h>
#include <filestream.h>
/* libc includes */ /* libc includes */
#include <assert.h> #include <assert.h>
@ -128,6 +129,10 @@ void rnl(FILE * F)
fputc('\n', F); fputc('\n', F);
} }
void newline(stream *out) {
sputs("", out);
}
static void centre(FILE * F, const char *s, bool breaking) static void centre(FILE * F, const char *s, bool breaking)
{ {
/* Bei Namen die genau 80 Zeichen lang sind, kann es hier Probleme /* Bei Namen die genau 80 Zeichen lang sind, kann es hier Probleme
@ -214,6 +219,71 @@ char mark)
} while (*begin); } while (*begin);
} }
static void
paragraph(stream *out, const char *str, ptrdiff_t indent, int hanging_indent,
char marker)
{
static const char *spaces = " ";
size_t length = REPORTWIDTH;
const char *end, *begin, *mark = 0;
if (!str) return;
/* find out if there's a mark + indent already encoded in the string. */
if (!marker) {
const char *x = str;
while (*x == ' ')
++x;
indent += x - str;
if (x[0] && indent && x[1] == ' ') {
indent += 2;
mark = x;
str = x + 2;
hanging_indent -= 2;
}
}
else {
mark = &marker;
}
begin = end = str;
do {
const char *last_space = begin;
if (mark && indent >= 2) {
swrite(spaces, sizeof(char), indent - 2, out);
swrite(mark, sizeof(char), 1, out);
swrite(spaces, sizeof(char), 1, out);
mark = 0;
}
else if (begin == str) {
swrite(spaces, sizeof(char), indent, out);
}
else {
swrite(spaces, sizeof(char), indent + hanging_indent, out);
}
while (*end && end <= begin + length - indent) {
if (*end == ' ') {
last_space = end;
}
++end;
}
if (*end == 0)
last_space = end;
if (last_space == begin) {
/* there was no space in this line. clip it */
last_space = end;
}
swrite(begin, sizeof(char), last_space - begin, out);
begin = last_space;
while (*begin == ' ') {
++begin;
}
if (begin > end)
begin = end;
sputs("", out);
} while (*begin);
}
static size_t write_spell_modifier(spell * sp, int flag, const char * str, bool cont, char * bufp, size_t size) { static size_t write_spell_modifier(spell * sp, int flag, const char * str, bool cont, char * bufp, size_t size) {
if (sp->sptyp & flag) { if (sp->sptyp & flag) {
size_t bytes = 0; size_t bytes = 0;
@ -564,11 +634,46 @@ void sparagraph(strlist ** SP, const char *s, int indent, char mark)
} }
static void static void
nr_curses(FILE * F, const faction * viewer, const void *obj, objtype_t typ, nr_curses_i(stream *out, int indent, const faction *viewer, objtype_t typ, const void *obj, attrib *a)
int indent)
{ {
attrib *a = NULL;
int self = 0; int self = 0;
for (; a; a = a->next) {
char buf[4096];
message *msg;
if (fval(a->type, ATF_CURSE)) {
curse *c = (curse *)a->data.v;
if (c->type->cansee) {
self = c->type->cansee(viewer, obj, typ, c, self);
}
msg = msg_curse(c, obj, typ, self);
if (msg) {
newline(out);
nr_render(msg, viewer->locale, buf, sizeof(buf), viewer);
paragraph(out, buf, indent, 2, 0);
msg_release(msg);
}
}
else if (a->type == &at_effect && self) {
effect_data *data = (effect_data *)a->data.v;
if (data->value > 0) {
msg = msg_message("nr_potion_effect", "potion left",
data->type->itype->rtype, data->value);
nr_render(msg, viewer->locale, buf, sizeof(buf), viewer);
paragraph(out, buf, indent, 2, 0);
msg_release(msg);
}
}
}
}
static void nr_curses(stream *out, int indent, const faction *viewer, objtype_t typ, const void *obj)
{
int self = 0;
attrib *a = NULL;
region *r; region *r;
/* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei /* Die Sichtbarkeit eines Zaubers und die Zaubermeldung sind bei
@ -629,39 +734,10 @@ int indent)
a = r->attribs; a = r->attribs;
} }
else { else {
/* fehler */ log_error("get_attribs: invalid object type %d", typ);
} assert(!"invalid object type");
for (; a; a = a->next) {
char buf[4096];
message *msg;
if (fval(a->type, ATF_CURSE)) {
curse *c = (curse *)a->data.v;
if (c->type->cansee) {
self = c->type->cansee(viewer, obj, typ, c, self);
}
msg = msg_curse(c, obj, typ, self);
if (msg) {
rnl(F);
nr_render(msg, viewer->locale, buf, sizeof(buf), viewer);
rparagraph(F, buf, indent, 2, 0);
msg_release(msg);
}
}
else if (a->type == &at_effect && self) {
effect_data *data = (effect_data *)a->data.v;
if (data->value > 0) {
msg = msg_message("nr_potion_effect", "potion left",
data->type->itype->rtype, data->value);
nr_render(msg, viewer->locale, buf, sizeof(buf), viewer);
rparagraph(F, buf, indent, 2, 0);
msg_release(msg);
}
}
} }
nr_curses_i(out, indent, viewer, typ, obj, a);
} }
static void rps_nowrap(FILE * F, const char *s) static void rps_nowrap(FILE * F, const char *s)
@ -687,7 +763,7 @@ static void rps_nowrap(FILE * F, const char *s)
} }
static void static void
nr_unit(FILE * F, const faction * f, const unit * u, int indent, int mode) nr_unit(stream *out, const faction * f, const unit * u, int indent, int mode)
{ {
attrib *a_otherfaction; attrib *a_otherfaction;
char marker; char marker;
@ -698,10 +774,8 @@ nr_unit(FILE * F, const faction * f, const unit * u, int indent, int mode)
if (fval(u_race(u), RCF_INVISIBLE)) if (fval(u_race(u), RCF_INVISIBLE))
return; return;
{ newline(out);
rnl(F);
dh = bufunit(f, u, indent, mode, buf, sizeof(buf)); dh = bufunit(f, u, indent, mode, buf, sizeof(buf));
}
a_otherfaction = a_find(u->attribs, &at_otherfaction); a_otherfaction = a_find(u->attribs, &at_otherfaction);
@ -723,10 +797,10 @@ nr_unit(FILE * F, const faction * f, const unit * u, int indent, int mode)
marker = '-'; marker = '-';
} }
} }
rparagraph(F, buf, indent, 0, marker); paragraph(out, buf, indent, 0, marker);
if (!isbattle) { if (!isbattle) {
nr_curses(F, f, u, TYP_UNIT, indent); nr_curses(out, indent, f, TYP_UNIT, u);
} }
} }
@ -838,7 +912,8 @@ static void prices(FILE * F, const region * r, const faction * f)
size); size);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
} else if (n == 1) { }
else if (n == 1) {
bytes = (int)strlcpy(bufp, " ", size); bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
@ -849,7 +924,8 @@ static void prices(FILE * F, const region * r, const faction * f)
bytes = (int)strlcpy(bufp, " ", size); bytes = (int)strlcpy(bufp, " ", size);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
} else { }
else {
bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_trade_next"), bytes = (int)strlcpy(bufp, LOC(f->locale, "nr_trade_next"),
size); size);
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
@ -887,7 +963,7 @@ bool see_border(const connection * b, const faction * f, const region * r)
return cs; return cs;
} }
static void describe(FILE * F, const seen_region * sr, faction * f) static void describe(stream *out, const seen_region * sr, faction * f)
{ {
const region *r = sr->r; const region *r = sr->r;
int n; int n;
@ -910,6 +986,7 @@ static void describe(FILE * F, const seen_region * sr, faction * f)
char *bufp = buf; char *bufp = buf;
size_t size = sizeof(buf); size_t size = sizeof(buf);
int bytes; int bytes;
FILE * F = fstream_file(out);
for (d = 0; d != MAXDIRECTIONS; d++) { for (d = 0; d != MAXDIRECTIONS; d++) {
/* Nachbarregionen, die gesehen werden, ermitteln */ /* Nachbarregionen, die gesehen werden, ermitteln */
@ -1237,10 +1314,9 @@ static void describe(FILE * F, const seen_region * sr, faction * f)
} }
} }
n = 0;
/* Wirkungen permanenter Sprüche */ /* Wirkungen permanenter Sprüche */
nr_curses(F, f, r, TYP_REGION, 0); nr_curses(out, 0, f, TYP_REGION, r);
n = 0;
/* Produktionsreduktion */ /* Produktionsreduktion */
a = a_find(r->attribs, &at_reduceproduction); a = a_find(r->attribs, &at_reduceproduction);
@ -1904,7 +1980,7 @@ static void list_address(FILE * F, const faction * uf, quicklist * seenfactions)
} }
static void static void
nr_ship(FILE * F, const seen_region * sr, const ship * sh, const faction * f, nr_ship(stream *out, const seen_region * sr, const ship * sh, const faction * f,
const unit * captain) const unit * captain)
{ {
const region *r = sr->r; const region *r = sr->r;
@ -1912,6 +1988,7 @@ const unit * captain)
size_t size = sizeof(buffer) - 1; size_t size = sizeof(buffer) - 1;
int bytes; int bytes;
char ch; char ch;
FILE * F = fstream_file(out);
rnl(F); rnl(F);
@ -1975,11 +2052,11 @@ const unit * captain)
*bufp = 0; *bufp = 0;
rparagraph(F, buffer, 2, 0, 0); rparagraph(F, buffer, 2, 0, 0);
nr_curses(F, f, sh, TYP_SHIP, 4); nr_curses(out, 4, f, TYP_SHIP, sh);
} }
static void static void
nr_building(FILE * F, const seen_region * sr, const building * b, nr_building(stream *out, const seen_region * sr, const building * b,
const faction * f) const faction * f)
{ {
int i, bytes; int i, bytes;
@ -1988,6 +2065,7 @@ const faction * f)
char buffer[8192], *bufp = buffer; char buffer[8192], *bufp = buffer;
message *msg; message *msg;
size_t size = sizeof(buffer) - 1; size_t size = sizeof(buffer) - 1;
FILE * F = fstream_file(out);
rnl(F); rnl(F);
@ -2052,7 +2130,8 @@ const faction * f)
if (sr->mode < see_lighthouse) if (sr->mode < see_lighthouse)
return; return;
nr_curses(F, f, b, TYP_BUILDING, 4); i = 0;
nr_curses(out, 4, f, TYP_BUILDING, b);
} }
static void nr_paragraph(FILE * F, message * m, faction * f) static void nr_paragraph(FILE * F, message * m, faction * f)
@ -2083,9 +2162,10 @@ const char *charset)
attrib *a; attrib *a;
message *m; message *m;
unsigned char op; unsigned char op;
int bytes, ix = want(O_STATISTICS); int maxh, bytes, ix = want(O_STATISTICS);
int wants_stats = (f->options & ix); int wants_stats = (f->options & ix);
FILE *F = fopen(filename, "wt"); FILE *F = fopen(filename, "wt");
stream out = { 0 };
seen_region *sr = NULL; seen_region *sr = NULL;
char buf[8192]; char buf[8192];
char *bufp; char *bufp;
@ -2109,6 +2189,8 @@ const char *charset)
perror(filename); perror(filename);
return -1; return -1;
} }
fstream_init(&out, F);
if (utf8) { if (utf8) {
const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 }; const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 };
fwrite(utf8_bom, 1, 3, F); fwrite(utf8_bom, 1, 3, F);
@ -2214,8 +2296,7 @@ const char *charset)
msg_release(m); msg_release(m);
centre(F, buf, true); centre(F, buf, true);
} }
{ maxh = maxheroes(f);
int maxh = maxheroes(f);
if (maxh) { if (maxh) {
message *msg = message *msg =
msg_message("nr_heroes", "units maxunits", countheroes(f), maxh); msg_message("nr_heroes", "units maxunits", countheroes(f), maxh);
@ -2223,7 +2304,6 @@ const char *charset)
msg_release(msg); msg_release(msg);
centre(F, buf, true); centre(F, buf, true);
} }
}
if (f->items != NULL) { if (f->items != NULL) {
message *msg = msg_message("nr_claims", "items", f->items); message *msg = msg_message("nr_claims", "items", f->items);
@ -2360,7 +2440,7 @@ const char *charset)
if (sr->mode == see_unit) { if (sr->mode == see_unit) {
anyunits = 1; anyunits = 1;
describe(F, sr, f); describe(&out, sr, f);
if (markets_module() && r->land) { if (markets_module() && r->land) {
const item_type *lux = r_luxury(r); const item_type *lux = r_luxury(r);
const item_type *herb = r->land->herbtype; const item_type *herb = r->land->herbtype;
@ -2390,16 +2470,16 @@ const char *charset)
} }
else { else {
if (sr->mode == see_far) { if (sr->mode == see_far) {
describe(F, sr, f); describe(&out, sr, f);
guards(F, r, f); guards(F, r, f);
durchreisende(F, r, f); durchreisende(F, r, f);
} }
else if (sr->mode == see_lighthouse) { else if (sr->mode == see_lighthouse) {
describe(F, sr, f); describe(&out, sr, f);
durchreisende(F, r, f); durchreisende(F, r, f);
} }
else { else {
describe(F, sr, f); describe(&out, sr, f);
durchreisende(F, r, f); durchreisende(F, r, f);
} }
} }
@ -2422,13 +2502,13 @@ const char *charset)
u = r->units; u = r->units;
while (b) { while (b) {
while (b && (!u || u->building != b)) { while (b && (!u || u->building != b)) {
nr_building(F, sr, b, f); nr_building(&out, sr, b, f);
b = b->next; b = b->next;
} }
if (b) { if (b) {
nr_building(F, sr, b, f); nr_building(&out, sr, b, f);
while (u && u->building == b) { while (u && u->building == b) {
nr_unit(F, f, u, 6, sr->mode); nr_unit(&out, f, u, 6, sr->mode);
u = u->next; u = u->next;
} }
b = b->next; b = b->next;
@ -2437,7 +2517,7 @@ const char *charset)
while (u && !u->ship) { while (u && !u->ship) {
if (stealthmod > INT_MIN) { if (stealthmod > INT_MIN) {
if (u->faction == f || cansee(f, r, u, stealthmod)) { if (u->faction == f || cansee(f, r, u, stealthmod)) {
nr_unit(F, f, u, 4, sr->mode); nr_unit(&out, f, u, 4, sr->mode);
} }
} }
assert(!u->building); assert(!u->building);
@ -2445,13 +2525,13 @@ const char *charset)
} }
while (sh) { while (sh) {
while (sh && (!u || u->ship != sh)) { while (sh && (!u || u->ship != sh)) {
nr_ship(F, sr, sh, f, NULL); nr_ship(&out, sr, sh, f, NULL);
sh = sh->next; sh = sh->next;
} }
if (sh) { if (sh) {
nr_ship(F, sr, sh, f, u); nr_ship(&out, sr, sh, f, u);
while (u && u->ship == sh) { while (u && u->ship == sh) {
nr_unit(F, f, u, 6, sr->mode); nr_unit(&out, f, u, 6, sr->mode);
u = u->next; u = u->next;
} }
sh = sh->next; sh = sh->next;
@ -2472,7 +2552,7 @@ const char *charset)
list_address(F, f, ctx->addresses); list_address(F, f, ctx->addresses);
} }
} }
fclose(F); fstream_done(&out);
return 0; return 0;
} }

@ -1 +1 @@
Subproject commit bcc2874cf289a1d0fc9cc79ff3ed271403b2e24c Subproject commit d2b5770a003a0b0233510e44b66defa8052fa0e6