#include "copyright.h"
#include "galaxy.h"

char            outbuf[256];
int             outi;

#ifdef __STDC__
void 
rnl (void)
#else
void 
rnl ()
#endif
{
   int             i;
   int             rc, vc;

   i = outi;
   while (i && isspace(outbuf[i - 1]))
      i--;
   outbuf[i] = 0;
   i = 0;
   rc = 0;
   vc = 0;
   while (outbuf[i]) {
      switch (outbuf[i]) {
      case ' ':
         vc++;
         break;
      case '\t':
         vc = (vc & ~7) + 8;
         break;
      default:
         while (rc / 8 != vc / 8) {
            if ((rc & 7) == 7)
               fputc(' ', f);
            else
               fputc('\t', f);
            rc = (rc & ~7) + 8;
         }
         while (rc != vc) {
            fputc(' ', f);
            rc++;
         }
         fputc(outbuf[i], f);
         rc++;
         vc++;
      }
      i++;
   }
   fputc('\n', f);
   outi = 0;
}

#ifdef __STDC__
void 
rpc (int c)
#else
void 
rpc (c)
int c;
#endif
{
   outbuf[outi++] = c;
   assert(outi < sizeof outbuf);
}

#ifdef __STDC__
void 
rps (char *s)
#else
void 
rps (s)
char *s;
#endif
{
   while (*s)
      rpc(*s++);
}


#ifdef __STDC__
void 
spf (char *s, double x)
#else
void 
spf (s, x)
char *s;
double x;
#endif
{
   sprintf(s, "%0.2lf", x);
   ftrunc3();
}

#ifdef __STDC__
void 
rpf (double x)
#else
void 
rpf (x)
double x;
#endif
{
   spf(buf, x);
   rps(buf);
}

#ifdef __STDC__
void 
ckunderscores (char *s)
#else
void 
ckunderscores (s)
char *s;
#endif
{
   if (underscores)
      while (*s) {
         if (*s == ' ')
            *s = '_';
         s++;
      }
}

char           *fheading;
int             fnfields, ffield;
char           *ftypes;
strlist        *fdata;
strlist       **flast;
char           *flabels;

#ifdef __STDC__
void 
fbegin (char *heading, char *types)
#else
void 
fbegin (heading, types)
char *heading;
char *types;
#endif
{
   fheading = strdup(heading);
   ffield = fnfields = strlen(types);
   ftypes = types;
   fdata = 0;
   flast = &fdata;
}

#ifdef __STDC__
void 
fs (char *s)
#else
void 
fs (s)
char *s;
#endif
{
   static strlist *p;
   strlist        *p2;

   if (ffield == fnfields) {
      p2 = alloc(sizeof(strlist) + fnfields * sizeof(char *) - sizeof(char *));
      addlist2(flast, p2);
      p = p2;
      ffield = 0;
   }
   p->s[ffield] = strdup(s);
   ckunderscores(p->s[ffield]);
   ffield++;
}

#ifdef __STDC__
void 
ff (double a)
#else
void 
ff (a)
double a;
#endif
{
   sprintf(buf, "%0.2f", a);
   fs(buf);
}

#ifdef __STDC__
void 
fi (int n)
#else
void 
fi (n)
int n;
#endif
{
   sprintf(buf, "%d", n);
   fs(buf);
}

#ifdef __STDC__
void 
space (int n)
#else
void 
space (n)
int n;
#endif
{
   while (--n >= 0)
      rpc(' ');
}

#ifdef __STDC__
void 
fend (void)
#else
void 
fend ()
#endif
{
   int             i, j, l, trunc, nlines, cn, cl, n, w;
   strlist        *p;
   static strlist *v[20];
   static char     width[20][50];
   char           *s;

   *flast = 0;

   nlines = 0;
   for (p = fdata; p; p = p->next)
      nlines++;

   if (nlines) {
      /* Print heading */

      rnl();
      rps("\t\t");
      rps(fheading);
      rnl();
      rnl();

      /* Truncate trailing decimals from floating-point numbers */

      for (i = 0; i != fnfields; i++)
         if (ftypes[i] == 'f') {
            trunc = 1;
            for (p = fdata; p; p = p->next)
               if (p->s[i][0] && p->s[i][strlen(p->s[i]) - 1] != '0')
                  trunc = 0;
            if (trunc) {
               for (p = fdata; p; p = p->next)
                  if (p->s[i][0])
                     p->s[i][strlen(p->s[i]) - 1] = 0;
               for (p = fdata; p; p = p->next)
                  if (p->s[i][0] && p->s[i][strlen(p->s[i]) - 1] != '0')
                     trunc = 0;
               if (trunc)
                  for (p = fdata; p; p = p->next)
                     if (p->s[i][0] && p->s[i][1])
                        p->s[i][strlen(p->s[i]) - 2] = 0;
            }
         }
      /* Decide how many columns will fit onto page */

      n = 0;
      do {      /* For each possible number of columns */
         n++;
         cl = (nlines + n - 1) / n;   /* Number of lines per
                      * column */
         p = fdata;
         w = -COLUMNSPACE;   /* Total width of all columns */
         cn = 0;
         do {   /* For each column */
            memset(width[cn], 0, sizeof width[cn]);

            /*
             * Determine maximum width of each field in
             * this column
             */

            for (i = cl; i && p; i--) {   /* For each line in this
                         * column */
               for (j = 0; j != fnfields; j++) {
                  l = strlen(p->s[j]);
                  if (l == 0)
                     l = 1;
                  if (l > width[cn][j])
                     width[cn][j] = l;
               }
               p = p->next;
            }

            /* Add field widths to total width */

            for (j = 0; j != fnfields; j++)
               w += width[cn][j];

            w += (fnfields - 1) * FIELDSPACE + COLUMNSPACE;

            cn++;
         }
         while (p);
      }
      while (twocol && (w <= PRINTWIDTH && n <= nlines));
      if (n != 1)
         n--;

      cl = (nlines + n - 1) / n;   /* Number of lines per column */

      /*
       * Calculate widths of fields for each column & print column
       * labels
       */

      p = fdata;
      cn = 0;
      do {      /* For each column */
         memset(width[cn], 0, sizeof width[cn]);

         for (i = cl; i && p; i--) {   /* For each line in this
                      * column */
            for (j = 0; j != fnfields; j++) {
               l = strlen(p->s[j]);
               if (l == 0)
                  l = 1;
               if (l > width[cn][j])
                  width[cn][j] = l;
            }
            p = p->next;
         }

         if (flabels) {   /* Print labels for this column */
            for (j = 0; j != fnfields; j++) {
               if (ftypes[j] == 'x') {
                  rpc(flabels[j]);
                  space(width[cn][j] - 1);
               } else {
                  space(width[cn][j] - 1);
                  rpc(flabels[j]);
               }
               space(FIELDSPACE);
            }
            space(COLUMNSPACE - FIELDSPACE);
         }
         cn++;
      }
      while (p);

      if (flabels)
         rnl();

      /* Set data pointers to start positions for each column */

      p = fdata;
      for (i = 0; i != n; i++) {
         v[i] = p;
         for (j = cl; j && p; j--)
            p = p->next;
      }

      /* Print data */

      for (i = cl; i; i--) {
         for (cn = 0; cn != n; cn++)
            if (v[cn]) {
               for (j = 0; j != fnfields; j++) {
                  s = v[cn]->s[j];
                  if (ftypes[j] == 'x') {
                     rps(s);
                     space(width[cn][j] - strlen(s));
                  } else {
                     space(width[cn][j] - strlen(s));
                     rps(s);
                  }
                  space(FIELDSPACE);
               }
               if (cn != n - 1)
                  space(COLUMNSPACE - FIELDSPACE);
               v[cn] = v[cn]->next;
            }
         rnl();
      }
   }
   /* Free allocated memory */

   for (p = fdata; p; p = p->next)
      for (i = 0; i != fnfields; i++)
         free(p->s[i]);
   freelist(fdata);

   free(fheading);

   flabels = 0;
}

#ifdef __STDC__
int
scrsize (double x, double y)
#else
int
scrsize (x, y)
double x;
double y;
#endif
{
   int             i;

   spf(buf, x);
   i = strlen(buf);
   spf(buf, y);
   return i + 1 + strlen(buf);
}

char            numberformat[10];
int             numbercount;

#ifdef __STDC__
void 
startnumber (int n)
#else
void 
startnumber (n)
int n;
#endif
{
   char            buf[10];

   sprintf(buf, "%d", n);
   sprintf(numberformat, "[%%%dd]", strlen(buf));
   numbercount = 0;
}

#ifdef __STDC__
char           *
donumber (int n)
#else
char           *
donumber (n)
int n;
#endif
{
   static char     buf[10];

   sprintf(buf, numberformat, n);
   return buf;
}

#ifdef __STDC__
char           *
countnumber (void)
#else
char           *
countnumber ()
#endif
{
   numbercount++;
   return donumber(numbercount);
}

#ifdef __STDC__
void 
printplanet (planet * p)
#else
void 
printplanet (p)
planet * p;
#endif
{
   fs(p->name);
   ff(p->x);
   ff(p->y);
   ff(p->size);
   ff(p->pop);
   ff(p->ind);
   ff(p->resources);
   if (p->producing == PR_SHIP)
      fs(p->producingshiptype->name);
   else
      fs(productname[p->producing]);
   ff(p->cap);
   ff(p->mat);
   ff(p->col);
}

void printproduction (planet *p)
{
   float mass;
   float theshipmass;
   float prog;

   if (p->producing == PR_SHIP) {
      fs (p->name);
      fs (p->producingshiptype->name);
      theshipmass = typemass(p->producingshiptype);
      mass = theshipmass*INDPERSHIP;
      prog = p->inprogress;
      if (theshipmass > p->mat)
         mass += (theshipmass - p->mat)/p->resources;
      ff (mass);
      ff (prog);
   }
}

#ifdef __STDC__
void 
printshiptype (shiptype * t)
#else
void 
printshiptype (t)
shiptype * t;
#endif
{
   fs(t->name);
   ff(t->drive);
   fi(t->attacks);
   ff(t->weapons);
   ff(t->shields);
   ff(t->cargo);
}

#ifdef __STDC__
void 
printgroup (player * P, group * g, int mode, int n)
#else
void 
printgroup (P, g, mode, n)
player * P;
group * g;
int mode;
int n;
#endif
{
   static char    *loadtypename[] =
   {
      "CAP",
      "MAT",
      "COL",
      "-",
   };

   if (mode == 2)
      fi(n);
   fi(g->ships);
   fs(g->type->name);
   ff(g->drive);
   ff(g->weapons);
   ff(g->shields);
   ff(g->cargo);
   fs(loadtypename[g->loadtype]);
   ff(g->load);
   if (mode) {
      fs(g->where->name);
      if (mode == 2) {
	 if (g->thefleet && !P->fleettables)
	    fs(g->thefleet->name);
	 if (!g->thefleet && !P->fleettables)
	    fs("-");
         if (g->dist)
            ff(g->dist);
         else
            fs("");
      }
   } 
   else
      fi(g->left);
}

