1 /***             analog 6.0             http://www.analog.cx/             ***/
2 /*** This program is copyright (c) Stephen R. E. Turner 1995 - 2004 except as
3  *** stated otherwise.
4  ***
5  *** This program is free software. You can redistribute it and/or modify it
6  *** under the terms of version 2 of the GNU General Public License, which you
7  *** should have received with it.
8  ***
9  *** This program is distributed in the hope that it will be useful, but
10  *** without any warranty, expressed or implied.   ***/
11 
12 /*** outplain.c; plain text output ***/
13 
14 #include "anlghea3.h"
15 
16 /* Page width */
plain_pagewidth(Outchoices * od)17 unsigned int plain_pagewidth(Outchoices *od) {
18   return od->plainpagewidth;
19 }
20 
21 /* The top of the output if we are in CGI mode */
plain_cgihead(FILE * outf,Outchoices * od)22 void plain_cgihead(FILE *outf, Outchoices *od) {
23   fprintf(outf, "Content-Type: text/plain\n\n");
24 }
25 
26 /* Stuff this output style needs in the page header */
plain_stylehead(FILE * outf,Outchoices * od)27 void plain_stylehead(FILE *outf, Outchoices *od) {
28 }
29 
30 /* The title of the page, plus the user's HEADERFILE */
plain_pagetitle(FILE * outf,Outchoices * od)31 void plain_pagetitle(FILE *outf, Outchoices *od) {
32   fprintf(outf, "%s %s\n", od->lngstr[webstatsfor_], od->hostname);
33   matchlength(outf, od, od->hostname, '=');
34   matchlength(outf, od, od->lngstr[webstatsfor_], '=');
35   fputs("=\n\n", outf);
36 
37   if (!strcaseeq(od->headerfile, "none"))
38     plain_includefile(outf, od, od->headerfile, 'h');
39 }
40 
41 /* Program start time, and logfile start and end times */
plain_timings(FILE * outf,Outchoices * od,Dateman * dman)42 void plain_timings(FILE *outf, Outchoices *od, Dateman *dman) {
43   extern timecode_t starttimec;
44 
45   char **lngstr = od->lngstr;
46 
47   double t0;
48   int t1, t2;
49 
50   if (od->runtime)
51     fprintf(outf, "%s %s.\n", lngstr[progstart_],
52 	    timesprintf(od, lngstr[datefmt2_], starttimec, UNSET));
53 
54   if (dman->firsttime <= dman->lasttime) {
55     mprintf(outf, od->plainpagewidth, "%s %s ", lngstr[reqstart_],
56 	    timesprintf(od, lngstr[datefmt2_], dman->firsttime, UNSET));
57     mprintf(outf, od->plainpagewidth, "%s %s", lngstr[to_],
58 	    timesprintf(od, lngstr[datefmt2_], dman->lasttime, UNSET));
59     t0 = (dman->lasttime - dman->firsttime) / 1440.0 + 0.005;
60     t1 = (int)t0;
61     t2 = (int)(100 * (t0 - (double)t1));
62     mprintf(outf, od->plainpagewidth, " (%d", t1);
63     putc(od->decpt, outf);
64     mprintf(outf, od->plainpagewidth, "%02d %s).", t2, od->lngstr[days_]);
65     mprintf(outf, 0, NULL);
66   }
67 }
68 
69 /* Finishing the top of the page */
plain_closehead(FILE * outf,Outchoices * od)70 void plain_closehead(FILE *outf, Outchoices *od) {
71   plain_hrule(outf, od);
72 }
73 
74 /* Starting the bottom of the page */
plain_pagebotstart(FILE * outf,Outchoices * od)75 void plain_pagebotstart(FILE *outf, Outchoices *od) {
76 }
77 
78 /* The credit line at the bottom of the page */
plain_credit(FILE * outf,Outchoices * od)79 void plain_credit(FILE *outf, Outchoices *od) {
80   fprintf(outf, "%s analog %s.\n", od->lngstr[credit_], VNUMBER);
81 }
82 
83 /* The program run time */
plain_runtime(FILE * outf,Outchoices * od,long secs)84 void plain_runtime(FILE *outf, Outchoices *od, long secs) {
85   char **lngstr = od->lngstr;
86 
87   fprintf(outf, "%s: ", lngstr[runtime_]);
88 
89   if (secs == 0)
90     fprintf(outf, "%s %s.\n", lngstr[lessone_], lngstr[second_]);
91   else if (secs < 60)
92     fprintf(outf, "%ld %s.\n", secs,
93 	    (secs == 1)?lngstr[second_]:lngstr[seconds_]);
94   else
95     fprintf(outf, "%ld %s, %ld %s.\n", secs / 60,
96 	    (secs < 120)?lngstr[minute_]:lngstr[minutes_], secs % 60,
97 	    (secs % 60 == 1)?lngstr[second_]:lngstr[seconds_]);
98 }
99 
100 /* The page footer, including the user's FOOTERFILE */
plain_pagefoot(FILE * outf,Outchoices * od)101 void plain_pagefoot(FILE *outf, Outchoices *od) {
102   if (!strcaseeq(od->footerfile, "none"))
103     plain_includefile(outf, od, od->footerfile, 'f');
104 }
105 
106 /* Footer material for this output style */
plain_stylefoot(FILE * outf,Outchoices * od)107 void plain_stylefoot(FILE *outf, Outchoices *od) {
108 }
109 
110 /* Report title */
plain_reporttitle(FILE * outf,Outchoices * od,choice rep)111 void plain_reporttitle(FILE *outf, Outchoices *od, choice rep) {
112   extern unsigned int *rep2lng;
113 
114   fprintf(outf, "%s\n", od->lngstr[rep2lng[rep]]);
115   matchlength(outf, od, od->lngstr[rep2lng[rep]], '-');
116   putc('\n', outf);
117 }
118 
119 /* Report footer */
plain_reportfooter(FILE * outf,Outchoices * od,choice rep)120 void plain_reportfooter(FILE *outf, Outchoices *od, choice rep) {
121 }
122 
123 /* Report description */
plain_reportdesc(FILE * outf,Outchoices * od,choice rep)124 void plain_reportdesc(FILE *outf, Outchoices *od, choice rep) {
125   mprintf(outf, od->plainpagewidth, "%s", od->descstr[rep]);
126   mprintf(outf, 0, NULL);
127   if (rep != REP_SIZE && rep != REP_PROCTIME)
128     putc('\n', outf);
129   /* These two reports probably have no further header text.
130       If this is wrong, it's corrected in plain_reportspan() later. */
131 }
132 
133 /* The time period spanned by the report */
plain_reportspan(FILE * outf,Outchoices * od,choice rep,timecode_t maxd,timecode_t mind)134 void plain_reportspan(FILE *outf, Outchoices *od, choice rep, timecode_t maxd,
135 		      timecode_t mind) {
136   if ((rep == REP_SIZE || rep == REP_PROCTIME) && od->descriptions &&
137       od->descstr[rep] != NULL)
138     putc('\n', outf);
139   /* We were wrong when we assumed in plain_reportdesc() that these reports
140      had no further header text. So correct for it now. */
141 
142   /* NB Can't combine next two lines because timesprintf uses static buffer. */
143   mprintf(outf, od->plainpagewidth, "%s %s ", od->lngstr[repspan_],
144 	  timesprintf(od, od->lngstr[datefmt2_], mind, UNSET));
145   mprintf(outf, od->plainpagewidth, "%s %s.", od->lngstr[to_],
146 	  timesprintf(od, od->lngstr[datefmt2_], maxd, UNSET));
147   mprintf(outf, 0, NULL);
148 
149   if (rep != REP_SIZE && rep != REP_PROCTIME)
150     putc('\n', outf);
151   /* This time these reports really do have no further header text. */
152 }
153 
154 /* General Summary header */
plain_gensumhead(FILE * outf,Outchoices * od)155 void plain_gensumhead(FILE *outf, Outchoices *od) {
156 }
157 
158 /* General Summary footer */
plain_gensumfoot(FILE * outf,Outchoices * od)159 void plain_gensumfoot(FILE *outf, Outchoices *od) {
160 }
161 
162 /* Single General Summary line, long data */
plain_gensumline(FILE * outf,Outchoices * od,int namecode,unsigned long x,unsigned long x7,logical isaverage)163 void plain_gensumline(FILE *outf, Outchoices *od, int namecode,
164 		      unsigned long x, unsigned long x7, logical isaverage) {
165 
166   fprintf(outf, "%s%s ",  od->lngstr[namecode], od->lngstr[colon_]);
167 
168   f3printf(outf, od, (double)x, 0, od->sepchar);
169 
170   if (x7 != (unsigned long)UNSET) {
171     fputs(" (", outf);
172     f3printf(outf, od, (double)x7, 0, od->sepchar);
173     putc(')', outf);
174   }
175   putc('\n', outf);
176 }
177 
178 /* Single General Summary line, bytes data */
plain_gensumlineb(FILE * outf,Outchoices * od,int namecode,double x,double x7,logical isaverage)179 void plain_gensumlineb(FILE *outf, Outchoices *od, int namecode, double x,
180 		       double x7, logical isaverage) {
181   char **lngstr = od->lngstr;
182 
183   unsigned int bm;
184   char *c;
185 
186   fprintf(outf, "%s%s ",  lngstr[namecode], lngstr[colon_]);
187 
188   bm = (od->rawbytes)?0:findbmult(x, od->bytesdp);
189   printbytes(outf, od, x, bm, 0, od->sepchar);
190 
191   if (bm > 0) {
192     c = strchr(lngstr[xbytes_], '?');
193     *c = '\0';
194     fprintf(outf, " %s%s%s", lngstr[xbytes_], lngstr[byteprefix_ + bm], c + 1);
195     *c = '?';
196   }
197   else
198     fprintf(outf, " %s", lngstr[bytes_]);
199 
200   if (x7 != UNSET) {
201     fputs(" (", outf);
202     bm = (od->rawbytes)?0:findbmult(x7, od->bytesdp);
203     printbytes(outf, od, x7, bm, 0, od->sepchar);
204     if (bm > 0) {
205       c = strchr(lngstr[xbytes_], '?');
206       *c = '\0';
207       fprintf(outf, " %s%s%s)", lngstr[xbytes_], lngstr[byteprefix_ + bm],
208 	      c + 1);
209       *c = '?';
210     }
211     else
212       fprintf(outf, " %s)", lngstr[bytes_]);
213   }
214 
215   putc('\n', outf);
216 }
217 
218 /* "Last seven" explanation line */
plain_lastseven(FILE * outf,Outchoices * od,timecode_t last7to)219 void plain_lastseven(FILE *outf, Outchoices *od, timecode_t last7to) {
220   mprintf(outf, od->plainpagewidth, "(%s %s %s).\n", od->lngstr[brackets_],
221 	  od->lngstr[sevendaysto_],
222 	  timesprintf(od, od->lngstr[datefmt1_], last7to, UNSET));
223   mprintf(outf, 0, NULL);
224 }
225 
226 /* Start of a <pre> section */
plain_prestart(FILE * outf,Outchoices * od)227 void plain_prestart(FILE *outf, Outchoices *od) {
228   putc('\n', outf);
229 }
230 
231 /* End of a <pre> section */
plain_preend(FILE * outf,Outchoices * od)232 void plain_preend(FILE *outf, Outchoices *od) {
233 }
234 
235 /* A horizontal rule */
plain_hrule(FILE * outf,Outchoices * od)236 void plain_hrule(FILE *outf, Outchoices *od) {
237   unsigned int i;
238 
239   for (i = 0; i < od->plainpagewidth; i++)
240     putc('-', outf);
241   fputs("\n\n", outf);
242 }
243 
244 /* An en dash */
plain_endash(void)245 char *plain_endash(void) {
246   return "-";
247 }
248 
249 /* putc with special characters escaped */
plain_putch(FILE * outf,char c)250 void plain_putch(FILE *outf, char c) {
251   putc(c, outf);
252 }
253 
254 /* strlen */
plain_strlength(const char * s)255 size_t plain_strlength(const char *s) {
256   return strlen(s);
257 }
258 
259 /* Allow month in dates? DO NOT enable for human-readable text because of
260    i18n problems. */
plain_allowmonth(void)261 logical plain_allowmonth(void) {
262   return FALSE;
263 }
264 
265 /* Calculate column widths */
plain_calcwidths(Outchoices * od,choice rep,unsigned int width[],unsigned int * bmult,unsigned int * bmult7,double * unit,unsigned long maxr,unsigned long maxr7,unsigned long maxp,unsigned long maxp7,double maxb,double maxb7,unsigned long howmany)266 void plain_calcwidths(Outchoices *od, choice rep, unsigned int width[],
267 		      unsigned int *bmult, unsigned int *bmult7, double *unit,
268 		      unsigned long maxr, unsigned long maxr7,
269 		      unsigned long maxp, unsigned long maxp7, double maxb,
270 		      double maxb7, unsigned long howmany) {
271   calcwidths(od, rep, width, bmult, bmult7, unit, maxr, maxr7, maxp, maxp7,
272 	     maxb, maxb7, howmany);
273 }
274 
275 /* "Each unit represents" line */
plain_declareunit(FILE * outf,Outchoices * od,char graphby,double unit,unsigned int bmult)276 void plain_declareunit(FILE *outf, Outchoices *od, char graphby, double unit,
277 		       unsigned int bmult) {
278   /* NB Number can still overflow pagewidth, but only if pagewidth is small,
279      & will wrap straight afterwards. pagewidth is never guaranteed anyway. */
280   extern unsigned int ppcol;
281   char **lngstr = od->lngstr;
282   unsigned int pagewidth = od->plainpagewidth;
283 
284   char *s;
285 
286   mprintf(outf, pagewidth, "%s (%c) %s ", lngstr[eachunit_], od->markchar,
287 	  lngstr[represents_]);
288 
289   if (graphby == 'R' || graphby == 'r') {
290     ppcol += f3printf(outf, od, unit, 0, od->sepchar);
291     if (unit == 1.)
292       mprintf(outf, pagewidth, " %s.", lngstr[request_]);
293     else
294       mprintf(outf, pagewidth, " %s %s.", lngstr[requests_],
295 	      lngstr[partof_]);
296   }
297   else if (graphby == 'P' || graphby == 'p') {
298     ppcol += f3printf(outf, od, unit, 0, od->sepchar);
299     if (unit == 1.)
300       mprintf(outf, pagewidth, " %s.", lngstr[pagereq_]);
301     else
302       mprintf(outf, pagewidth, " %s %s.", lngstr[pagereqs_],
303 	      lngstr[partof_]);
304   }
305   else {
306     if (bmult > 0) {
307       plain_printdouble(outf, od, unit);
308       s = strchr(lngstr[xbytes_], '?');  /* checked in initialisation */
309       *s = '\0';
310       mprintf(outf, pagewidth, " %s%s%s %s.", lngstr[xbytes_],
311 	      lngstr[byteprefix_ + bmult], s + 1, lngstr[partof_]);
312       *s = '?';
313     }
314     else {
315       ppcol += f3printf(outf, od, unit, 0, od->sepchar);
316       mprintf(outf, pagewidth, " %s %s.", lngstr[bytes_], lngstr[partof_]);
317     }
318   }
319   mprintf(outf, 0, NULL);
320 }
321 
322 /* Start of column header line */
plain_colheadstart(FILE * outf,Outchoices * od,choice rep)323 void plain_colheadstart(FILE *outf, Outchoices *od, choice rep) {
324 }
325 
326 /* Column header line: individual column */
plain_colheadcol(FILE * outf,Outchoices * od,choice rep,choice col,unsigned int width,char * colname,logical unterminated)327 void plain_colheadcol(FILE *outf, Outchoices *od, choice rep, choice col,
328 		      unsigned int width, char *colname,
329 		      logical unterminated) {
330   if (unterminated)
331     fputs(colname, outf);
332   else
333     fprintf(outf, "%*s: ", width, colname);
334 }
335 
336 /* End of column header line */
plain_colheadend(FILE * outf,Outchoices * od,choice rep)337 void plain_colheadend(FILE *outf, Outchoices *od, choice rep) {
338   putc('\n', outf);
339 }
340 
341 /* Start of column header underlining line */
plain_colheadustart(FILE * outf,Outchoices * od,choice rep)342 void plain_colheadustart(FILE *outf, Outchoices *od, choice rep) {
343 }
344 
345 /* Underlining of one column header. */
346 /* If column is terminated, set width and leave name blank; and conversely. */
plain_colheadunderline(FILE * outf,Outchoices * od,choice rep,choice col,unsigned int width,char * name)347 void plain_colheadunderline(FILE *outf, Outchoices *od, choice rep, choice col,
348 			    unsigned int width, char *name) {
349   if (width > 0) {
350     matchlengthn(outf, od, (size_t)width, '-');
351     fputs(": ", outf);
352   }
353   else
354     matchlength(outf, od, name, '-');
355 }
356 
357 /* End of column header underlining line */
plain_colheaduend(FILE * outf,Outchoices * od,choice rep)358 void plain_colheaduend(FILE *outf, Outchoices *od, choice rep) {
359   putc('\n', outf);
360 }
361 
362 /* Start of a table row */
plain_rowstart(FILE * outf,Outchoices * od,choice rep,choice * cols,int level,char * name,char * datefmt,char * timefmt)363 void plain_rowstart(FILE *outf, Outchoices *od, choice rep, choice *cols,
364 		    int level, char *name, char *datefmt, char *timefmt) {
365 }
366 
367 /* Print level in hierarchy represented by this row */
plain_levelcell(FILE * outf,Outchoices * od,choice rep,int level)368 void plain_levelcell(FILE *outf, Outchoices *od, choice rep, int level) {
369 }
370 
371 /* Name column */
plain_namecell(FILE * outf,Outchoices * od,choice rep,char * name,choice source,unsigned int width,logical name1st,logical isfirst,logical rightalign,Alias * aliashead,Include * linkhead,logical ispage,unsigned int spaces,char * baseurl)372 void plain_namecell(FILE *outf, Outchoices *od, choice rep, char *name,
373 		    choice source, unsigned int width, logical name1st,
374 		    logical isfirst, logical rightalign, Alias *aliashead,
375 		    Include *linkhead, logical ispage, unsigned int spaces,
376 		    char *baseurl) {
377   extern char *workspace;
378 
379   int i;
380 
381   if (name1st != isfirst)
382     return;
383 
384   if (isfirst)
385     matchlengthn(outf, od, width - strlen(name), ' ');
386 
387   strcpy(workspace, name);
388   do_aliasx(workspace, aliashead);
389 
390   if (!isfirst) {
391     if (rightalign)
392       i = (int)width - (int)strlen(workspace) - (int)spaces;
393     else
394       i = (int)spaces;
395     matchlengthn(outf, od, i, ' ');
396   }
397 
398   fputs(workspace, outf);
399 
400   if (isfirst)
401     fputs(": ", outf);
402 }
403 
404 /* Single cell, unsigned long argument */
plain_ulcell(FILE * outf,Outchoices * od,choice rep,choice col,unsigned long x,unsigned int width)405 void plain_ulcell(FILE *outf, Outchoices *od, choice rep, choice col,
406 		  unsigned long x, unsigned int width) {
407   f3printf(outf, od, (double)x, width, od->repsepchar);
408   fputs(": ", outf);
409 }
410 
411 /* Single cell, TRUSTED string argument */
plain_strcell(FILE * outf,Outchoices * od,choice rep,choice col,char * s,unsigned int width)412 void plain_strcell(FILE *outf, Outchoices *od, choice rep, choice col,
413 		   char *s, unsigned int width) {
414   matchlengthn(outf, od, width - strlen(s), ' ');
415   fputs(s, outf);
416   fputs(": ", outf);
417 }
418 
419 /* Single cell, listing bytes */
plain_bytescell(FILE * outf,Outchoices * od,choice rep,choice col,double b,double bmult,unsigned int width)420 void plain_bytescell(FILE *outf, Outchoices *od, choice rep, choice col,
421 		     double b, double bmult, unsigned int width) {
422   printbytes(outf, od, b, bmult, width, od->repsepchar);
423   fputs(": ", outf);
424 }
425 
426 /* Single cell, listing percentage */
plain_pccell(FILE * outf,Outchoices * od,choice rep,choice col,double n,double tot,unsigned int width)427 void plain_pccell(FILE *outf, Outchoices *od, choice rep, choice col, double n,
428 		  double tot, unsigned int width) {
429   double pc;
430   unsigned int pc1, pc2;
431 
432   matchlengthn(outf, od, width - 6, ' ');
433   if (tot == 0)
434     pc = 0.0;
435   else
436     pc = n * 10000.0 / tot;
437   if (pc >= 9999.5)
438     fputs("  100%", outf);
439   else if (pc < 0.5)
440     fputs("      ", outf);
441   else {
442     pc1 = ((int)(pc + 0.5)) / 100;
443     pc2 = ((int)(pc + 0.5)) % 100;
444     fprintf(outf, "%2d", pc1);
445     putc(od->decpt, outf);
446     fprintf(outf, "%02d%%", pc2);
447   }
448   fputs(": ", outf);
449 }
450 
451 /* Single cell, index */
plain_indexcell(FILE * outf,Outchoices * od,choice rep,choice col,long index,unsigned int width)452 void plain_indexcell(FILE *outf, Outchoices *od, choice rep, choice col,
453 		    long index, unsigned int width) {
454   /* If index is 0 (i.e. sub-item), just print spaces */
455   if (index <= 0)
456     matchlengthn(outf, od, width, ' ');
457   else
458     f3printf(outf, od, (double)index, width, od->repsepchar);
459   fputs(": ", outf);
460 }
461 
462 /* End of a table row */
plain_rowend(FILE * outf,Outchoices * od,choice rep)463 void plain_rowend(FILE *outf, Outchoices *od, choice rep) {
464   putc('\n', outf);
465 }
466 
467 /* Blank line in time reports */
plain_blankline(FILE * outf,Outchoices * od,choice * cols)468 void plain_blankline(FILE *outf, Outchoices *od, choice *cols) {
469   putc('\n', outf);
470 }
471 
472 /* Barchart in time reports */
plain_barchart(FILE * outf,Outchoices * od,int y,char graphby)473 void plain_barchart(FILE *outf, Outchoices *od, int y, char graphby) {
474   int i;
475 
476   for (i = 0; i < y; i++)
477     putc(od->markchar, outf);
478 }
479 
480 /* "Busiest time period" line */
plain_busyprintf(FILE * outf,Outchoices * od,choice rep,char * datefmt,unsigned long reqs,unsigned long pages,double bys,datecode_t date,unsigned int hr,unsigned int min,datecode_t newdate,unsigned int newhr,unsigned int newmin,char graphby)481 void plain_busyprintf(FILE *outf, Outchoices *od, choice rep, char *datefmt,
482 		      unsigned long reqs, unsigned long pages, double bys,
483 		      datecode_t date, unsigned int hr, unsigned int min,
484 		      datecode_t newdate, unsigned int newhr,
485 		      unsigned int newmin, char graphby) {
486   extern unsigned int *rep2busystr;
487 
488   char **lngstr = od->lngstr;
489   char sepchar = od->sepchar;
490 
491   unsigned int bmult;
492   char *s;
493 
494   fprintf(outf, "\n%s %s (", lngstr[rep2busystr[rep]],
495 	  datesprintf(od, datefmt, date, hr, min, newdate, newhr, newmin,
496 		      TRUE, UNSET));
497   if (TOLOWER(graphby) == 'r') {
498     f3printf(outf, od, (double)reqs, 0, sepchar);
499     fprintf(outf, " %s).\n", (reqs == 1)?lngstr[request_]:lngstr[requests_]);
500   }
501   else if (TOLOWER(graphby) == 'p') {
502     f3printf(outf, od, (double)pages, 0, sepchar);
503     fprintf(outf, " %s).\n",
504 	    (pages == 1)?lngstr[pagereq_]:lngstr[pagereqs_]);
505   }
506   else /* TOLOWER(graphby) == 'b' */ {
507     if (od->rawbytes)
508       bmult = 0;
509     else
510       bmult = findbmult(bys, od->bytesdp);
511     printbytes(outf, od, bys, bmult, 0, sepchar);
512     putc(' ', outf);
513     if (bmult >= 1) {
514       s = strchr(lngstr[xbytes_], '?');  /* checked in initialisation */
515       *s = '\0';
516       fprintf(outf, "%s%s%s).\n", lngstr[xbytes_],
517 	      lngstr[byteprefix_ + bmult], s + 1);
518       *s = '?';
519     }
520     else
521       fprintf(outf, "%s).\n", lngstr[bytes_]);
522   }
523 }
524 
525 /* End of "Not listed" line. */
plain_notlistedstr(FILE * outf,Outchoices * od,choice rep,unsigned long badn)526 void plain_notlistedstr(FILE *outf, Outchoices *od, choice rep,
527 			unsigned long badn) {
528   extern unsigned int *rep2lng, *rep2colhead;
529 
530   char **lngstr = od->lngstr;
531   char *colhead = lngstr[rep2colhead[rep]];
532   char *colheadp = lngstr[rep2colhead[rep] + 1];
533   char gender = lngstr[rep2lng[rep] + 3][0];
534 
535   char *notlistedstr;
536 
537   if (gender == 'm')
538     notlistedstr = lngstr[notlistedm_];
539   else if (gender == 'f')
540     notlistedstr = lngstr[notlistedf_];
541   else
542     notlistedstr = lngstr[notlistedn_];
543 
544   fprintf(outf, "[%s: ", notlistedstr);
545   f3printf(outf, od, (double)badn, 0, od->sepchar);
546   fprintf(outf, " %s]", (badn == 1)?colhead:colheadp);
547 }
548 
549 /* The line declaring the floor and sort for a report */
plain_whatincluded(FILE * outf,Outchoices * od,choice rep,unsigned long n,Dateman * dman)550 void plain_whatincluded(FILE *outf, Outchoices *od, choice rep,
551 			unsigned long n, Dateman *dman) {
552   whatincluded(outf, od, rep, n, dman);
553 }
554 
555 /* Spacing at the start of the whatincluded line */
plain_whatinchead(FILE * outf,Outchoices * od)556 void plain_whatinchead(FILE *outf, Outchoices *od) {
557 }
558 
559 /* Finishing the whatincluded line */
plain_whatincfoot(FILE * outf,Outchoices * od)560 void plain_whatincfoot(FILE *outf, Outchoices *od) {
561   mprintf(outf, 0, NULL);
562 }
563 
564 /* Printing part of the whatincluded line */
plain_whatincprintstr(FILE * outf,Outchoices * od,char * s)565 void plain_whatincprintstr(FILE *outf, Outchoices *od, char *s) {
566   mprintf(outf, od->plainpagewidth, "%s", s);
567 }
568 
569 /* Print a double to a nice number of decimal places */
570 /* plain_printdouble always uses mprintf */
plain_printdouble(FILE * outf,Outchoices * od,double x)571 void plain_printdouble(FILE *outf, Outchoices *od, double x) {
572   unsigned int pagewidth;
573   char decpt;
574   unsigned int prec;
575   double d;
576 
577   if (od == NULL) {
578     pagewidth = 1;
579     decpt = '.';
580   }
581   else {
582     pagewidth = od->plainpagewidth;
583     decpt = od->decpt;
584   }
585 
586   /* first calculate how many decimal places we need */
587 
588   for (prec = 0, d = x - (double)((int)(x));
589        d - (double)((int)(d + 0.000005)) > 0.00001; d *= 10)
590     prec++;
591 
592   /* now print it */
593 
594   if (prec > 0)
595     mprintf(outf, pagewidth, "%d%c%0*d", (int)x, decpt, prec,
596 	    (int)(d + EPSILON));
597   else
598     mprintf(outf, pagewidth, "%d", (int)(x + EPSILON));
599 }
600 
601 /* Include a header file or footer file */
plain_includefile(FILE * outf,Outchoices * od,char * name,char type)602 void plain_includefile(FILE *outf, Outchoices *od, char *name, char type) {
603   FILE *inf;
604   char buffer[BLOCKSIZE];
605   size_t n;
606 
607   if ((inf = my_fopen(name, (type == 'h')?"header file":"footer file")) !=
608       NULL) {
609     if (type == 'f')
610       plain_hrule(outf, od);
611     while ((n = fread(buffer, 1, BLOCKSIZE, inf)))  /* single equals */
612       fwrite((void *)buffer, 1, n, outf);
613     if (type == 'h')
614       plain_hrule(outf, od);
615     (void)my_fclose(inf, name, (type == 'h')?"header file":"footer file");
616   }
617 }
618 
619 /* Filetype for RISC OS */
plain_riscosfiletype(void)620 unsigned int plain_riscosfiletype(void) {
621   return 0xfff;
622 }
623