Subversion Repositories Kolibri OS

Rev

Rev 9764 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
9763 vitalkrilo 1
#include 
2
#include 
3
#include 
4
#include 
5
#include 
6
 
7
#include "func.h"
8
#include "parser.h"
9
 
10
#define nullptr 0
11
#define dword unsigned int
12
 
13
enum BUTTONS {
14
	BTN_QUIT = 1,
15
	BTN_EDIT = 5
16
};
17
 
18
const char header[] = "Graph";
19
const char empty_text[] = "No function loaded. Type file name and press Enter. ";
20
const char er_file_not_found[] = "Cannot open file. ";
21
const char str_filename[] = "Filename:";
22
const char str_editfile[] = "Edit";
23
 
24
// начальные размеры
25
#define WND_W 600
26
#define WND_H 470
27
 
28
#define LIGHTGREEN 0xff0000
29
#define WHITE 0xffffff
30
#define BLACK 0x0
31
#define LIGHTBLUE 0x0000ff
32
#define LIGHTRED 0xff0000
33
 
34
// font colors
35
#define BIGFONTCOLOR BLACK
36
#define SMALLFONTCOLOR BLACK
37
 
38
#define THREE 3.0
39
// minimum space: 3 pixels
40
 
41
#define BIG_HEIGHT 4.0
42
#define SMALL_HEIGHT 2.0
43
#define TEXT_X 15.0
44
// numeric format for output
45
#define FORMAT "%.2f%c"
46
// format for two coords
47
#define FORMAT_COORD "(%.2f, %.2f)%c"
48
// special value to text if enough space
49
#define FORMAT_TEST "0.00"
50
 
51
#define DELTA_BIG 1.0
52
#define DELTA_SMALL 0.1
53
 
54
int SysColor = 0;
55
 
56
double* points;
57
dword point_count = 0;
58
double x1, y1, x2, y2;
59
char* funct = nullptr;
60
 
61
char edit_path[256];
62
edit_box mybox = { 200, 92, WND_H-16-32, 0xffffff, 0x94AECE, 0, 0x808080, 0x10000000,
63
					sizeof(edit_path)-1, (void*)&edit_path, 0, 0, 0 };
64
 
65
char* full_head;
66
 
67
char* HugeBuf = nullptr;
68
 
69
// constructor of TCoord
70
TCoord coord(double x, double y) {
71
  TCoord r;
72
  r.x = x;
73
  r.y = y;
74
  return r;
75
}
76
 
77
// move and scale mathematical coords to fit screen coords
78
TCoord mat2Graf(TCoord c, TCoord scrMin, TCoord scrMax, TCoord mMin, TCoord mMax) {
79
  TCoord r;
80
  if (c.x > mMax.x)
81
    c.x = mMax.x;
82
  if (c.x < mMin.x)
83
    c.x = mMin.x;
84
  if (c.y > mMax.y)
85
    c.y = mMax.y;
86
  if (c.y < mMin.y)
87
    c.y = mMin.y;
88
  r.x = (scrMax.x - scrMin.x) / (mMax.x - mMin.x) * (c.x - mMin.x) + scrMin.x;
89
  r.y = (scrMax.y - scrMin.y) / (mMax.y - mMin.y) * (mMax.y - c.y) + scrMin.y;
90
 
91
  return r;
92
}
93
 
94
// huge function to draw all the stuff except the function itself
95
void drawAxis(TCoord scrMin, TCoord scrMax, TCoord mMin, TCoord mMax) {
96
  TCoord cZero={0.0,0.0},
97
	   gMin, gMax, gZero, step;
98
  TCoord from, to;
99
  double i=0.0;
100
  int j;
101
  double xmin, xmin2, ymin, ymin2;
102
  char buf[30]="";
103
  int strlentemp;
104
 
105
 
106
// scr means Screen(bounding rect)
107
// m   means Mathematical
108
// g   means Graphic(real screen position)
109
 
110
  //_ksys_debug_puts("draw axis called\n");
111
 
112
  //sprintf(debuf, "test: %f,%f,%f,%f\n", 123.45, 1.0, -0.9, 12.57);
113
  //_ksys_debug_puts(debuf);
114
 
115
  gMin = mat2Graf(mMin, scrMin, scrMax, mMin, mMax);
116
  gMax = mat2Graf(mMax, scrMin, scrMax, mMin, mMax);
117
  gZero = mat2Graf(cZero, scrMin, scrMax, mMin, mMax);
118
 
119
  // clear
120
 // SysColor = WHITE;
121
 //rectangle(di(gMin.x), di(gMin.y), di(gMax.x), di(gMax.y));
122
  // ftopku
123
 
124
  SysColor = BLACK;
125
  // osy X
126
  _ksys_draw_line(gMin.x, gZero.y ,gMax.x, gZero.y, SysColor);
127
  // osy Y
128
  _ksys_draw_line(gZero.x, gMin.y, gZero.x, gMax.y, SysColor);
129
  // bounding rect
130
  _ksys_draw_line(gMin.x, gMin.y, gMax.x, gMin.y, SysColor);
131
  _ksys_draw_line(gMin.x, gMax.y, gMax.x, gMax.y, SysColor);
132
 
133
  _ksys_draw_line(gMin.x, gMin.y, gMin.x, gMax.y, SysColor);
134
  _ksys_draw_line(gMax.x, gMin.y, gMax.x, gMax.y, SysColor);
135
 
136
  // coords of the rect : lower left
137
  sprintf(buf, FORMAT_COORD, x1, y1, '\0');
138
  //_ksys_debug_puts(buf);
139
  strlentemp = strlen(buf);
140
  _ksys_draw_text(buf, gMin.x, gMin.y + textheight(buf, strlentemp), strlentemp, SysColor);
141
  // upper left
142
  sprintf(buf, FORMAT_COORD, x1, y2, '\0');
143
  strlentemp = strlen(buf);
144
  _ksys_draw_text(buf, gMin.x, gMax.y - textheight(buf, strlentemp), strlentemp, SysColor);
145
  // lower right
146
  sprintf(buf, FORMAT_COORD, x2, y1, '\0');
147
  strlentemp = strlen(buf);
148
  _ksys_draw_text(buf, gMax.x - textwidth(buf, strlentemp), gMin.y + textheight(buf, strlentemp), strlentemp, SysColor);
149
  // upper right
150
  sprintf(buf, FORMAT_COORD, x2, y2, '\0');
151
  strlentemp = strlen(buf);
152
  _ksys_draw_text(buf, gMax.x - textwidth(buf, strlentemp), gMax.y - textheight(buf, strlentemp), strlentemp, SysColor);
153
 
154
  //_ksys_debug_puts("some lines painted\n");
155
 
156
 
157
  step.x = (mMax.x - mMin.x) / (scrMax.x - scrMin.x);
158
  step.y = (mMax.y - mMin.y) / (scrMax.y - scrMin.y);
159
 
160
// round values
161
  xmin = (int)((mMin.x / DELTA_BIG) * DELTA_BIG);
162
  ymin = (int)((mMin.y / DELTA_BIG) * DELTA_BIG);
163
 
164
  // (0,0)
165
 
166
  if ((x1 * x2 <= 0.0) && (y1 * y2 <= 0.0))
167
  {
168
	  from.x=0.0;
169
	  from.y=0.0;
170
	  from = mat2Graf(from, scrMin, scrMax, mMin, mMax);
171
	  SysColor = BLACK;
172
	  sprintf(buf, FORMAT, 0.0, '\0');
173
	  strlentemp = strlen(buf);
174
	  _ksys_draw_text(buf, from.x - textwidth(buf, strlentemp), from.y + textheight(buf, strlentemp), strlentemp, SysColor);
175
  }
176
 
177
 
178
  // big marks on X
179
  //settextstyle(0, 0, 1);
180
  if (DELTA_BIG / step.x > THREE) {
181
    for (i = xmin; i <= mMax.x; i += DELTA_BIG) {
182
	  if (i != 0.0) {
183
		  from.x = i;
184
		  to.x = from.x;
185
		  from.y = -BIG_HEIGHT * step.y;
186
		  to.y = BIG_HEIGHT * step.y;
187
		  from = mat2Graf(from, scrMin, scrMax, mMin, mMax);
188
		  to = mat2Graf(to, scrMin, scrMax, mMin, mMax);
189
		  SysColor = BLACK;
190
		  _ksys_draw_line(from.x, from.y, to.x, to.y, SysColor);
191
		  // write number
192
		  sprintf(buf, FORMAT, i, '\0');
193
		  strlentemp = strlen(buf);
194
		  // if it fits in the GAP, then write it
195
		  if (from.y > scrMin.y && (DELTA_BIG > (textwidth(buf, strlentemp) + 1.0) * step.x)) {
196
			   SysColor = BIGFONTCOLOR;
197
			   _ksys_draw_text(buf, from.x - textwidth(buf, strlentemp) / 2.0, to.y - textheight(buf, strlentemp), strlentemp, SysColor);
198
		  }
199
	  }
200
    }
201
  }
202
  //_ksys_debug_puts("big marks x painted\n");
203
 
204
  // big marks on Y
205
  if (DELTA_BIG / step.y > THREE) {
206
    for (i = ymin; i <= mMax.y; i += DELTA_BIG) {
207
	  if (i != 0.0) {
208
		  from.y = i;
209
		  to.y = from.y;
210
		  from.x = -BIG_HEIGHT * step.x;
211
		  to.x = BIG_HEIGHT * step.x;
212
		  from = mat2Graf(from, scrMin, scrMax, mMin, mMax);
213
		  to = mat2Graf(to, scrMin, scrMax, mMin, mMax);
214
		  SysColor = BLACK;
215
		  _ksys_draw_line(from.x, from.y, to.x, to.y, SysColor);
216
		  sprintf(buf, FORMAT, i, '\0');
217
		  strlentemp = strlen(buf);
218
 		  if (from.x > scrMin.x && (DELTA_BIG > textheight(buf, strlentemp) * step.y)) {
219
			   SysColor = BIGFONTCOLOR;
220
			 _ksys_draw_text(buf, from.x + TEXT_X, to.y - textheight(buf, strlentemp) / 2.0, strlentemp, SysColor);
221
		  }
222
	  }
223
    }
224
  }
225
 
226
  xmin2 = (int)(mMin.x / DELTA_SMALL) * DELTA_SMALL;
227
  ymin2 = (int)(mMin.y / DELTA_SMALL) * DELTA_SMALL;
228
 
229
  if (DELTA_SMALL / step.x  > THREE) {
230
    j = (int)(( - xmin + xmin2 ) / DELTA_SMALL);
231
    for (i = xmin2; i <= mMax.x; i += DELTA_SMALL, j++) {
232
      if (j % 10 == 0) {
233
      // we need to skip every tenth mark, to avoid overwriting big marks
234
		j = 0;
235
		continue;
236
      }
237
      from.x = i;
238
      to.x = from.x;
239
      from.y = -SMALL_HEIGHT * step.y;
240
      to.y = SMALL_HEIGHT * step.y;
241
      from = mat2Graf(from, scrMin, scrMax, mMin, mMax);
242
	  to = mat2Graf(to, scrMin, scrMax, mMin, mMax);
243
      SysColor = BLACK;
244
      _ksys_draw_line(from.x, from.y, to.x, to.y, SysColor);
245
      sprintf(buf, FORMAT, i, '\0');
246
  	  strlentemp = strlen(buf);
247
      if (from.y > scrMin.y && (DELTA_SMALL > textwidth(buf, strlentemp) * step.x)) {
248
		SysColor = SMALLFONTCOLOR;
249
		_ksys_draw_text(buf, from.x - textwidth(buf, strlentemp) / 2.0, to.y - textheight(buf, strlentemp), strlentemp, SysColor);
250
      }
251
 
252
 
253
    }
254
 
255
  }
256
 
257
  // finally small marks on Y
258
  if (DELTA_SMALL / step.y > THREE) {
259
    //_ksys_debug_puts("really small marks y painted\n");
260
    j = (int)(( - ymin + ymin2) / DELTA_SMALL);
261
    for (i = ymin2; i <= mMax.y; i += DELTA_SMALL, j++) {
262
      if (j % 10 == 0) {
263
      // we need to skip every tenth, to avoid overwriting
264
		j = 0;
265
		continue;
266
      }
267
      from.y = i;
268
      to.y = from.y;
269
      from.x = -SMALL_HEIGHT * step.x;
270
      to.x = SMALL_HEIGHT * step.x;
271
      from = mat2Graf(from, scrMin, scrMax, mMin, mMax);
272
      to = mat2Graf(to, scrMin, scrMax, mMin, mMax);
273
      SysColor = BLACK;
274
      _ksys_draw_line(from.x, from.y, to.x, to.y, SysColor);
275
      sprintf(buf, FORMAT, i, '\0');
276
  	  strlentemp = strlen(buf);
277
      if (from.x > scrMin.x && (DELTA_SMALL > textheight(buf, strlentemp) * step.y)) {
278
       	SysColor = SMALLFONTCOLOR;
279
       	_ksys_draw_text(buf, from.x + TEXT_X, from.y - textheight(buf, strlentemp) / 2.0, strlentemp, SysColor);
280
      }
281
    }
282
  }
283
 
284
}
285
 
286
/*
287
  ends fucking piece of shit
288
*/
289
 
290
void drawFunction( function_t fi, TCoord scrMin, TCoord scrMax,
291
		   TCoord mMin, TCoord mMax, int color) {
292
  double x;
293
  double y;
294
  int firstPoint = 1;
295
  TCoord p, p0 = {0.0, 0.0}, step;
296
 
297
  drawAxis(scrMin, scrMax, mMin, mMax);
298
 
299
  SysColor = color;
300
  step.x = (mMax.x - mMin.x) / (scrMax.x - scrMin.x);
301
 
302
  for (x = mMin.x; x < mMax.x; x += step.x) {
303
    y = fi(x);
304
// function is defined here and gets in the range
305
    if (1) { // тут было условие, что функция правильно вычислена
306
      if ((y > mMin.y) && (y < mMax.y)) {
307
	      p = mat2Graf(coord(x, y), scrMin, scrMax, mMin, mMax);
308
	// if it's our first point, only remember its coords
309
	// otherwise, draw a line from prev to current
310
      	if (firstPoint == 0) {
311
      	  _ksys_draw_line(p0.x, p0.y, p.x, p.y, SysColor);
312
        } else firstPoint = 0;
313
     	p0 = p;
314
      }
315
      else {// too big/small
316
	      firstPoint = 1;
317
      }
318
    }
319
    else { // no value
320
      firstPoint = 1;
321
    }
322
  }
323
 
324
}
325
 
326
// итоговая версия читалки текстовых файлов
327
int load_points3() {
328
	ksys_bdfe_t bdfe;
329
	int filePointer = 0;
330
 
331
	int i,j,k;
332
	double d;
333
	dword filesize, num_number;
334
 
335
	double* p2=0;
336
 
337
	// get file size
338
	int rr = _ksys_file_get_info(edit_path, &bdfe);
339
	sprintf(debuf, "getsize: %d\n", rr);
340
	_ksys_debug_puts(debuf);
341
	if (rr != 0) {
342
		_ksys_draw_text((char*)er_file_not_found, 10, 10, strlen(er_file_not_found), 0x90FF0000);
343
		return 0;
344
	}
345
 
346
	filesize = bdfe.size;
347
	num_number = filesize / 2;
348
 
349
	HugeBuf = (char*)malloc(filesize + 1); // разбираем как строку, отсюда терминатор \0
350
 
351
	for (i=0;i
352
		HugeBuf[i] = 0;
353
 
354
	rr = _ksys_file_read_file(edit_path, 0, filesize, HugeBuf, nullptr);
355
	sprintf(debuf, "read3: %d\n", rr);
356
	_ksys_debug_puts(debuf);
357
 
358
	strcpy(full_head, header);
359
	strcpy(full_head+strlen(full_head), " - ");
360
	strcpy(full_head+strlen(full_head), edit_path);		// bad code
361
 
362
	// а теперь разобраться в этом
363
 
364
	i=0;
365
	k=0;
366
	while (i < filesize) {
367
 
368
		while (isalpha(HugeBuf[i]) && i
369
		if (i == filesize) break;
370
		if (k==4 && HugeBuf[i] == '=') {
371
			//sprintf(debuf,"function: %S",HugeBuf + i);
372
			//_ksys_debug_puts(debuf);
373
			// we have a function here
374
			//HugeBuf[0] = ' ';
375
			funct = HugeBuf + i + 1;
376
			strcpy(full_head+strlen(full_head), ". Function y=");
377
			strcpy(full_head+strlen(full_head), funct);
378
			return 1;
379
		}
380
 
381
		d = convert(HugeBuf+i, &j);
382
		if (d == ERROR) {
383
			sprintf(debuf, "Error in input file, byte %d, count %d\n", i, k);
384
			_ksys_debug_puts(debuf);
385
			_ksys_draw_text((char*)debuf, 10, 10, strlen(debuf), 0x000000);
386
			return 0;
387
		}
388
		if (d == ERROR_END) {
389
			_ksys_debug_puts("EOF :)!\n");
390
			break;
391
		}
392
 
393
		i+=j;
394
		switch (k) {
395
			case 0:
396
				x1=d;
397
				break;
398
			case 1:
399
				x2=d;
400
				break;
401
			case 2:
402
				y1=d;
403
				break;
404
			case 3:
405
				y2=d;
406
				break;
407
			default: {
408
				if (p2 == NULL)
409
					p2 = (double*)malloc(num_number * 8);
410
				p2[k-4]=d;
411
			}
412
		}
413
		k++;
414
	}
415
//	sprintf(debuf, "(%f,%f)-(%f,%f)",x1,y1,x2,y2);
416
//	_ksys_debug_puts(debuf);
417
	point_count=(k - 4)/2;
418
 
419
	//
420
	points = (double*)malloc(point_count * 2 * 8);
421
	for (i = 0; i < point_count * 2; i++)
422
		points[i] = p2[i];
423
	free(p2);
424
//	sprintf(debuf, "count: %d\n", point_count);
425
//	_ksys_debug_puts(debuf);
426
	sprintf(debuf, ". Number of points: %u.", point_count);
427
	strcpy(full_head+strlen(full_head), debuf);
428
	free(HugeBuf);
429
	HugeBuf = NULL;
430
	return 1;
431
}
432
 
433
// вычислить заданную функцию или кусочно-линейную между точками
434
double fu(double x) {
435
	int i;
436
	double res;
437
 
438
	if (funct) {
439
		set_exp(funct,x);
440
		get_exp(&res);		// парсить для каждого значения х? да я с ума сошел.
441
		return res;
442
	}
443
 
444
	if (point_count == 0) {
445
		return 0.0;
446
	}
447
 
448
	if (x <= points[0])
449
		return points[1];
450
	if (x >= points[(point_count-1) * 2])
451
		return points[(point_count-1) * 2 + 1];
452
 
453
	for (i = 0; i < point_count; i++) {
454
		if ((x >= points[2 * i]) && (x < points[2 * (i + 1)]))
455
			break;
456
	}
457
 
458
	return (x - points[2 * i]) / (points[2 * (i + 1)] - points[2 * i])
459
		* (points[2 * (i + 1) + 1] - points[2 * i + 1]) + points[2 * i + 1];
460
 
461
}
462
 
463
void draw_window(void) {
464
	double xx0=0.0, yy0=0.0;
465
 
466
	_ksys_start_draw();
467
	_ksys_create_window(100, 80, WND_W, WND_H, full_head, 0xFFFFFF, 0x33);
468
	_ksys_end_draw();
469
 
470
	ksys_thread_t info;
471
	_ksys_thread_info(&info, 0xFFFFFFFF);
472
	int cWidth = info.winx_size - 9;
473
	int cHeight = info.winy_size - _ksys_get_skin_height() - 4;
474
 
475
	mybox.top = cHeight - 50;
476
	mybox.width = cWidth - mybox.left - 80;
477
 
478
	if (info.window_state&0x04) return; //draw nothing if window is rolled-up
479
 
480
	if (point_count == 0 && funct == NULL) {
481
		_ksys_draw_text((char *)empty_text, (cWidth - 8 * strlen(empty_text))/2,cHeight/2-25, strlen(empty_text), 0x90000000);
482
	} else {
483
		drawFunction(&fu, coord(10, 20), coord(cWidth - 20, cHeight - 70), coord(x1,y1), coord(x2,y2), 0x00ff0000);
484
	}
485
 
486
	_ksys_draw_text((char*)str_filename, 15, mybox.top + 4, strlen(str_filename), 0x90000000);
487
 
488
	edit_box_draw(&mybox);
489
 
490
	_ksys_define_button(cWidth - 70, mybox.top, 50, 21, BTN_EDIT, 0xc0c0c0);
491
	_ksys_draw_text((char*)str_editfile, cWidth - 60, mybox.top + 4, 0, 0x90000000);
492
}
493
 
494
int main() {
495
	full_head = (char*)malloc(300);
496
	strcpy(full_head, "Graph");
497
	_ksys_set_event_mask(0xC0000027);
498
	int event;
499
	while (1) {
500
		edit_box_mouse(&mybox);
501
		event = _ksys_get_event();
502
		switch (event) {
503
			case KSYS_EVENT_REDRAW:
504
				draw_window();
505
				break;
506
			case KSYS_EVENT_KEY: {
507
				ksys_oskey_t kc = _ksys_get_key();
508
				switch (kc.code) {
509
					case 0x0D:
510
						if (HugeBuf) {
511
							//sprintf(debuf, "freemem: HugeBuf = %X", HugeBuf);
512
							//_ksys_debug_puts(debuf);
513
							free(HugeBuf); // что за баг - понять не могу.
514
							HugeBuf = nullptr;
515
							funct = nullptr;
516
						}
517
						if (points) {
518
							//sprintf(debuf, "freemem: points = %X", points);
519
							//_ksys_debug_puts(debuf);
520
							free(points); // и тут. ну не обращаюсь я к этому указателю, только память в него, потом снова выделяю
521
							points = nullptr;
522
						}
523
						point_count = 0;
524
						_ksys_draw_bar(10, 10, 200, 20, 0xFFFFFF); // фон для сообщений об ошибках
525
						if (load_points3())
526
							draw_window();
527
						break;
528
					default:
529
						edit_box_key_safe(&mybox, kc);
530
				}
531
				break;
532
			}
533
			case KSYS_EVENT_BUTTON: {
534
				// button pressed; we have only one button, close
535
				uint32_t button = _ksys_get_button();
536
				if (button == BTN_QUIT)
537
					_ksys_exit();
538
				else if (button == BTN_EDIT)
539
					_ksys_exec("/sys/develop/cedit", edit_path);
540
			}
541
		}
542
	}
543
	return 0;
544
}