/* Miscellaneous support routines
   Copyright (C) 1993, 1994 Free Software Foundation

This file is part of the GNU Hurd.

The GNU Hurd 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.

The GNU Hurd 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 the GNU Hurd; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* Written by Michael I. Bushnell.  */

#include "term.h"
#include <string.h>

struct queue *
reallocate (struct queue *q)
{
  int shift_size;
  struct quote *qt, *nxt;
  
  if (qsize (q) > q->chars_alloced / 2)
    {
      if (qsize (q) < 3 * q->chars_alloced / 4)
	{
	  /* If we are using more than half, but not 3/4 of the space, then
	     make more space and get rid of the gap at the beginning */

	  struct queue *newq = malloc (sizeof (struct queue)
					+ q->chars_alloced * 2);
	  newq->qp = newq->chars;
	  newq->qs = newq->qp + qsize (q);
	  newq->chars_alloced = q->chars_alloced * 2;
	  newq->quoted = q->quoted;
	  memcpy (newq->chars, q->qs, qsize (q));
	  shift_size = q->qs - q->chars;
	  free (q);
	  q = newq;
	}
      else
	{
	  /* Just reallocate and don't try to compress the gap */
	  struct queue *newq = realloc (q, sizeof (struct queue)
					+ q->chars_alloced * 2);
	  newq->chars_alloced *= 2;
	  if (newq != q)
	    {	  
	      newq->qp = newq->chars + (newq->qp - q->chars);
	      newq->qs = newq->chars + (newq->qs - q->chars);
	    }
	  return newq;
	}
    }
  else
    {
      /* Compress the gap */
      shift_size = q->qs - q->chars;
      memmove (q->chars, q->qs, qsize (q));
      q->qs = q->chars;
      q->qp -= shift_size;
    }
  
  for (qt = q->quoted; qt; qt = nxt)
    {
      nxt = qt->next;
      if (qt->charno < shift_size)
	free (qt);
      else
	qt->charno -= shift_size;
    }
  
  return q;
}

void
clear_queue (struct queue *q)
{
  struct quote *qt, *nxt;
  
  q->qs = q->qp = q->chars;
  
  for (qt = q->quoted; qt; qt = nxt)
    {
      nxt = qt->next;
      free (qt);
    }
}

struct queue *
create_queue ()
{
  struct queue *q;
  
  q = malloc (sizeof (struct queue) + 512);
  
  q->qs = q->chars;
  q->qp = q->chars;
  q->chars_alloced = 512;
  q->quoted = 0;
  
  return q;
}
