#include <stdio.h>

/*
  (2w+2h-4)/0  1     ..    w-2  w-1
              +---------------+ 
      2w+2h-5 |               | w
            . |               | .
            . |               | .
            . |               | .
       2w+h-2 |               | w+h-3
              +---------------+
       2w+h-3  2w+h-4 .. w+h-1  w+h-2
*/

int EnvelopeLength(int w, int h)
{
  if (w <= 0 || h <= 0)
    return 0;

  if (h == 1)
    return w;

  if (w == 1)
    return h;

  return 2 * (w + h) - 4;
}

#if 0 // this function is currently unused
int Coords2EnvelopePosition(int x, int y, int w, int h)
{
  int pos = -1;
  if (w <= 0 || h <= 0)
    pos = -1;
  else if (w == 1 && h == 1)
    pos = 0;
  else if (h == 1)
    pos = x;
  else if (w == 1)
    pos = y;
  else if (y == 0)
    pos = x;
  else if (x == w - 1)
    pos = w + y - 1;
  else if (y == h - 1)
    pos = 2 * w + h - x - 3;
  else if (x == 0)
    pos = 2 * w + 2 * h - y - 4;
  return pos;
}
#endif

void EnvelopePosition2Coords(int* px, int* py, int w, int h, int pos)
{
  *py = *px = -1;
  if (w <= 0 || h <= 0)
    *py = *px = -1;
  else if (w == 1 && h == 1)
    *py = *px = 0;
  else if (h == 1)
    *px = pos, *py = 0;
  else if (w == 1)
    *px = 0, *py = pos;
  else if (pos < w)
    *px = pos, *py = 0;
  else if (pos <= w + h - 2)
    *px = w - 1, *py = pos - w + 1;
  else if (pos <= 2 * w + h - 3)
    *px = 2 * w + h - 3 - pos, *py = h - 1;
  else if (pos <= 2 * w + 2 * h - 5)
    *px = 0, *py = 2 * w + 2 * h - 4 - pos;
}

void SpiralShift(char* a, int w, int h)
{
  int w0 = w;

  while (w > 0 && h > 0)
  {
    int len = EnvelopeLength(w, h), pos;
    int xto, yto, xfrom, yfrom;

    for (pos = 0; pos < len - 1; pos++)
    {
      EnvelopePosition2Coords(&xto, &yto, w, h, pos);
      EnvelopePosition2Coords(&xfrom, &yfrom, w, h, pos + 1);
      a[yto * w0 + xto] = a[yfrom * w0 + xfrom];
    }

    EnvelopePosition2Coords(&xto, &yto, w, h, len - 1);

    if (w > 2 && h > 2)
    {
      EnvelopePosition2Coords(&xfrom, &yfrom, w - 2, h - 2, 0);
      a[yto * w0 + xto] = a[w0 + 1 + yfrom * w0 + xfrom];
      w -= 2;
      h -= 2;
      a += w0 + 1;
    }
    else
    {
      a[yto * w0 + xto] = ' ';
      break;
    }
  }
}

void PrintSpiral(const char*s, int w, int h)
{
  int x, y;
  puts("Spiral:");
  for (y = 0; y < h; y++)
  {
    for (x = 0; x < w; x++)
      printf("%c ", s[y * w + x]);
    puts("");
  }
  puts("");
}

int main(void)
{
  char spiral1x1[1 * 1] =
    "a";
  char spiral2x2[2 * 2] =
    "wo"
    "dr";
  char spiral5x6[5 * 6] =
    "This i"
    "ing ss"
    "lce.e "
    "lnetna"
    "arips ";
  int i;

  PrintSpiral(spiral1x1, 1, 1);
  for (i = 0; i < 1 * 1; i++)
  {
    SpiralShift(spiral1x1, 1, 1);
    PrintSpiral(spiral1x1, 1, 1);
  }

  PrintSpiral(spiral2x2, 2, 2);
  for (i = 0; i < 2 * 2; i++)
  {
    SpiralShift(spiral2x2, 2, 2);
    PrintSpiral(spiral2x2, 2, 2);
  }

  PrintSpiral(spiral5x6, 6, 5);
  for (i = 0; i < 5 * 6; i++)
  {
    SpiralShift(spiral5x6, 6, 5);
    PrintSpiral(spiral5x6, 6, 5);
  }
  return 0;
}
