/* field functions for pptop

   Copyright (C) 2002 James A. Morrison.

   Written by James A. Morrison <ja2morri@uwaterloo.ca>

   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 the Free Software Foundation; either version 2, or (at
   your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA */


#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <error.h>

#include "aux.h"

int fields_size;
int fmt_length;
char **fields;

/* returns the placement of the field that was added or removed.
   if PLACEMENT == -1, then the field will be removed.
*/
int
add_remove_field (char *field, int placement)
{
  if (placement == -1)
    {
      int i = 0, state = 0;
      for (; i < fields_size; i++)
	{
	  if (state)
	    fields[i - 1] = fields[i];
	  else if (fields[i] && !strcmp (field, fields[i]))
	    {
	      fmt_length -= strlen (field) + 2;
	      placement = state = i;
	      free (fields[i]);
	    }
	}
    }
  else
    {
      int i = placement;
      char *tmp = strdup (field);
      for (; i < fields_size; i++)
	{
	  char *cur = fields[i];
	  fields[i] = tmp;
	  tmp = cur;
	  if ((i == fields_size - 1) && fields[i])
	    {
	      int j = fields_size;
	      fields_size *= 2;
	      fields = realloc (fields, fields_size * sizeof (char *));
	      if (!fields)
		{
		  undo_curses ();
		  error (1, errno, "Cannot allocate space for fields");
		}
	      for (; j < fields_size; j++)
		fields[j] = '\0';
	      break;
	    }
	}
      fmt_length += strlen (field) + 2;
    }
  return placement;
}

char *get_fields (void)
{
  char *to_ret = (char *) calloc (fmt_length, 1);
  if (!to_ret)
    return NULL;
  int i = 0;

  strcat (to_ret, "%^");
  for (;i < fields_size && fields[i]; i++)
    {
      strcat (to_ret, " %");
      strcat (to_ret, fields[i]);
    }
  to_ret[fmt_length - 1] = '\0';;

  return to_ret;
}

error_t
setup_fields (void)
{
  fields = (char **) calloc (16 * sizeof (char *), 1);
  if (!fields)
    return ENOMEM;
  fields_size = 16;

  fields[0] = strdup ("user");
  fields[1] = strdup ("pid");
  fields[2] = strdup ("state");
  fields[3] = strdup ("cpu");
  fields[4] = strdup ("mem");
  fields[5] = strdup ("rss");
  fields[6] = strdup ("sz");
  fields[7] = strdup ("Time");
  fields[8] = strdup ("commandline");
  fields[9] = NULL;

  fmt_length = 2 + 6 + 5 + 7 + 5 + 5 + 5 + 4 + 6 + 13 + 1;

  return 0;
}
