#define MAXCOLORTC
#include "wingraph.h"

struct SharedData  // Разделяемая структура данных
{
  char fig; // Фигура, y-координату которой надо изменить (значения: a, b, c, d)
  char sign; // Показывает, увеличить или уменьшить y-координату фигуры (значения: +, -)
  int stop; // = 1, если была команда выхода из программы
};

SharedData *p; // указатель на разделяемую структуру данных
HANDLE hMap; // Описатель объекта, возвращаемый функцией CreateFileMapping()

int x1; // Координата x 1-й окружности
int r1; // Радиус 1-ой окружности

void ExitPr() // функция для завершения процесса
{
  UnmapViewOfFile (p); // освобождаем все ресурсы
  CloseHandle (hMap);
  ExitProcess (0);
}

// Проверяет, пересекает ли первая окружность линию x = 320
int CirclesX320()
{
  const int x = 320;
  if (x1 - r1 <= x && x1 + r1 >= x)
    return 1;
  return 0;
}

void ShowCircle1() // нить для 1-й окружности
{
  int y = 40;
  r1 = 20;
  int del = 1000 / 10; // задержка
  x1 = 200;
  int dx = 1;
  while (x1 <= getmaxx() - 40)
  {
    circle(x1, y, r1, RGB(0, 200, 0)); // рисуем окружность
    delay(del);
    circle(x1, y, r1, RGB(255, 255, 255)); // стираем окружность
    if (p->fig == 'a') // если пришла команда изменить у-координату
    {
      if (p->sign == '+')
        y += 10;
      else
        y -= 10;
      p->fig = ' ';
      p->sign = ' ';
    }
    if (p->stop) // если пришла команда завершить процесс
      ExitPr();
    x1 += dx;
  }
}

void ShowCircle2() // нить для 2-й окружности
{
  int y = 140;
  int r = 20; // Радиус
  int del = 1000 / 10; // задержка
  int x = getmaxx() - 40;
  int dx = -1;
  while (x >= 40)
  {
    circle(x, y, r, RGB(0, 200, 0)); // рисуем окружность
    delay(del);
    circle(x, y, r, RGB(255, 255, 255)); // стираем окружность
    if (p->fig == 'b') // если пришла команда изменить у-координату
    {
      if (p->sign == '+')
        y += 10;
      else
        y -= 10;
      p->fig = ' ';
      p->sign = ' ';
    }
    if (p->stop) // если пришла команда завершить процесс
      ExitPr();
    x += dx;
  }
}

void ShowSquare1() // нить для 1-го квадрата
{
  int y = 220;
  int len = 30; // Длина стороны
  int del = 1000 / 20; // задержка
  int colors[] = {RGB(0, 0, 255), RGB(255, 0, 0)};
  int color = 0;
  int x = 20;
  int dx = 1;
  while (x <= getmaxx() - 60)
  {
    rectangle(x, y, x + len, y + len, colors[color]); // рисуем квадрат
    delay(del);
    rectangle(x, y, x + len, y + len, RGB(255, 255, 255)); // стираем квадрат
    if (p->fig == 'c') // если пришла команда изменить у-координату
    {
      if (p->sign == '+')
        y += 10;
      else
        y -= 10;
      p->fig = ' ';
      p->sign = ' ';
    }
    if (CirclesX320()) // Если первая окружность пересекает линию x = 320
      color = 1 - color;
    if (p->stop) // если пришла команда завершить процесс
      ExitPr();
    x += dx;
  }
}

void ShowSquare2() // нить для 2-го квадрата
{
  int y = 300;
  int len = 30; // Длина стороны
  int del = 1000 / 40; // задержка
  int colors[] = {RGB(0, 0, 255), RGB(255, 0, 0)};
  int color = 0;
  int x = getmaxx() - 60;
  int dx = -1;
  while (x >= 20)
  {
    rectangle(x, y, x + len, y + len, colors[color]); // рисуем квадрат
    delay(del);
    rectangle(x, y, x + len, y + len, RGB(255, 255, 255)); // стираем квадрат
    if (p->fig == 'd') // если пришла команда изменить у-координату
    {
      if (p->sign == '+')
        y += 10;
      else
        y -= 10;
      p->fig = ' ';
      p->sign = ' ';
    }
    if (CirclesX320()) // Если первая окружность пересекает линию x = 320
      color = 1 - color;
    if (p->stop) // если пришла команда завершить процесс
      ExitPr();
    x += dx;
  }
}

void mainx ()
{
  char buf[100];
  int size;
  // берем значение размера окна из переменной окружения, которую устанавливает
  // программа p2
  if (GetEnvironmentVariable ("WINDOWSIZE", buf, 100))
    size = atoi(buf);
  else
    size = 600;
  resize(size, size); // Меняем размер окна
  char str[40];
  // читаем переменную окружения с информацией об описателе объекта с разделяемыми
  // данными
  if (GetEnvironmentVariable ("hMap", str, 40))
    hMap = (HANDLE) atoi (str);
  else
    ExitProcess (1);
  // строим отображение объекта
  p = (SharedData*) MapViewOfFile (hMap, FILE_MAP_WRITE,
    0, 0, sizeof(SharedData));
  if (p == 0)
    ExitProcess (2);

  // создаем отдельные нити для всех фигур
  CreateThread (0, 0, (LPTHREAD_START_ROUTINE) ShowCircle1, 0, 0, 0);
  CreateThread (0, 0, (LPTHREAD_START_ROUTINE) ShowCircle2, 0, 0, 0);
  CreateThread (0, 0, (LPTHREAD_START_ROUTINE) ShowSquare1, 0, 0, 0);
  CreateThread (0, 0, (LPTHREAD_START_ROUTINE) ShowSquare2, 0, 0, 0);
}
