Subversion Repositories Kolibri OS

Rev

Rev 8133 | Rev 8184 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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