Subversion Repositories Kolibri OS

Rev

Rev 8184 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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