Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include <menuet.h>
  2. #include <me_heap.h>
  3. #include <me_file.h>
  4. #include "lifegen.h"
  5. #include "life_bmp.h"
  6. #include "me_cdlg.h"
  7.  
  8. using namespace Menuet;
  9.  
  10. /***
  11. #define StrLen   LibbStrLen
  12. #define StrCopy  LibbStrCopy
  13. #define MemCopy  LibbMemCopy
  14. #define MemSet   LibbMemSet
  15. #define Floor    LibbFloor
  16.  
  17. unsigned int (*StrLen)(const char *str) = 0;
  18. char *(*StrCopy)(char *dest, const char *src) = 0;
  19. void *(*MemCopy)(void *dest, const void *src, unsigned int n) = 0;
  20. void *(*MemSet)(void *s, char c, unsigned int n) = 0;
  21. double (*Floor)(double x) = 0;
  22.  
  23. #include <windows.h>
  24. void LibbInit()
  25. {
  26.         HINSTANCE hLib = LoadLibrary("Libb.dll");
  27.         if (!hLib)
  28.         {
  29.                 DebugPutString("Can't load the library.\n");
  30.                 Menuet::Abort();
  31.         }
  32.         StrLen = (unsigned int(*)(const char *str))GetProcAddress(hLib, "StrLen");
  33.         StrCopy = (char *(*)(char *dest, const char *src))GetProcAddress(hLib, "StrCopy");
  34.         MemCopy = (void *(*)(void *dest, const void *src, unsigned int n))GetProcAddress(hLib, "MemCopy");
  35.         MemSet = (void *(*)(void *s, char c, unsigned int n))GetProcAddress(hLib, "MemSet");
  36.         Floor = (double (*)(double x))GetProcAddress(hLib, "Floor");
  37. }
  38.  
  39. #pragma startup LibbInit
  40. /**/
  41.  
  42. void __stdcall OneGeneration(int w, int h, void *dest, const void *src, int flag);
  43.  
  44. struct GenerateParam
  45. {
  46.         unsigned int gps;
  47.         unsigned int paint_time, time, count;
  48.         bool stop;
  49.         int paint;
  50.         double speed;
  51. };
  52.  
  53. struct AxisParam
  54. {
  55.         unsigned int win;
  56.         int p;
  57.         double shift;
  58. };
  59.  
  60. struct MouseParam
  61. {
  62.         int hit_x, hit_y, last_x, last_y;
  63.         int button, hit_type;
  64.  
  65.         enum {HitNull = 0, HitLine, HitCircle, HitScroll};
  66. };
  67.  
  68. struct MenuButtonParam
  69. {
  70.         int left, size, border;
  71.         bool check;
  72.         const unsigned char *bitmap;
  73.  
  74.         int Left() const {return left;}
  75.         int Right() const {return left + size;}
  76. };
  77.  
  78. const int MenuDig = 10;
  79.  
  80. struct MenuParam
  81. {
  82.         enum {Size = 20, NButton = 14};
  83.  
  84.         bool draw;
  85.         int pressed, current, edit;
  86.         int edit_index, edit_num[2], edit_num_max;
  87.         MenuButtonParam button[NButton];
  88.         const unsigned char *digit[MenuDig];
  89. };
  90.  
  91. struct TimeGeneration
  92. {
  93.         unsigned int t, g;
  94. };
  95.  
  96. enum MenuItem {MenuIHide, MenuIClear, MenuIOpen, MenuIAbout, MenuIExit,
  97.                                 MenuIGenerate, MenuIRandom, MenuIVCircle, MenuIHCircle,
  98.                                 MenuILine, MenuIScroll, MenuIWinSize, MenuISize, MenuISpeed};
  99.  
  100. enum {PaintWNull = 0, PaintWPole = 1, PaintWMenuBorder = 2, PaintWMenu = 6,
  101.                 PaintWSpeed = 8, PaintWAll = 15, PaintWFast = 64, PaintWNow = 128};
  102.  
  103. enum {TimeGenLength = 500};
  104.  
  105. unsigned char *life_data = 0, *picture = 0;
  106. GenerateParam generate = {0, 0, 0, 0, false, PaintWNull, 0};
  107. AxisParam xpar = {0, 0, 0};
  108. AxisParam ypar = {0, 0, 0};
  109. MouseParam mpar = {0, 0, 0, 0, 0, MouseParam::HitNull};
  110. MenuParam menu;
  111. TOpenFileStruct open_file_str = MENUET_OPEN_FILE_INIT;
  112. TimeGeneration timegen[TimeGenLength];
  113. int timegenpos = 0;
  114.  
  115. #ifdef __MENUET__
  116.  
  117. inline int abs(int i) {return (i >= 0) ? i : (-i);}
  118.  
  119. unsigned int rand_data[4];
  120.  
  121. void randomize()
  122. {
  123.         rand_data[0] = (unsigned int)Clock();
  124.         rand_data[1] = (unsigned int)GetPackedTime();
  125.         rand_data[2] = (unsigned int)GetPackedDate();
  126.         rand_data[3] = (unsigned int)0xA3901BD2 ^ GetPid();
  127. }
  128.  
  129. unsigned int rand()
  130. {
  131.         rand_data[0] ^= _HashDword(rand_data[3] + 0x2835C013U);
  132.         rand_data[1] += _HashDword(rand_data[0]);
  133.         rand_data[2] -= _HashDword(rand_data[1]);
  134.         rand_data[3] ^= _HashDword(rand_data[2]);
  135.         return rand_data[3];
  136. }
  137.  
  138. #define random(k)  (rand() % (k))
  139.  
  140. #else
  141.  
  142. #include <stdlib.h>
  143.  
  144. #endif
  145.  
  146. /*void DebugPutNumber(int x)
  147. {
  148.         char word[12], *w = word, *s, c;
  149.         int i;
  150.         if (x < 0) {*(w++) = '-'; x = -x;}
  151.         s = w;
  152.         do
  153.         {
  154.                 *(s++) = char('0' + (unsigned int)x % 10U);
  155.                 (unsigned int&)x /= 10U;
  156.         } while(x);
  157.         for (i = 0; w + i < s - 1 - i; i++)
  158.         {
  159.                 c = w[i]; w[i] = s[-1 - i]; s[-1 - i] = c;
  160.         }
  161.         *s = 0;
  162.         DebugPutString(word);
  163. }*/
  164.  
  165. bool SetPictureSize(int w = -1, int h = -1)
  166. {
  167.         if (w > 32767) w = 32767;
  168.         if (h > 32767) h = 32767;
  169.         if (w > 0) xpar.win = (unsigned short)w;
  170.         if (h > 0) ypar.win = (unsigned short)h;
  171.         if (picture) {Free(picture); picture = 0;}
  172.         if (w == 0 || h == 0 || xpar.win == 0 || ypar.win == 0) return true;
  173.         picture = (unsigned char*)Alloc(3 * xpar.win * ypar.win);
  174.         return picture != 0;
  175.  
  176. }
  177.  
  178. bool SetPoleSize(int w = -1, int h = -1)
  179. {
  180.         int s;
  181.         if (w > 32767) w = 32767;
  182.         if (h > 32767) h = 32767;
  183.         if (w > 0) xpar.p = (unsigned short)w;
  184.         if (h > 0) ypar.p = (unsigned short)h;
  185.         if (xpar.p < 4) xpar.p = 4;
  186.         if (ypar.p < 4) ypar.p = 4;
  187.         if (life_data) {Free(life_data); life_data = 0;}
  188.         if (w == 0 || h == 0) return true;
  189.         s = GetDataSize(xpar.p, ypar.p);
  190.         life_data = (unsigned char*)Alloc(2*s + DataMemAdd);
  191.         if (!life_data) return false;
  192.         MemSet(GetDataAddress(life_data), 0, s);
  193.         return true;
  194. }
  195.  
  196. int GetMenuHeight();
  197.  
  198. void GetPaintSize(int &w, int &h, int &xx, int &yy)
  199. {
  200.         int t = GetMenuHeight();
  201.         w = xpar.win; h = ypar.win - t;
  202.         xx = 0; yy = t;
  203. }
  204.  
  205. double GetAxisRatio(const AxisParam &par, int s)
  206. {
  207.         int t = par.p - s;
  208.         if (s <= 0 || t <= 0) return 0;
  209.         return double(t) / 2;
  210. }
  211.  
  212. void GetAxisShift(const AxisParam &par, int &s, int &k, int &kk)
  213. {
  214.         int t = par.p - s;
  215.         if (t < 0) {kk += (-t) / 2; t = 0; s = par.p;}
  216.         if (s <= 0 || t <= 0) k = 0;
  217.         else
  218.         {
  219.                 double r = double(t) / 2;
  220.                 k = (int)Floor(r * (1 + par.shift));
  221.                 if (k < 0) k = 0;
  222.                 else if (k > t) k = t;
  223.         }
  224. }
  225.  
  226. void GetPaintOrigin(int &w, int &h, int &x, int &y, int &xx, int &yy)
  227. {
  228.         GetPaintSize(w, h, xx, yy);
  229.         GetAxisShift(xpar, w, x, xx);
  230.         GetAxisShift(ypar, h, y, yy);
  231. }
  232.  
  233. void ApplyScroll(unsigned char *data1 = life_data, unsigned char *data0 = 0)
  234. {
  235.         if (!data0) data0 = data1;
  236.         data0 = (unsigned char*)GetDataAddress(data0);
  237.         data1 = (unsigned char*)GetDataAddress(data1);
  238.         const double min_ratio = 1e-2;
  239.         double r;
  240.         int w, h, xx, yy;
  241.         GetPaintSize(w, h, xx, yy);
  242.         xx = 0; yy = 0;
  243.         r = GetAxisRatio(xpar, w);
  244.         if (menu.button[MenuIHCircle].check)
  245.         {
  246.                 xx = mpar.hit_x - mpar.last_x + (int)Floor(xpar.shift * r + 0.5);
  247.                 xx %= xpar.p - 2;
  248.                 if (xx < 0) xx += xpar.p - 2;
  249.                 xpar.shift = 0;
  250.         }
  251.         else if (r < min_ratio) xpar.shift = 0;
  252.         else
  253.         {
  254.                 xpar.shift -= double(mpar.last_x - mpar.hit_x) / r;
  255.                 if (xpar.shift < -1) xpar.shift = -1;
  256.                 else if (xpar.shift > 1) xpar.shift = 1;
  257.         }
  258.         r = GetAxisRatio(ypar, h);
  259.         if (menu.button[MenuIVCircle].check)
  260.         {
  261.                 yy = mpar.hit_y - mpar.last_y + (int)Floor(ypar.shift * r + 0.5);
  262.                 yy %= ypar.p - 2;
  263.                 if (yy < 0) yy += ypar.p - 2;
  264.                 ypar.shift = 0;
  265.         }
  266.         else if (r < min_ratio) ypar.shift = 0;
  267.         else
  268.         {
  269.                 ypar.shift -= double(mpar.last_y - mpar.hit_y) / r;
  270.                 if (ypar.shift < -1) ypar.shift = -1;
  271.                 else if (ypar.shift > 1) ypar.shift = 1;
  272.         }
  273.         if (xx == 0 && yy == 0)
  274.         {
  275.                 if (data0 != data1) MemCopy(data0, data1, GetDataSize(xpar.p, ypar.p));
  276.         }
  277.         else
  278.         {
  279.                 int i, j;
  280.                 i = GetDataSize(xpar.p, ypar.p);
  281.                 if (data0 == data1)
  282.                 {
  283.                         data1 += i;
  284.                         MemCopy(data1, data0, i);
  285.                 }
  286.                 MemSet(data0, 0, i);
  287.                 APosPixel pixel0(xpar.p, ypar.p, data0);
  288.                 APosPixel pixel1(xpar.p, ypar.p, data1);
  289.                 for (i = 0; i < xpar.p; i++)
  290.                 {
  291.                         pixel0.SetTo(i, 0);
  292.                         pixel1.SetTo(xx, yy);
  293.                         j = ypar.p - yy;
  294.                         for (;;)
  295.                         {
  296.                                 if (pixel1.GetPixel()) pixel0.Set1Pixel();
  297.                                 if (--j == 0) break;
  298.                                 pixel0.AddY1(); pixel1.AddY1();
  299.                         }
  300.                         if (yy)
  301.                         {
  302.                                 pixel0.AddY1();
  303.                                 pixel1.SetTo(xx, 2);
  304.                                 j = yy;
  305.                                 for (;;)
  306.                                 {
  307.                                         if (pixel1.GetPixel()) pixel0.Set1Pixel();
  308.                                         if (--j == 0) break;
  309.                                         pixel0.AddY1(); pixel1.AddY1();
  310.                                 }
  311.                         }
  312.                         xx++;
  313.                         if (xx >= xpar.p) xx = 2;
  314.                 }
  315.         }
  316. }
  317.  
  318. void DrawLine(int x0, int y0, int x1, int y1, bool c, unsigned char *data0 = life_data)
  319. {
  320.         int i;
  321.         if (y0 == y1)
  322.         {
  323.                 if (x0 > x1) {i = x0; x0 = x1; x1 = i;}
  324.                 if (x1 < 0 || x0 >= xpar.p || y1 < 0 || y0 >= ypar.p) return;
  325.                 if (x0 < 0) x0 = 0;
  326.                 if (x1 >= xpar.p) x1 = xpar.p - 1;
  327.                 APosPixel pixel(xpar.p, ypar.p, data0, x0, y0);
  328.                 for (i = x1 - x0; i >= 0; pixel.AddX1(), i--) pixel.SetPixel(c);
  329.         }
  330.         else if (x0 == x1)
  331.         {
  332.                 if (y0 > y1) {i = y0; y0 = y1; y1 = i;}
  333.                 if (x1 < 0 || x0 >= xpar.p || y1 < 0 || y0 >= ypar.p) return;
  334.                 if (y0 < 0) y0 = 0;
  335.                 if (y1 >= ypar.p) y1 = ypar.p - 1;
  336.                 APosPixel pixel(xpar.p, ypar.p, data0, x0, y0);
  337.                 for (i = y1 - y0; i >= 0; pixel.AddY1(), i--) pixel.SetPixel(c);
  338.         }
  339.         else
  340.         {
  341.                 long dx = x1 - x0, dy = y1 - y0;
  342.                 int i;
  343.                 if (abs(dx) >= abs(dy))
  344.                 {
  345.                         if (dx < 0)
  346.                         {
  347.                                 i = x0; x0 = x1; x1 = i; dx = -dx;
  348.                                 y0 = y1; dy = -dy;
  349.                         }
  350.                         long vy = 0, b_x = dx / 2;
  351.                         APosPixel pixel(xpar.p, ypar.p, data0, x0, y0);
  352.                         for (i = x0;; i++, pixel.AddX1())
  353.                         {
  354.                                 pixel.SetPixel(c);
  355.                                 if (i >= x1) break;
  356.                                 vy += dy;
  357.                                 if (vy > b_x)
  358.                                 {
  359.                                         vy -= dx;
  360.                                         pixel.AddY1();
  361.                                 }
  362.                                 else if (vy < -b_x)
  363.                                 {
  364.                                         vy += dx;
  365.                                         pixel.SubY1();
  366.                                 }
  367.                         }
  368.                 }
  369.                 else
  370.                 {
  371.                         if (dy < 0)
  372.                         {
  373.                                 i = y0; y0 = y1; y1 = i; dy = -dy;
  374.                                 x0 = x1; dx = -dx;
  375.                         }
  376.                         long vx = 0, b_y = dy / 2;
  377.                         APosPixel pixel(xpar.p, ypar.p, data0, x0, y0);
  378.                         for (i = y0;; i++, pixel.AddY1())
  379.                         {
  380.                                 pixel.SetPixel(c);
  381.                                 if (i >= y1) break;
  382.                                 vx += dx;
  383.                                 if (vx > b_y)
  384.                                 {
  385.                                         vx -= dy;
  386.                                         pixel.AddX1();
  387.                                 }
  388.                                 else if (vx < -b_y)
  389.                                 {
  390.                                         vx += dy;
  391.                                         pixel.SubX1();
  392.                                 }
  393.                         }
  394.                 }
  395.         }
  396. }
  397.  
  398. void FillCircle(int x0, int y0, int r, bool c, unsigned char *data0 = life_data)
  399. {
  400.         int x = 0, y = r, v = 0;
  401.         while (x <= y)
  402.         {
  403.                 DrawLine(x0 - x, y0 + y, x0 + x, y0 + y, c, data0);
  404.                 if (y) DrawLine(x0 - x, y0 - y, x0 + x, y0 - y, c, data0);
  405.                 if (x < y)
  406.                 {
  407.                         DrawLine(x0 - y, y0 + x, x0 + y, y0 + x, c, data0);
  408.                         DrawLine(x0 - y, y0 - x, x0 + y, y0 - x, c, data0);
  409.                 }
  410.                 v += 2 * (x++) + 1;
  411.                 if (v >= y) v -= 2 * (y--) - 1;
  412.         }
  413. }
  414.  
  415. void RandomDraw(unsigned char *data0 = life_data)
  416. {
  417.         if (!data0 || random(300) >= 1) return;
  418.         int d = xpar.p;
  419.         if (d > ypar.p) d = ypar.p;
  420.         data0 = (unsigned char*)GetDataAddress(data0);
  421.         d = random((d * 3) / 4);
  422.         int x = random(xpar.p - d), y = random(ypar.p - d);
  423.         if (random(10) < 1)
  424.         {
  425.                 int NBusy, NTest = 4096;
  426.                 NBusy = 5 * xpar.p * ypar.p;
  427.                 if (NTest > NBusy) NTest = NBusy;
  428.                 NBusy = 0;
  429.                 for (int k = 0; k < NTest; k++)
  430.                 {
  431.                         if (GetDataBit(GetDataWidth(xpar.p), GetDataHeight(ypar.p), data0, random(xpar.p), random(ypar.p))) NBusy++;
  432.                 }
  433.                 if (NBusy * 100 < NTest)
  434.                 {
  435.                         if (random(3) == 0)
  436.                         {
  437.                                 DrawLine(x, y, x + d, y + d, true, data0);
  438.                                 DrawLine(x, y + d, x + d, y, true, data0);
  439.                         }
  440.                         else
  441.                         {
  442.                                 DrawLine(x + d/2, y, x + d/2, y + d, true, data0);
  443.                                 DrawLine(x, y + d/2, x + d, y + d/2, true, data0);
  444.                         }
  445.                         return;
  446.                 }
  447.         }
  448.         if (2*d < xpar.p && 2*d < ypar.p && random(10) < 3)
  449.         {
  450.                 FillCircle(x + d/2, y + d/2, d/2, false, data0);
  451.         }
  452.         else if (random(2)) DrawLine(x, y, x + d, y + d, true, data0);
  453.         else DrawLine(x, y + d, x + d, y, true, data0);
  454. }
  455.  
  456. void LineInScreen(int ax, int ay, int bx, int by, bool c, unsigned char *data0 = life_data)
  457. {
  458.         int mul = 1, sbeg, send, t0, t1;
  459.         if (ax != bx) mul *= abs(ax - bx);
  460.         if (ay != by) mul *= abs(ay - by);
  461.         sbeg = 0; send = mul;
  462.         if (ax != bx)
  463.         {
  464.                 t0 = ax * (mul / (ax - bx));
  465.                 t1 = (ax - xpar.p + 1) * (mul / (ax - bx));
  466.                 if (t0 < t1)
  467.                 {
  468.                         if (sbeg < t0) sbeg = t0;
  469.                         if (send > t1) send = t1;
  470.                 }
  471.                 else
  472.                 {
  473.                         if (sbeg < t1) sbeg = t1;
  474.                         if (send > t0) send = t0;
  475.                 }
  476.         }
  477.         else if (ax < 0 || ax >= xpar.p) return;
  478.         if (ay != by)
  479.         {
  480.                 t0 = ay * (mul / (ay - by));
  481.                 t1 = (ay - ypar.p + 1) * (mul / (ay - by));
  482.                 if (t0 < t1)
  483.                 {
  484.                         if (sbeg < t0) sbeg = t0;
  485.                         if (send > t1) send = t1;
  486.                 }
  487.                 else
  488.                 {
  489.                         if (sbeg < t1) sbeg = t1;
  490.                         if (send > t0) send = t0;
  491.                 }
  492.         }
  493.         else if (ay < 0 || ay > ypar.p) return;
  494.         if (send < sbeg) return;
  495.         DrawLine(ax + (bx - ax) * sbeg / mul, ay + (by - ay) * sbeg / mul,
  496.                         ax + (bx - ax) * send / mul, ay + (by - ay) * send / mul, c, data0);
  497. }
  498.  
  499. int GetRadius(int ax, int ay, int bx, int by)
  500. {
  501.         int s, t0, t1, t, tt;
  502.         bx -= ax; by -= ay;
  503.         s = bx*bx + by*by;
  504.         t0 = 0; t1 = s;
  505.         while (t0 + 1 < t1)
  506.         {
  507.                 t = (t0 + t1) / 2;
  508.                 tt = t*t;
  509.                 if (tt / t == t && s > tt + t) t0 = t; else t1 = t;
  510.         }
  511.         return t1;
  512. }
  513.  
  514. int ReadNumberFromString(const unsigned char *&str)
  515. {
  516.         int x = 0, s = 1;
  517.         while (*str == ' ' || *str == '\t' || *str == '\r') str++;
  518.         if (*str == '-') {s = -1; str++;}
  519.         else if (*str == '+') str++;
  520.         while (*str >= '0' && *str <= '9')
  521.         {
  522.                 x = 10*x + (*str - '0');
  523.                 str++;
  524.         }
  525.         return x*s;
  526. }
  527.  
  528. const unsigned char *StringPrefSpace(const unsigned char *pict, int size, const unsigned char *pref)
  529. {
  530.         const unsigned char *pict_end = pict + size;
  531.         for (;;)
  532.         {
  533.                 if (!*pref) return pict;
  534.                 else if (*pref == ' ')
  535.                 {
  536.                         if (pict >= pict_end || !(*pict == ' ' || *pict == '\t' || *pict == '\r')) return 0;
  537.                         while (pict < pict_end && (*pict == ' ' || *pict == '\t' || *pict == '\r')) pict++;
  538.                         pref++;
  539.                 }
  540.                 else if (*pref == '\n')
  541.                 {
  542.                         while (pict < pict_end && (*pict == ' ' || *pict == '\t' || *pict == '\r')) pict++;
  543.                         if (pict >= pict_end || *pict != '\n') return 0;
  544.                         pict++; pref++;
  545.                 }
  546.                 else if (pict >= pict_end || *pict != *pref) return 0;
  547.                 else {pict++; pref++;}
  548.         }
  549. }
  550.  
  551. int LifeGetPictureType(const unsigned char *&pict, int size)
  552. {
  553.         const unsigned char *p;
  554.         p = StringPrefSpace(pict, size, (const unsigned char*)"#LifeBin 2.0\n");
  555.         if (p && p + 4 <= pict + size) {pict = p; return 1;}
  556.         p = StringPrefSpace(pict, size, (const unsigned char*)"#Life 1.05\n");
  557.         if (p) {pict = p; return 2;}
  558.         if (size >= 54 && pict[0] == 'B' && pict[1] == 'M' && *(int*)(pict+6) == 0 &&
  559.                 *(int*)(pict+14) == 0x28 && *(short*)(pict+26) == 1 && *(int*)(pict+30) == 0 &&
  560.                 *(short*)(pict+28) > 0 && *(short*)(pict+28) <= 32 &&
  561.                 *(int*)(pict+18) >= 0 && *(int*)(pict+22) >= 0 &&
  562.                 *(int*)(pict+10) >= 54 && *(int*)(pict+10) <= *(int*)(pict+2) &&
  563.                 *(int*)(pict+2) <= size && *(int*)(pict+34) >= 0 &&
  564.                 *(int*)(pict+34) <= *(int*)(pict+2) - *(int*)(pict+10) &&
  565.                 *(int*)(pict+46) <= 256 && *(int*)(pict+50) <= *(int*)(pict+46) &&
  566.                 (*(short*)(pict+28) >= 8 || *(int*)(pict+46) <= (1 << *(short*)(pict+28))))
  567.         {
  568.                 if (*(int*)(pict+18) == 0 || *(int*)(pict+22) == 0) return 3;
  569.                 int s = *(int*)(pict+34);
  570.                 if (s == 0)
  571.                 {
  572.                         s = ((*(int*)(pict+18) * *(short*)(pict+28) - 1) / 32 + 1) * *(int*)(pict+22) * 4;
  573.                 }
  574.                 if (s > 0 && s <= *(int*)(pict+2) - *(int*)(pict+10))
  575.                 {
  576.                         s /= *(int*)(pict+22);
  577.                         if (s < (1 << 28) && (s * 8) / *(short*)(pict+28) >= *(int*)(pict+18)) return 3;
  578.                 }
  579.         }
  580.         return 0;
  581. }
  582.  
  583. void LifeGetPictureSize(int &w, int &h, const unsigned char *pict, int size)
  584. {
  585.         const unsigned char *pict_end = pict + size;
  586.         int type = LifeGetPictureType(pict, size);
  587.         w = 0; h = 0;
  588.         if (type == 1)
  589.         {
  590.                 w = (int)pict[0] + ((int)pict[1] << 8);
  591.                 h = (int)pict[2] + ((int)pict[3] << 8);
  592.         }
  593.         else if (type == 2)
  594.         {
  595.                 int x = 0, y = 0, xb = x;
  596.                 int x0 = 0, y0 = 0, x1 = -1, y1 = -1;
  597.                 while (pict < pict_end && *pict)
  598.                 {
  599.                         while (pict < pict_end && *pict == '\n') pict++;
  600.                         if (pict < pict_end && *pict == '#')
  601.                         {
  602.                                 pict++;
  603.                                 if (pict < pict_end && (*pict == 'p' || *pict == 'P'))
  604.                                 {
  605.                                         pict++;
  606.                                         x = ReadNumberFromString(pict);
  607.                                         y = ReadNumberFromString(pict);
  608.                                         xb = x;
  609.                                 }
  610.                                 while (pict < pict_end && *pict)
  611.                                 {
  612.                                         if (*pict == '\n') {pict++; break;}
  613.                                         pict++;
  614.                                 }
  615.                                 continue;
  616.                         }
  617.                         for (; pict < pict_end && *pict; pict++)
  618.                         {
  619.                                 if (*pict == '\n')
  620.                                 {
  621.                                         x = xb; y++;
  622.                                         if (pict + 1 < pict_end && pict[1] == '#') break;
  623.                                         continue;
  624.                                 }
  625.                                 else if (*pict == '\r') continue;
  626.                                 if (*pict == '*')
  627.                                 {
  628.                                         if (x0 > x) x0 = x;
  629.                                         if (x1 < x) x1 = x;
  630.                                         if (y0 > y) y0 = y;
  631.                                         if (y1 < y) y1 = y;
  632.                                 }
  633.                                 x++;
  634.                         }
  635.                 }
  636.                 x0 = -2*x0; x1 = 2*x1 + 1;
  637.                 y0 = -2*y0; y1 = 2*y1 + 1;
  638.                 w = (x0 < x1) ? x1 : x0;
  639.                 h = (y0 < y1) ? y1 : y0;
  640.         }
  641.         else if (type == 3)
  642.         {
  643.                 w = *(int*)(pict+18);
  644.                 h = *(int*)(pict+22);
  645.                 if (w == 0) h = 0;
  646.                 else if (h == 0) w = 0;
  647.         }
  648. }
  649.  
  650. void LifePutPicture(int x0, int y0, const unsigned char *pict, int size, unsigned char *data0 = life_data)
  651. {
  652.         const unsigned char *pict_end = pict + size;
  653.         int type = LifeGetPictureType(pict, size);
  654.         if (type == 1)
  655.         {
  656.                 int w = (int)pict[0] + ((int)pict[1] << 8);
  657.                 int h = (int)pict[2] + ((int)pict[3] << 8);
  658.                 if (w && h)
  659.                 {
  660.                         int i, j, x, y;
  661.                         pict += 4;
  662.                         x0 -= w / 2; y0 -= h / 2;
  663.                         x = x0 + w; y = y0 - 1;
  664.                         APosPixel pixel(xpar.p, ypar.p, data0);
  665.                         while (pict < pict_end)
  666.                         {
  667.                                 if (x >= x0 + w)
  668.                                 {
  669.                                         i = (x - x0) / w;
  670.                                         x -= i * w; y += i;
  671.                                         if (y >= y0 + h) break;
  672.                                         j = 0;
  673.                                         if (x >= 0 && x < xpar.p) j |= 1;
  674.                                         if (y >= 0 && y < ypar.p) j |= 2;
  675.                                         if (j == 3)     pixel.SetTo(x, y);
  676.                                 }
  677.                                 i = *(pict++);
  678.                                 if (i == 0)
  679.                                 {
  680.                                         if (j == 3) pixel.Set1Pixel();
  681.                                         i = 1;
  682.                                 }
  683.                                 x += i;
  684.                                 if ((j & 2) && x < x0 + w)
  685.                                 {
  686.                                         if (x >= 0 && x < xpar.p)
  687.                                         {
  688.                                                 if ((j & 1) && i < 5)
  689.                                                 {
  690.                                                         while (i--) pixel.AddX1();
  691.                                                 }
  692.                                                 else
  693.                                                 {
  694.                                                         j |= 1;
  695.                                                         pixel.SetTo(x, y);
  696.                                                 }
  697.                                         }
  698.                                         else j &= ~1;
  699.                                 }
  700.                         }
  701.                 }
  702.         }
  703.         else if (type == 2)
  704.         {
  705.                 int x = x0, y = y0, xb = x;
  706.                 while (pict < pict_end && *pict)
  707.                 {
  708.                         while (pict < pict_end && *pict == '\n') pict++;
  709.                         if (pict < pict_end && *pict == '#')
  710.                         {
  711.                                 pict++;
  712.                                 if (pict < pict_end && (*pict == 'p' || *pict == 'P'))
  713.                                 {
  714.                                         pict++;
  715.                                         x = x0 + ReadNumberFromString(pict);
  716.                                         y = y0 + ReadNumberFromString(pict);
  717.                                         xb = x;
  718.                                 }
  719.                                 while (pict < pict_end && *pict)
  720.                                 {
  721.                                         if (*pict == '\n') {pict++; break;}
  722.                                         pict++;
  723.                                 }
  724.                                 continue;
  725.                         }
  726.                         if (y >= ypar.p || x >= xpar.p)
  727.                         {
  728.                                 for (; pict < pict_end && *pict; pict++) if (*pict == '\n')
  729.                                 {
  730.                                         y++;
  731.                                         if (pict + 1 < pict_end && pict[1] == '#') break;
  732.                                 }
  733.                                 continue;
  734.                         }
  735.                         if (y < 0)
  736.                         {
  737.                                 for (; pict < pict_end && *pict; pict++) if (*pict == '\n')
  738.                                 {
  739.                                         y++;
  740.                                         if (y >= 0 || (pict + 1 < pict_end && pict[1] == '#')) break;
  741.                                 }
  742.                                 if (pict + 1 < pict_end && *pict == '\n' && pict[1] == '#') continue;
  743.                         }
  744.                         APosPixel pixel(xpar.p, ypar.p, data0);
  745.                         if (x >= 0) pixel.SetTo(x, y);
  746.                         for (; pict < pict_end && *pict; pict++)
  747.                         {
  748.                                 if (*pict == '\n')
  749.                                 {
  750.                                         x = xb; y++;
  751.                                         if (y >= ypar.p) break;
  752.                                         if (x >= 0) pixel.SetTo(x, y);
  753.                                         if (pict + 1 < pict_end && pict[1] == '#') break;
  754.                                         continue;
  755.                                 }
  756.                                 else if (*pict == '\r') continue;
  757.                                 if (*pict == '*') pixel.Set1Pixel();
  758.                                 x++;
  759.                                 if (x < 0) continue;
  760.                                 if (x >= xpar.p)
  761.                                 {
  762.                                         while (pict < pict_end && *pict && *pict != '\n') pict++;
  763.                                         if (pict < pict_end && *pict == '\n') pict--;
  764.                                         continue;
  765.                                 }
  766.                                 if (x == 0) pixel.SetTo(0, y);
  767.                                 else pixel.AddX1();
  768.                         }
  769.                 }
  770.         }
  771.         else if (type == 3)
  772.         {
  773.                 int w = *(int*)(pict+18), h = *(int*)(pict+22);
  774.                 if (w && h)
  775.                 {
  776.                         int n, i, j;
  777.                         unsigned char ch;
  778.                         const unsigned char *p = pict + *(int*)(pict+10);
  779.                         short bp = *(short*)(pict+28);
  780.                         int s = *(int*)(pict+34);
  781.                         x0 -= w / 2; y0 -= h / 2;
  782.                         if (x0 < xpar.p && y0 < ypar.p && x0 + w > 0 && y0 + h > 0)
  783.                         {
  784.                                 if (s) s /= *(int*)(pict+22);
  785.                                 else s = ((*(int*)(pict+18) * *(short*)(pict+28) - 1) / 32 + 1) * 4;
  786.                                 n = (*(int*)(pict+10) - 54) / 4;
  787.                                 APosPixel pixel(xpar.p, ypar.p, data0);
  788.                                 if (y0 + h <= ypar.p) i = h - 1;
  789.                                 else
  790.                                 {
  791.                                         i = ypar.p - y0 - 1;
  792.                                         p += (ypar.p - y0) * s;
  793.                                 }
  794.                                 for (; i >= 0; i--)
  795.                                 {
  796.                                         int tj = 0, tl = 0;
  797.                                         if (y0 + i < 0) break;
  798.                                         if (x0 > 0) pixel.SetTo(x0, y0 + i);
  799.                                         for (j = 0; j < 8*s; j += 8)
  800.                                         {
  801.                                                 if (tj >= w || x0 + tj >= xpar.p) {p += (s - j/8); break;}
  802.                                                 ch = *(p++);
  803.                                                 while (tj < w && x0 + tj < xpar.p && j + 8 >= (tj+1) * bp)
  804.                                                 {
  805.                                                         union
  806.                                                         {
  807.                                                                 long za;
  808.                                                                 unsigned char z[4];
  809.                                                         };
  810.  
  811.                                                         tl |= (unsigned long)(ch) >> ((int)j + 8 - (tj+1) * bp);
  812.                                                         if (n)
  813.                                                         {
  814.                                                                 if (tl >= n) za = 0;
  815.                                                                 else
  816.                                                                 {
  817.                                                                         const unsigned char *zp = pict + 54 + 4*tl;
  818.                                                                         z[0] = zp[3];
  819.                                                                         z[1] = zp[2];
  820.                                                                         z[2] = zp[1];
  821.                                                                         z[3] = zp[0];
  822.                                                                 }
  823.                                                         }
  824.                                                         else if (bp == 8)
  825.                                                         {
  826.                                                                 z[0] = 0;
  827.                                                                 z[1] = z[2] = z[3] = (char)tl;
  828.                                                         }
  829.                                                         else if (bp == 32) za = tl;
  830.                                                         else za = tl << (32 - bp);
  831.  
  832.                                                         if (x0 + tj >= 0)
  833.                                                         {
  834.                                                                 if (x0 + tj == 0) pixel.SetTo(0, y0 + i);
  835.                                                                 else pixel.AddX1();
  836.                                                                 if ((int)z[1] + (int)z[2] + (int)z[3] >= 384)
  837.                                                                 {
  838.                                                                         pixel.Set1Pixel();
  839.                                                                 }
  840.                                                         }
  841.  
  842.                                                         tl = 0;
  843.                                                         ch &= (unsigned char)((1 << ((int)j + 8 - (tj+1) * bp)) - 1);
  844.                                                         tj++;
  845.                                                 }
  846.                                                 tl |= (int)ch << ((tj+1) * bp - (j + 8));
  847.                                         }
  848.                                 }
  849.                         }
  850.                 }
  851.         }
  852. }
  853.  
  854. void ApplyHit(unsigned char *data1 = life_data, unsigned char *data0 = 0)
  855. {
  856.         if (!data0) data0 = data1;
  857.         if (!data0) return;
  858.         data0 = (unsigned char*)GetDataAddress(data0);
  859.         data1 = (unsigned char*)GetDataAddress(data1);
  860.         if (data0 != data1 && mpar.hit_type != MouseParam::HitScroll)
  861.         {
  862.                 MemCopy(data0, data1, GetDataSize(xpar.p, ypar.p));
  863.         }
  864.         switch (mpar.hit_type)
  865.         {
  866.         case MouseParam::HitLine:
  867.                 LineInScreen(mpar.hit_x, mpar.hit_y, mpar.last_x, mpar.last_y, true, data0);
  868.                 break;
  869.         case MouseParam::HitCircle:
  870.                 FillCircle(mpar.hit_x, mpar.hit_y,
  871.                                 GetRadius(mpar.hit_x, mpar.hit_y, mpar.last_x, mpar.last_y), false, data0);
  872.                 break;
  873.         case MouseParam::HitScroll:
  874.                 ApplyScroll(data1, data0);
  875.                 break;
  876.         }
  877. }
  878.  
  879. void MoveGenerateTime(unsigned int t)
  880. {
  881.         static const unsigned int COUNT_MAX = 1 << 24;
  882.  
  883.         if (generate.stop)
  884.         {
  885.                 if (generate.count > COUNT_MAX) generate.count = COUNT_MAX;
  886.         }
  887.         else if (!generate.gps) generate.count = COUNT_MAX;
  888.         else if (t > 100 || generate.count >= generate.gps)
  889.         {
  890.                 generate.count = generate.gps;
  891.         }
  892.         else if (t)
  893.         {
  894.                 generate.count += (generate.gps * t -
  895.                                         (((generate.time + t) % 100U) * generate.gps) % 100 +
  896.                                         ((generate.time % 100U) * generate.gps) % 100) / 100;
  897.                 if (generate.count > generate.gps) generate.count = generate.gps;
  898.         }
  899.         generate.time += t;
  900.         if (timegen[timegenpos].t > (~t)) timegen[timegenpos].t = -1;
  901.         else timegen[timegenpos].t += t;
  902. }
  903.  
  904. void ResetGenerate()
  905. {
  906.         generate.time = Clock();
  907.         generate.paint_time = generate.time - 100;
  908.         generate.count = 0;
  909.         if (generate.stop)
  910.         {
  911.                 generate.stop = false;
  912.                 menu.button[MenuIGenerate].check = false;
  913.         }
  914. }
  915.  
  916. void InitGenerate()
  917. {
  918.         int i;
  919.         for (i = 0; i < TimeGenLength; i++)
  920.         {
  921.                 timegen[timegenpos].t = -1;
  922.                 timegen[timegenpos].g = 0;
  923.         }
  924.         ResetGenerate();
  925. }
  926.  
  927. bool AddGenerateCount(int c)
  928. {
  929.         if (c < 0) return false;
  930.         if (!menu.button[MenuIGenerate].check)
  931.         {
  932.                 ResetGenerate();
  933.                 menu.button[MenuIGenerate].check = true;
  934.                 generate.paint |= PaintWMenuBorder | PaintWSpeed;
  935.                 generate.stop = true;
  936.                 generate.count += c;
  937.         }
  938.         else if (generate.stop) generate.count += c;
  939.         else return false;
  940.         return true;
  941. }
  942.  
  943. void InitMenuButton()
  944. {
  945.         int i;
  946.         const unsigned char *p = menu_picture, *p_end = menu_picture + sizeof(menu_picture);
  947.         const unsigned int separator = 5;
  948.         for (i = 0; i < MenuParam::NButton; i++)
  949.         {
  950.                 menu.button[i].left = 0;
  951.                 menu.button[i].size = MenuParam::Size - 2;
  952.                 menu.button[i].border = 2;
  953.                 menu.button[i].check = false;
  954.                 menu.button[i].bitmap = p;
  955.                 if (p && !p[0])
  956.                 {
  957.                         menu.button[i].bitmap = 0;
  958.                         if (p[1]) p = 0;
  959.                 }
  960.                 if (p)
  961.                 {
  962.                         p += 2 + 3 * (int)p[0] * (int)p[1];
  963.                         if (p > p_end) menu.button[i].bitmap = 0;
  964.                         if (p >= p_end) p = 0;
  965.                 }
  966.         }
  967.         p = digits_picture; p_end = digits_picture + sizeof(digits_picture);
  968.         for (i = 0; i < MenuDig; i++)
  969.         {
  970.                 menu.digit[i] = p;
  971.                 if (p && !p[0])
  972.                 {
  973.                         menu.digit[i] = 0;
  974.                         if (p[1]) p = 0;
  975.                 }
  976.                 if (p)
  977.                 {
  978.                         p += 2 + ((int)p[0] * (int)p[1] + 7) / 8;
  979.                         if (p > p_end) menu.digit[i] = 0;
  980.                         if (p >= p_end) p = 0;
  981.                 }
  982.         }
  983.         menu.draw = false;
  984.         menu.pressed = -1;
  985.         menu.current = MenuILine;
  986.         menu.edit = -1;
  987.         menu.button[menu.current].check = true;
  988.         menu.button[MenuIHide].size /= 2;
  989.         menu.button[MenuIGenerate].left += separator;
  990.         menu.button[MenuIGenerate].check = true;
  991.         menu.button[MenuIRandom].check = true;
  992.         menu.button[MenuILine].left += separator;
  993.         menu.button[MenuIWinSize].left += separator;
  994.         menu.button[MenuISize].size += 80;
  995.         menu.button[MenuISpeed].left += separator;
  996.         menu.button[MenuISpeed].size += 60;
  997.         menu.button[0].left = 1;
  998.         for (i = 1; i < MenuParam::NButton; i++)
  999.         {
  1000.                 menu.button[i].left += menu.button[i-1].left + menu.button[i-1].size;
  1001.         }
  1002. }
  1003.  
  1004. int GetMenuYPos()
  1005. {
  1006.         return 0;
  1007. }
  1008.  
  1009. int GetMenuHeight()
  1010. {
  1011.         if (!menu.draw) return 0;
  1012.         return (ypar.win <= MenuParam::Size) ? 0 : MenuParam::Size;
  1013. }
  1014.  
  1015. int GetMenuNumber(int k, int i)
  1016. {
  1017.         if (k == menu.edit) return menu.edit_num[i];
  1018.         switch (k)
  1019.         {
  1020.         case MenuISize:
  1021.                 return i ? ypar.p : xpar.p;
  1022.         case MenuISpeed:
  1023.                 return menu.button[MenuIGenerate].check ? (int)Floor(generate.speed + 0.5) : 0;
  1024.         default:
  1025.                 return 0;
  1026.         }
  1027. }
  1028.  
  1029. void WinDrawRect(int x, int y, int w, int h, const unsigned char *const *color)
  1030. {
  1031.         unsigned char *p = picture + 3 * (y * xpar.win + x);
  1032.         int j;
  1033.         w--; h--;
  1034.         for (j = w; j > 0; j--)
  1035.         {
  1036.                 p[0] = color[0][0]; p[1] = color[0][1]; p[2] = color[0][2];
  1037.                 p += 3;
  1038.         }
  1039.         for (j = h; j > 0; j--)
  1040.         {
  1041.                 p[0] = color[1][0]; p[1] = color[1][1]; p[2] = color[1][2];
  1042.                 p += 3 * xpar.win;
  1043.         }
  1044.         for (j = w; j > 0; j--)
  1045.         {
  1046.                 p[0] = color[2][0]; p[1] = color[2][1]; p[2] = color[2][2];
  1047.                 p -= 3;
  1048.         }
  1049.         for (j = h; j > 0; j--)
  1050.         {
  1051.                 p[0] = color[3][0]; p[1] = color[3][1]; p[2] = color[3][2];
  1052.                 p -= 3 * xpar.win;
  1053.         }
  1054. }
  1055.  
  1056. void WinFillRect(int x, int y, int w, int h, const unsigned char *color)
  1057. {
  1058.         if (x >= xpar.win || y >= ypar.win || w <= 0 || h <= 0) return;
  1059.         if (w > xpar.win - x) w = xpar.win - x;
  1060.         if (h > ypar.win - y) h = ypar.win - y;
  1061.         unsigned char *p, *pp = picture + 3 * (y * xpar.win + x);
  1062.         int i, j;
  1063.         for (i = h; i > 0; i--)
  1064.         {
  1065.                 p = pp;
  1066.                 for (j = w; j > 0; j--)
  1067.                 {
  1068.                         *(p++) = color[0]; *(p++) = color[1]; *(p++) = color[2];
  1069.                 }
  1070.                 pp += 3 * xpar.win;
  1071.         }
  1072. }
  1073.  
  1074. void WinBitmapRect(int x, int y, const unsigned char *bmp)
  1075. {
  1076.         if (!bmp || !bmp[0] || !bmp[1]) return;
  1077.         int w = bmp[0], h = bmp[1], strl = 3 * (int)bmp[0];
  1078.         bmp += 2;
  1079.         x -= w/2; y -= h/2;
  1080.         if (x >= xpar.win || y >= ypar.win) return;
  1081.         if (w > xpar.win - x) w = xpar.win - x;
  1082.         if (h > ypar.win - y) h = ypar.win - y;
  1083.         unsigned char *p, *pp = picture + 3 * (y * xpar.win + x);
  1084.         const unsigned char *b;
  1085.         int i, j;
  1086.         for (i = h; i > 0; i--)
  1087.         {
  1088.                 p = pp; b = bmp;
  1089.                 for (j = w; j > 0; j--)
  1090.                 {
  1091.                         *(p++) = *(b++); *(p++) = *(b++); *(p++) = *(b++);
  1092.                 }
  1093.                 pp += 3 * xpar.win; bmp += strl;
  1094.         }
  1095. }
  1096.  
  1097. void WinBitSetRect(int x, int y, const unsigned char *set, const unsigned char *color)
  1098. {
  1099.         if (!set || !set[0] || !set[1]) return;
  1100.         int w = set[0], h = set[1], strr = (int)set[0];
  1101.         set += 2;
  1102.         x -= w/2; y -= h/2;
  1103.         if (x >= xpar.win || y >= ypar.win) return;
  1104.         if (w > xpar.win - x) w = xpar.win - x;
  1105.         if (h > ypar.win - y) h = ypar.win - y;
  1106.         strr -= w;
  1107.         unsigned char *p, *pp = picture + 3 * (y * xpar.win + x);
  1108.         int i, j, m = 1;
  1109.         for (i = h; i > 0; i--)
  1110.         {
  1111.                 p = pp;
  1112.                 for (j = w; j > 0; j--)
  1113.                 {
  1114.                         if (*set & m) {p[0] = color[0]; p[1] = color[1]; p[2] = color[2];}
  1115.                         p += 3;
  1116.                         m <<= 1;
  1117.                         if (!(m & 255)) {m = 1; set++;}
  1118.                 }
  1119.                 pp += 3 * xpar.win;
  1120.                 m <<= strr % 8; set += strr / 8;
  1121.                 if (!(m & 255)) {m >>= 8; set++;}
  1122.         }
  1123. }
  1124.  
  1125. void WinNumberRect(int x, int y, unsigned int n, const unsigned char *color)
  1126. {
  1127.         int w, m, i;
  1128.         w = 0; m = n;
  1129.         do
  1130.         {
  1131.                 i = m % MenuDig; m /= MenuDig;
  1132.                 if (menu.digit[i]) w += 2 + menu.digit[i][0];
  1133.         } while(m);
  1134.         if (w <= 2) return;
  1135.         x += w - (w-2) / 2;
  1136.         m = n;
  1137.         do
  1138.         {
  1139.                 i = m % MenuDig; m /= MenuDig;
  1140.                 if (menu.digit[i])
  1141.                 {
  1142.                         x -= 2 + menu.digit[i][0];
  1143.                         WinBitSetRect(x + menu.digit[i][0] / 2, y, menu.digit[i], color);
  1144.                 }
  1145.         } while(m);
  1146. }
  1147.  
  1148. void WinNumberEditRect(int x, int y, int w, int h, unsigned int n,
  1149.                         const unsigned char *color, const unsigned char *bg_color)
  1150. {
  1151.         if (bg_color) WinFillRect(x, y, w, h, bg_color);
  1152.         WinNumberRect(x + w/2, y + h/2, n, color);
  1153. }
  1154.  
  1155. void MenuPaint(int what)
  1156. {
  1157.         static const unsigned char color_light0[3] = {255, 255, 255};
  1158.         static const unsigned char color_light[3] = {208, 208, 208};
  1159.         static const unsigned char color_face[3] = {192, 192, 192};
  1160.         static const unsigned char color_shadow[3] = {128, 128, 128};
  1161.         static const unsigned char color_shadow0[3] = {64, 64, 64};
  1162.         static const unsigned char color_black[3] = {0, 0, 0};
  1163.         static const unsigned char (&color_white)[3] = color_light0;
  1164.  
  1165.         if (GetMenuHeight() < MenuParam::Size) return;
  1166.         const unsigned char *color[4];
  1167.         int menuy = GetMenuYPos(), i, k, x, xx, y, yy;
  1168.         if ((what & PaintWSpeed) && !(what & (PaintWMenu & ~PaintWMenuBorder)) &&
  1169.                                 menu.button[MenuISpeed].Right() < xpar.win)
  1170.         {
  1171.                 k = MenuISpeed;
  1172.                 i = menu.button[k].border + 1;
  1173.                 xx = menu.button[k].Left() + i;
  1174.                 yy = menuy + 1 + i;
  1175.                 x = menu.button[k].size - 2*i;
  1176.                 y = MenuParam::Size - 2 - 2*i;
  1177.                 i = 0;
  1178.                 if (menu.button[k].bitmap) i += menu.button[k].bitmap[0] + 2;
  1179.                 WinNumberEditRect(xx + i, yy, x - i, y, GetMenuNumber(k, 0), color_black,
  1180.                                         (menu.edit == k && menu.edit_index == 0) ? color_white : color_face);
  1181.         }
  1182.         if (!(what & PaintWMenu)) return;
  1183.         if (what & (PaintWMenu & ~PaintWMenuBorder))
  1184.         {
  1185.                 x = menu.button[MenuParam::NButton - 1].Right();
  1186.                 WinFillRect(0, menuy, x, 1, color_face);
  1187.                 WinFillRect(0, menuy + MenuParam::Size - 1, x, 1, color_face);
  1188.                 WinFillRect(x, menuy, xpar.win - x, MenuParam::Size, color_face);
  1189.         }
  1190.         for (k = 0; k < MenuParam::NButton; k++)
  1191.         {
  1192.                 xx = menu.button[k].Left();
  1193.                 yy = menuy + 1;
  1194.                 x = menu.button[k].size;
  1195.                 y = MenuParam::Size - 2;
  1196.                 if (xx + x >= xpar.win)
  1197.                 {
  1198.                         if (what & (PaintWMenu & ~PaintWMenuBorder))
  1199.                         {
  1200.                                 i = (k >= 1) ? menu.button[k-1].Right() : 0;
  1201.                                 WinFillRect(i, yy, xpar.win - i, y, color_face);
  1202.                         }
  1203.                         break;
  1204.                 }
  1205.                 if (what & (PaintWMenu & ~PaintWMenuBorder))
  1206.                 {
  1207.                         i = (k >= 1) ? menu.button[k-1].Right() : 0;
  1208.                         WinFillRect(i, yy, xx - i, y, color_face);
  1209.                 }
  1210.                 for (i = 0; i < menu.button[k].border; i++)
  1211.                 {
  1212.                         if (i <= 1)
  1213.                         {
  1214.                                 if (menu.button[k].check)
  1215.                                 {
  1216.                                         color[0] = color[3] = i ? color_shadow : color_shadow0;
  1217.                                         color[1] = color[2] = i ? color_light : color_light0;
  1218.                                 }
  1219.                                 else
  1220.                                 {
  1221.                                         color[0] = color[3] = i ? color_light : color_light0;
  1222.                                         color[1] = color[2] = i ? color_shadow : color_shadow0;
  1223.                                 }
  1224.                         }
  1225.                         WinDrawRect(xx, yy, x, y, color);
  1226.                         xx++; yy++; x -= 2; y -= 2;
  1227.                 }
  1228.                 if (what & (PaintWMenu & ~PaintWMenuBorder))
  1229.                 {
  1230.                         WinFillRect(xx, yy, x, y, color_face);
  1231.                         if (menu.button[k].bitmap)
  1232.                         {
  1233.                                 i = (k == MenuISpeed) ? (1 + menu.button[k].bitmap[0] / 2) : (x / 2);
  1234.                                 WinBitmapRect(xx + i, yy + y/2, menu.button[k].bitmap);
  1235.                         }
  1236.                         if (k == MenuISize)
  1237.                         {
  1238.                                 xx++; yy++; x -= 2; y -= 2;
  1239.                                 i = x - 4;
  1240.                                 if (menu.button[k].bitmap) i -= menu.button[k].bitmap[0];
  1241.                                 i /= 2;
  1242.                                 WinNumberEditRect(xx, yy, i, y, GetMenuNumber(k, 0), color_black,
  1243.                                                         (menu.edit == k && menu.edit_index == 0) ? color_white : 0);
  1244.                                 WinNumberEditRect(xx + x - i, yy, i, y, GetMenuNumber(k, 1), color_black,
  1245.                                                         (menu.edit == k && menu.edit_index == 1) ? color_white : 0);
  1246.                         }
  1247.                         else if (k == MenuISpeed)
  1248.                         {
  1249.                                 xx++; yy++; x -= 2; y -= 2;
  1250.                                 i = 0;
  1251.                                 if (menu.button[k].bitmap) i += menu.button[k].bitmap[0] + 2;
  1252.                                 WinNumberEditRect(xx + i, yy, x - i, y, GetMenuNumber(k, 0), color_black,
  1253.                                                         (menu.edit == k && menu.edit_index == 0) ? color_white : 0);
  1254.                         }
  1255.                 }
  1256.         }
  1257. }
  1258.  
  1259. void Paint(int what, TThreadData th);
  1260.  
  1261. void SetMenuDraw(bool draw, TThreadData th)
  1262. {
  1263.         if (draw == menu.draw) return;
  1264.         if (menu.pressed >= 0) menu.button[menu.pressed].check = false;
  1265.         menu.pressed = -1;
  1266.         menu.draw = draw;
  1267.         Paint(PaintWAll | PaintWFast, th);
  1268. }
  1269.  
  1270. void SetMenuPressed(int k, TThreadData th)
  1271. {
  1272.         if (menu.pressed == k) return;
  1273.         if (menu.pressed >= 0) menu.button[menu.pressed].check = false;
  1274.         if (k >= 0) menu.button[k].check = true;
  1275.         menu.pressed = k;
  1276.         Paint(PaintWMenuBorder | PaintWFast, th);
  1277. }
  1278.  
  1279. void SetMenuCurrent(int k, TThreadData th)
  1280. {
  1281.         if (menu.current == k) return;
  1282.         if (menu.current >= 0) menu.button[menu.current].check = false;
  1283.         if (k >= 0) menu.button[k].check = true;
  1284.         menu.current = k;
  1285.         Paint(PaintWMenuBorder | PaintWFast, th);
  1286. }
  1287.  
  1288. void SetMenuEdit(int k, int i, TThreadData th)
  1289. {
  1290.         if (menu.edit != k)
  1291.         {
  1292.                 if (menu.edit >= 0) menu.button[menu.edit].check = false;
  1293.                 if (k >= 0) menu.button[k].check = true;
  1294.                 if (k == MenuISize) {menu.edit_num[0] = xpar.p; menu.edit_num[1] = ypar.p;}
  1295.                 else if (k == MenuISpeed) menu.edit_num[0] = generate.gps;
  1296.         }
  1297.         else if (menu.edit_index == i) return;
  1298.         if (k == MenuISize) menu.edit_num_max = 32767;
  1299.         else if (k == MenuISpeed) menu.edit_num_max = 9999999;
  1300.         menu.edit = k; menu.edit_index = i;
  1301.         Paint(PaintWMenu | PaintWFast, th);
  1302. }
  1303.  
  1304. void ApplyMenuEdit(TThreadData th)
  1305. {
  1306.         if (menu.edit < 0) return;
  1307.         if (menu.edit == MenuISize)
  1308.         {
  1309.                 int w = menu.edit_num[0], h = menu.edit_num[1];
  1310.                 ResetGenerate();
  1311.                 if (xpar.p != w || ypar.p != h)
  1312.                 {
  1313.                         if (w <= 0) w = 1;
  1314.                         if (h <= 0) h = 1;
  1315.                         SetPoleSize(w, h);
  1316.                         generate.paint |= PaintWPole | PaintWMenu | PaintWFast;
  1317.                 }
  1318.         }
  1319.         else if (menu.edit == MenuISpeed)
  1320.         {
  1321.                 generate.gps = menu.edit_num[0];
  1322.         }
  1323.         SetMenuEdit(-1, -1, th);
  1324. }
  1325.  
  1326. int GetMenuEditIndex(int k, int x)
  1327. {
  1328.         if (k == MenuISize) return x >= menu.button[k].left + menu.button[k].size / 2;
  1329.         else return 0;
  1330. }
  1331.  
  1332. void LifeScreenPutPicture(const unsigned char *pict, int size, TThreadData th)
  1333. {
  1334.         int w, h;
  1335.         ResetGenerate();
  1336.         LifeGetPictureSize(w, h, pict, size);
  1337.         w += 10; h += 10;
  1338.         if (!life_data || xpar.p < w || ypar.p < h)
  1339.         {
  1340.                 if (xpar.p >= w) w = xpar.p;
  1341.                 if (ypar.p >= h) h = ypar.p;
  1342.                 SetPoleSize(w, h);
  1343.                 if (!life_data)
  1344.                 {
  1345.                         Paint(PaintWMenu | PaintWFast, th);
  1346.                         return;
  1347.                 }
  1348.         }
  1349.         MemSet(GetDataAddress(life_data), 0, GetDataSize(xpar.p, ypar.p));
  1350.         LifePutPicture(xpar.p / 2, ypar.p / 2, pict, size, life_data);
  1351.         menu.button[MenuIRandom].check = false;
  1352.         xpar.shift = 0; ypar.shift = 0;
  1353.         generate.paint |= PaintWPole | PaintWMenu | PaintWFast;
  1354. //      SetMenuCurrent(MenuIScroll, th);
  1355.         Paint(PaintWNull, th);
  1356. }
  1357.  
  1358. void MenuOpenDialogEnd(TThreadData th)
  1359. {
  1360.         int state = OpenFileGetState(open_file_str);
  1361.         if (state <= 0) return;
  1362.         OpenFileSetState(open_file_str, 0);
  1363.         if (state != 2) return;
  1364.         char *name = OpenFileGetName(open_file_str);
  1365.         if (!name) return;
  1366.         TFileData file = FileOpen(name);
  1367.         if (!file) return;
  1368.         int k = FileGetLength(file);
  1369.         unsigned char *pict = 0;
  1370.         if (k > 0 && k < (1 << 24))
  1371.         {
  1372.                 pict = (unsigned char*)Alloc(k+1);
  1373.                 if (pict)
  1374.                 {
  1375.                         if (FileRead(file, pict, k) == k) pict[k] = 0;
  1376.                         else {Free(pict); pict = 0;}
  1377.                 }
  1378.         }
  1379.         FileClose(file);
  1380.         if (!pict) return;
  1381.         LifeScreenPutPicture(pict, k, th);
  1382.         Free(pict);
  1383. }
  1384.  
  1385. void MenuWinSizeClick(TThreadData th)
  1386. {
  1387.         int w = xpar.win, h = ypar.win - GetMenuHeight();
  1388.         ResetGenerate();
  1389.         if (w > 0 && h > 0 && (xpar.p != w || ypar.p != h))
  1390.         {
  1391.                 SetPoleSize(w, h);
  1392.                 Paint(PaintWPole | PaintWMenu | PaintWFast, th);
  1393.         }
  1394. }
  1395.  
  1396. void MenuGenerateClick(TThreadData th)
  1397. {
  1398.         generate.stop = false;
  1399.         ResetGenerate();
  1400.         menu.button[MenuIGenerate].check = !menu.button[MenuIGenerate].check;
  1401.         Paint(PaintWMenuBorder | PaintWSpeed | PaintWFast, th);
  1402. }
  1403.  
  1404. void MenuClearClick(TThreadData th)
  1405. {
  1406.         ResetGenerate();
  1407.         if (life_data) MemSet(GetDataAddress(life_data), 0, GetDataSize(xpar.p, ypar.p));
  1408.         Paint(PaintWPole | PaintWFast, th);
  1409. }
  1410.  
  1411. void MenuAboutClick(TThreadData th)
  1412. {
  1413.         generate.stop = false;
  1414.         menu.button[MenuIGenerate].check = true;
  1415.         generate.paint |= PaintWSpeed;
  1416.         LifeScreenPutPicture(about_picture, sizeof(about_picture), th);
  1417. }
  1418.  
  1419. void MenuMouseClick(int x, int y, int m, TThreadData th)
  1420. {
  1421.         int k, i, j = GetMenuYPos();
  1422.         if (menu.edit >= 0)
  1423.         {
  1424.                 k = menu.edit;
  1425.                 j = GetMenuYPos();
  1426.                 if (GetMenuHeight() < MenuParam::Size || y < j + 1 || y >= j + MenuParam::Size - 1 ||
  1427.                                         x < menu.button[k].Left() || x >= menu.button[k].Right())
  1428.                 {
  1429.                         if (m == 1) ApplyMenuEdit(th);
  1430.                         else SetMenuEdit(-1, -1, th);
  1431.                 }
  1432.                 else SetMenuEdit(k, GetMenuEditIndex(k, x), th);
  1433.                 return;
  1434.         }
  1435.         if (GetMenuHeight() < MenuParam::Size || y < j + 1 || y >= j + MenuParam::Size - 1)
  1436.         {
  1437.                 if (m < 0) x = -1;
  1438.                 else return;
  1439.         }
  1440.         if (m < 0)
  1441.         {
  1442.                 if (menu.pressed < 0) return;
  1443.                 k = menu.pressed;
  1444.                 if (x < menu.button[k].Left() || x >= menu.button[k].Right())
  1445.                 {
  1446.                         if (menu.button[k].check)
  1447.                         {
  1448.                                 menu.button[k].check = false;
  1449.                                 Paint(PaintWMenuBorder | PaintWFast, th);
  1450.                         }
  1451.                 }
  1452.                 else if (!menu.button[k].check)
  1453.                 {
  1454.                         menu.button[k].check = true;
  1455.                         Paint(PaintWMenuBorder | PaintWFast, th);
  1456.                 }
  1457.                 return;
  1458.         }
  1459.         if (m == 0)
  1460.         {
  1461.                 if (menu.pressed < 0 || !menu.button[menu.pressed].check) return;
  1462.                 switch (menu.pressed)
  1463.                 {
  1464.                 case MenuIHide:
  1465.                         SetMenuDraw(false, th);
  1466.                         break;
  1467.                 case MenuIClear:
  1468.                         MenuClearClick(th);
  1469.                         break;
  1470.                 case MenuIOpen:
  1471.                         if (OpenFileGetState(open_file_str) < 0) break;
  1472.                         OpenFileDialog(open_file_str);
  1473.                         break;
  1474.                 case MenuIAbout:
  1475.                         MenuAboutClick(th);
  1476.                         break;
  1477.                 case MenuIExit:
  1478.                         CloseWindow(th);
  1479.                         break;
  1480.                 case MenuIWinSize:
  1481.                         MenuWinSizeClick(th);
  1482.                         break;
  1483.                 }
  1484.                 return;
  1485.         }
  1486.         k = -1; i = MenuParam::NButton;
  1487.         while (k + 1 < i)
  1488.         {
  1489.                 j = (k + i) / 2;
  1490.                 if (x < menu.button[j].Left()) i = j;
  1491.                 else k = j;
  1492.         }
  1493.         i = menu.button[k].Right();
  1494.         if (k < 0 || x >= i || i >= xpar.win) return;
  1495.         switch (k)
  1496.         {
  1497.         case MenuIHide:
  1498.         case MenuIClear:
  1499.         case MenuIOpen:
  1500.         case MenuIAbout:
  1501.         case MenuIExit:
  1502.         case MenuIWinSize:
  1503.                 SetMenuPressed(k, th);
  1504.                 break;
  1505.         case MenuIGenerate:
  1506.                 MenuGenerateClick(th);
  1507.                 break;
  1508.         case MenuIRandom:
  1509.         case MenuIVCircle:
  1510.         case MenuIHCircle:
  1511.                 menu.button[k].check = !menu.button[k].check;
  1512.                 Paint(PaintWMenuBorder | PaintWFast, th);
  1513.                 break;
  1514.         case MenuILine:
  1515.         case MenuIScroll:
  1516.                 SetMenuCurrent(k, th);
  1517.                 break;
  1518.         case MenuISize:
  1519.         case MenuISpeed:
  1520.                 SetMenuEdit(k, GetMenuEditIndex(k, x), th);
  1521.                 break;
  1522.         }
  1523. }
  1524.  
  1525. void PoleMouseClick(int m, TThreadData th)
  1526. {
  1527.         if (m != 1 && m != 2) return;
  1528.         mpar.hit_type = MouseParam::HitNull;
  1529.         switch (menu.current)
  1530.         {
  1531.         case MenuILine:
  1532.                 if (menu.draw)
  1533.                 {
  1534.                         menu.button[MenuIRandom].check = false;
  1535.                         generate.paint |= PaintWMenuBorder | PaintWFast;
  1536.                         if (m == 1) mpar.hit_type = MouseParam::HitLine;
  1537.                         else mpar.hit_type = MouseParam::HitCircle;
  1538.                 }
  1539.                 break;
  1540.         case MenuIScroll:
  1541.                 if (m == 1) mpar.hit_type = MouseParam::HitScroll;
  1542.                 break;
  1543.         }
  1544.         if (mpar.hit_type) Paint(PaintWPole | PaintWFast, th);
  1545.         else if (!menu.draw) SetMenuDraw(true, th);
  1546. }
  1547.  
  1548. void MenuEditPressKey(int ch, TThreadData th)
  1549. {
  1550.         if (menu.edit < 0) return;
  1551.         int &num = menu.edit_num[menu.edit_index];
  1552.         if (ch == 27) SetMenuEdit(-1, -1, th);
  1553.         else if (ch == '\r') ApplyMenuEdit(th);
  1554.         else if (ch == 8) {num /= 10; Paint(PaintWMenu | PaintWFast, th);}
  1555.         else if (ch >= '0' && ch <= '9')
  1556.         {
  1557.                 num = 10 * num + (ch - '0');
  1558.                 if (num >= menu.edit_num_max) num = menu.edit_num_max;
  1559.                 Paint(PaintWMenu | PaintWFast, th);
  1560.         }
  1561.         else if (menu.edit == MenuISize)
  1562.         {
  1563.                 if (ch == '\t') SetMenuEdit(MenuISize, !menu.edit_index, th);
  1564.                 else if (ch == 'x' || ch == 'X') SetMenuEdit(MenuISize, 0, th);
  1565.                 else if (ch == 'y' || ch == 'Y') SetMenuEdit(MenuISize, 1, th);
  1566.         }
  1567. }
  1568.  
  1569. void CalculateSpeed()
  1570. {
  1571.         double t = 0, g = 0, dn, n = 0, st = 0, sg = 0, ss = 0, sp = 0;
  1572.         int i = timegenpos;
  1573.         do
  1574.         {
  1575.                 if (t >= 500) break;
  1576.                 g += timegen[i].g;
  1577.                 dn = timegen[i].g;
  1578.                 n += dn * (500 - t);
  1579.                 st += dn * t;
  1580.                 sg += dn * g;
  1581.                 ss += dn * t * t;
  1582.                 sp += dn * g * t;
  1583.                 if (--i < 0) i = TimeGenLength;
  1584.                 t += timegen[i].t;
  1585.         } while(i != timegenpos);
  1586.         ss = n * ss - st * st;
  1587.         sp = n * sp - sg * st;
  1588.         if (st < 1e-4 || ss < 1e-4 * st * st) g = 0;
  1589.         else g = sp / ss;
  1590.         generate.speed = 100 * g;
  1591. }
  1592.  
  1593. void Paint(int what, TThreadData th)
  1594. {
  1595.         what |= generate.paint;
  1596.         if (!(what & PaintWAll) || !life_data || xpar.win <= 0 || ypar.win <= 0) return;
  1597.  
  1598.         const unsigned int FAST_PAINT_TIME = 2, WAIT_PAINT_TIME = 8;
  1599.         unsigned int t = Clock() - generate.paint_time;
  1600.         unsigned int wt = (what & PaintWFast) ? FAST_PAINT_TIME : WAIT_PAINT_TIME;
  1601.         if (!(what & PaintWNow) && t >= (unsigned int)(-WAIT_PAINT_TIME))
  1602.         {
  1603.                 if ((unsigned int)(-t) > wt) generate.paint_time += t + wt;
  1604.                 generate.paint = what;
  1605.                 return;
  1606.         }
  1607.         generate.paint_time += t + wt;
  1608.         generate.paint = PaintWNull;
  1609.  
  1610.         if (!picture)
  1611.         {
  1612.                 SetPictureSize();
  1613.                 if (!picture) return;
  1614.         }
  1615.         if (what & PaintWPole)
  1616.         {
  1617.                 const unsigned char bgcolor[3] = {128, 128, 0};
  1618.                 int w, h, x, y, xx, yy, i, j;
  1619.                 int menu0 = GetMenuYPos(), menu1 = menu0 + GetMenuHeight();
  1620.                 unsigned char *p = picture;
  1621.                 unsigned char *data0 = (unsigned char*)GetDataAddress(life_data);
  1622.                 int size = GetDataSize(xpar.p, ypar.p);
  1623.                 if (xpar.win <= 0 || ypar.win <= 0) return;
  1624.                 if (mpar.hit_type > 0)
  1625.                 {
  1626.                         double shift_x = xpar.shift, shift_y = ypar.shift;
  1627.                         ApplyHit(data0, data0 + size);
  1628.                         data0 += size;
  1629.                         GetPaintOrigin(w, h, x, y, xx, yy);
  1630.                         xpar.shift = shift_x; ypar.shift = shift_y;
  1631.                 }
  1632.                 else GetPaintOrigin(w, h, x, y, xx, yy);
  1633.                 APosPixel pixel(xpar.p, ypar.p, data0);
  1634.                 j = menu0;
  1635.                 if (j < 0) j = 0;
  1636.                 else if (j > yy) j = yy;
  1637.                 for (i = j * xpar.win; i > 0; i--)
  1638.                 {
  1639.                         *(p++) = bgcolor[0]; *(p++) = bgcolor[1]; *(p++) = bgcolor[2];
  1640.                 }
  1641.                 i = menu1;
  1642.                 if (i < 0) i = 0;
  1643.                 else if (i > yy) i = yy;
  1644.                 p += 3 * xpar.win * (i - j);
  1645.                 for (i = (yy - i) * xpar.win; i > 0; i--)
  1646.                 {
  1647.                         *(p++) = bgcolor[0]; *(p++) = bgcolor[1]; *(p++) = bgcolor[2];
  1648.                 }
  1649.                 for (i = 0; i < h; i++)
  1650.                 {
  1651.                         for (j = xx; j > 0; j--)
  1652.                         {
  1653.                                 *(p++) = bgcolor[0]; *(p++) = bgcolor[1]; *(p++) = bgcolor[2];
  1654.                         }
  1655.                         pixel.SetTo(x, (y + i) % ypar.p);
  1656.                         j = xpar.p - x;
  1657.                         if (j > w) j = w;
  1658.                         for (;;)
  1659.                         {
  1660.                                 if (pixel.GetPixel()) {*(p++) = 255; *(p++) = 255; *(p++) = 255;}
  1661.                                 else {*(p++) = 0; *(p++) = 0; *(p++) = 0;}
  1662.                                 if (--j <= 0) break;
  1663.                                 pixel.AddX1();
  1664.                         }
  1665.                         j = w - (xpar.p - x);
  1666.                         if (j > 0)
  1667.                         {
  1668.                                 pixel.SetTo(0, (y + i) % ypar.p);
  1669.                                 for (;;)
  1670.                                 {
  1671.                                         if (pixel.GetPixel()) {*(p++) = 255; *(p++) = 255; *(p++) = 255;}
  1672.                                         else {*(p++) = 0; *(p++) = 0; *(p++) = 0;}
  1673.                                         if (--j <= 0) break;
  1674.                                         pixel.AddX1();
  1675.                                 }
  1676.                         }
  1677.                         for (j = xpar.win - xx - w; j > 0; j--)
  1678.                         {
  1679.                                 *(p++) = bgcolor[0]; *(p++) = bgcolor[1]; *(p++) = bgcolor[2];
  1680.                         }
  1681.                 }
  1682.                 j = menu0;
  1683.                 if (j < yy + h) j = yy + h;
  1684.                 else if (j > ypar.win) j = ypar.win;
  1685.                 for (i = (j - yy - h) * xpar.win; i > 0; i--)
  1686.                 {
  1687.                         *(p++) = bgcolor[0]; *(p++) = bgcolor[1]; *(p++) = bgcolor[2];
  1688.                 }
  1689.                 i = menu1;
  1690.                 if (i < yy + h) i = yy + h;
  1691.                 else if (i > ypar.win) i = ypar.win;
  1692.                 p += 3 * xpar.win * (i - j);
  1693.                 for (i = (ypar.win - i) * xpar.win; i > 0; i--)
  1694.                 {
  1695.                         *(p++) = bgcolor[0]; *(p++) = bgcolor[1]; *(p++) = bgcolor[2];
  1696.                 }
  1697.         }
  1698.         if (what & PaintWSpeed) CalculateSpeed();
  1699.         MenuPaint(what);
  1700.         SetPicture(picture, (unsigned short)xpar.win, (unsigned short)ypar.win, th);
  1701. }
  1702.  
  1703. bool MenuetOnStart(TStartData &me_start, TThreadData th)
  1704. {
  1705.         randomize();
  1706.         me_start.WinData.Title = "Black and white Life";
  1707.         me_start.Width = 500; me_start.Height = 400;
  1708.         InitGenerate();
  1709.         InitMenuButton();
  1710.         if (CommandLine[0])
  1711.         {
  1712.                 open_file_str.state = 2;
  1713.                 OpenFileSetName(open_file_str, CommandLine);
  1714.         }
  1715.         return true;
  1716. }
  1717.  
  1718. bool MenuetOnClose(TThreadData)
  1719. {
  1720.         SetPictureSize(0, 0);
  1721.         SetPoleSize(0, 0);
  1722.         return true;
  1723. }
  1724.  
  1725. int MenuetOnIdle(TThreadData th)
  1726. {
  1727.         static const unsigned int WAIT_TIME = 2, GEN_TIME = 1;
  1728.         int res = -1;
  1729.         if (OpenFileGetState(open_file_str) > 0)
  1730.         {
  1731.                 MenuOpenDialogEnd(th);
  1732.                 res = 0;
  1733.         }
  1734.         else
  1735.         {
  1736.                 if (life_data && menu.button[MenuIGenerate].check)
  1737.                 {
  1738.                         unsigned int t = Clock() - generate.time;
  1739.                         if (t >= (unsigned int)(-WAIT_TIME)) res = -t;
  1740.                         else
  1741.                         {
  1742.                                 MoveGenerateTime(t);
  1743.                                 if (generate.count > 0)
  1744.                                 {
  1745.                                         unsigned char *data0 = (unsigned char*)GetDataAddress(life_data);
  1746.                                         int size = GetDataSize(xpar.p, ypar.p);
  1747.                                         int flag = (menu.button[MenuIHCircle].check ? 4 : 1) +
  1748.                                                                 (menu.button[MenuIVCircle].check ? 8 : 2);
  1749.                                         if (++timegenpos >= TimeGenLength) timegenpos = 0;
  1750.                                         timegen[timegenpos].t = 0;
  1751.                                         timegen[timegenpos].g = 0;
  1752.                                         for (;;)
  1753.                                         {
  1754.                                                 OneGeneration(xpar.p, ypar.p, data0 + size, data0, flag);
  1755.                                                 if (menu.button[MenuIRandom].check) RandomDraw(data0 + size);
  1756.                                                 timegen[timegenpos].g++;
  1757.                                                 if (--generate.count == 0 || (unsigned int)(Clock() - generate.time) >= GEN_TIME)
  1758.                                                 {
  1759.                                                         MemCopy(data0, data0 + size, size);
  1760.                                                         break;
  1761.                                                 }
  1762.                                                 OneGeneration(xpar.p, ypar.p, data0, data0 + size, flag);
  1763.                                                 if (menu.button[MenuIRandom].check) RandomDraw(data0);
  1764.                                                 timegen[timegenpos].g++;
  1765.                                                 if (--generate.count == 0 || (unsigned int)(Clock() - generate.time) >= GEN_TIME) break;
  1766.                                         }
  1767.                                         generate.paint |= PaintWPole | PaintWSpeed;
  1768.                                 }
  1769.                                 if (generate.stop && generate.count == 0)
  1770.                                 {
  1771.                                         ResetGenerate();
  1772.                                         menu.button[MenuIGenerate].check = false;
  1773.                                         generate.paint |= PaintWMenuBorder | PaintWSpeed;
  1774.                                         res = -1;
  1775.                                 }
  1776.                                 else
  1777.                                 {
  1778.                                         MoveGenerateTime(Clock() - generate.time);
  1779.                                         res = (generate.count <= generate.gps / 100) ? WAIT_TIME : 0;
  1780.                                         MoveGenerateTime(res);
  1781.                                 }
  1782.                         }
  1783.                 }
  1784.         }
  1785.         if (generate.paint)
  1786.         {
  1787.                 Paint((res < 0 || res > WAIT_TIME) ? (PaintWNull | PaintWNow) : PaintWNull, th);
  1788.         }
  1789.         return res;
  1790. }
  1791.  
  1792. void MenuetOnSize(int window_rect[], Menuet::TThreadData th)
  1793. {
  1794.         unsigned short w, h;
  1795.         GetClientSize(w, h, window_rect[2], window_rect[3], th);
  1796.         SetPictureSize(w, h);
  1797.         generate.paint |= PaintWAll | PaintWFast;
  1798.         if (!life_data) MenuWinSizeClick(th);
  1799.         Paint(PaintWNull | PaintWNow, th);
  1800. }
  1801.  
  1802. void MenuetOnKeyPress(TThreadData th)
  1803. {
  1804.         int ch;
  1805.         while ((ch = GetKey()) >= 0)
  1806.         {
  1807.                 if (mpar.hit_type > 0)
  1808.                 {
  1809.                         mpar.hit_type = 0;
  1810.                         generate.paint |= PaintWPole | PaintWFast;
  1811.                         SetMenuPressed(-1, th);
  1812.                         if (generate.paint) Paint(PaintWNull, th);
  1813.                 }
  1814.                 else if (menu.pressed >= 0) SetMenuPressed(-1, th);
  1815.                 else if (menu.edit >= 0) MenuEditPressKey(ch, th);
  1816.                 else
  1817.                 {
  1818.                         switch (ch)
  1819.                         {
  1820.                         case 'm':
  1821.                         case 'M':
  1822.                                 SetMenuDraw(!menu.draw, th);
  1823.                                 break;
  1824.                         case 'c':
  1825.                         case 'C':
  1826.                                 MenuClearClick(th);
  1827.                                 break;
  1828.                         case 'o':
  1829.                         case 'O':
  1830.                                 if (OpenFileGetState(open_file_str) < 0) break;
  1831.                                 OpenFileDialog(open_file_str);
  1832.                                 break;
  1833.                         case 'a':
  1834.                         case 'A':
  1835.                                 MenuAboutClick(th);
  1836.                                 break;
  1837.                         case 'q':
  1838.                         case 'Q':
  1839.                                 CloseWindow(th);
  1840.                                 break;
  1841.                         case 'w':
  1842.                         case 'W':
  1843.                                 MenuWinSizeClick(th);
  1844.                                 break;
  1845.                         case 'g':
  1846.                         case 'G':
  1847.                                 MenuGenerateClick(th);
  1848.                                 break;
  1849.                         case 'r':
  1850.                         case 'R':
  1851.                                 menu.button[MenuIRandom].check = !menu.button[MenuIRandom].check;
  1852.                                 Paint(PaintWMenuBorder | PaintWFast, th);
  1853.                                 break;
  1854.                         case 'v':
  1855.                         case 'V':
  1856.                                 menu.button[MenuIVCircle].check = !menu.button[MenuIVCircle].check;
  1857.                                 Paint(PaintWMenuBorder | PaintWFast, th);
  1858.                                 break;
  1859.                         case 'h':
  1860.                         case 'H':
  1861.                                 menu.button[MenuIHCircle].check = !menu.button[MenuIHCircle].check;
  1862.                                 Paint(PaintWMenuBorder | PaintWFast, th);
  1863.                                 break;
  1864.                         case 'l':
  1865.                         case 'L':
  1866.                                 SetMenuCurrent(MenuILine, th);
  1867.                                 break;
  1868.                         case 's':
  1869.                         case 'S':
  1870.                                 SetMenuCurrent(MenuIScroll, th);
  1871.                                 break;
  1872.                         case 'x':
  1873.                         case 'X':
  1874.                                 if (!menu.draw) SetMenuDraw(true, th);
  1875.                                 SetMenuEdit(MenuISize, 0, th);
  1876.                                 break;
  1877.                         case 'y':
  1878.                         case 'Y':
  1879.                                 if (!menu.draw) SetMenuDraw(true, th);
  1880.                                 SetMenuEdit(MenuISize, 1, th);
  1881.                                 break;
  1882.                         case 'f':
  1883.                         case 'F':
  1884.                                 if (!menu.draw) SetMenuDraw(true, th);
  1885.                                 SetMenuEdit(MenuISpeed, 0, th);
  1886.                                 break;
  1887.                         case ' ':
  1888.                         case '\\':
  1889.                         case '|':
  1890.                                 if (menu.button[MenuIGenerate].check && !generate.stop)
  1891.                                 {
  1892.                                         menu.button[MenuIGenerate].check = false;
  1893.                                         Paint(PaintWMenuBorder | PaintWSpeed | PaintWFast, th);
  1894.                                 }
  1895.                                 else AddGenerateCount((ch == ' ') ? 1 : 15);
  1896.                                 break;
  1897.                         }
  1898.                 }
  1899.         }
  1900. }
  1901.  
  1902. void MenuetOnMouse(TThreadData th)
  1903. {
  1904.         short xp = 0, yp = 0;
  1905.         int w, h, x, y, xx, yy, m;
  1906.         GetMousePosPicture(xp, yp);
  1907.         m = GetMouseButton();
  1908.         GetPaintOrigin(w, h, x, y, xx, yy);
  1909.         x += xp - xx;
  1910.         y += yp - yy;
  1911.         if (mpar.hit_type > 0)
  1912.         {
  1913.                 if (mpar.last_x != x || mpar.last_y != y)
  1914.                 {
  1915.                         mpar.last_x = x; mpar.last_y = y;
  1916.                         generate.paint |= PaintWPole | PaintWFast;
  1917.                 }
  1918.                 if (m != mpar.button)
  1919.                 {
  1920.                         if ((m & ~mpar.button) == 0) ApplyHit();
  1921.                         mpar.hit_type = 0;
  1922.                         generate.paint |= PaintWPole | PaintWFast;
  1923.                         SetMenuPressed(-1, th);
  1924.                         if (generate.paint) Paint(PaintWNull, th);
  1925.                 }
  1926.         }
  1927.         else if (menu.pressed >= 0)
  1928.         {
  1929.                 if (mpar.last_x != x || mpar.last_y != y)
  1930.                 {
  1931.                         MenuMouseClick(xp, yp, -1, th);
  1932.                 }
  1933.                 if (m != mpar.button)
  1934.                 {
  1935.                         if ((m & ~mpar.button) == 0) MenuMouseClick(xp, yp, 0, th);
  1936.                         SetMenuPressed(-1, th);
  1937.                 }
  1938.         }
  1939.         else if (mpar.button == 0 && (m == 1 || m == 2))
  1940.         {
  1941.                 if (xp >= 0 && xp < xpar.win && yp >= 0 && yp < ypar.win)
  1942.                 {
  1943.                         mpar.hit_x = x; mpar.hit_y = y; mpar.last_x = x; mpar.last_y = y;
  1944.                         yy = GetMenuYPos();
  1945.                         if (menu.edit >= 0 || (yp >= yy && yp < yy + GetMenuHeight()))
  1946.                         {
  1947.                                 MenuMouseClick(xp, yp, m, th);
  1948.                         }
  1949.                         else PoleMouseClick(m, th);
  1950.                 }
  1951.         }
  1952.         mpar.button = m;
  1953. }
  1954.  
  1955. #ifndef __MENUET__
  1956.  
  1957. #include <windows.h>
  1958.  
  1959. void __stdcall (*DllOneGeneration)(int w, int h, void *dest, const void *src, int flag) = 0;
  1960.  
  1961. void DllInit()
  1962. {
  1963.         HINSTANCE hLib = LoadLibrary("LifeGen.dll");
  1964.         if (!hLib)
  1965.         {
  1966.                 DebugPutString("Can't load the library.\n");
  1967.                 Menuet::Abort();
  1968.         }
  1969.         DllOneGeneration = (void(__stdcall*)(int, int, void*, const void*, int))GetProcAddress(hLib, "OneGeneration");
  1970.         if (!DllOneGeneration)
  1971.         {
  1972.                 DebugPutString("Can't get a library function.\n");
  1973.                 Menuet::Abort();
  1974.         }
  1975. }
  1976.  
  1977. void __stdcall OneGeneration(int w, int h, void *dest, const void *src, int flag)
  1978. {
  1979.         if (!DllOneGeneration) DllInit();
  1980.         DllOneGeneration(w, h, dest, src, flag);
  1981. }
  1982.  
  1983. #endif
  1984.  
  1985.