Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
7618 leency 1
#include "func.h"
2
#include "parser.h"
3
#include "use_library.h"
4
 
5
#ifdef AUTOBUILD
6
extern char params[1024];
7
#endif
8
char params[1024];// = "/sys/1.grf";
9
 
10
const char header[] = "Graph";
11
const char empty_text[] = "No function loaded. Type file name and press Enter. ";
12
const char er_file_not_found[] = "Cannot open file. ";
13
const char str_filename[]="Filename:";
14
const char str_editfile[]="Edit";
15
 
16
// начальные размеры
17
#define WND_W 600
18
#define WND_H 470
19
 
20
#define LIGHTGREEN 0xff0000
21
#define WHITE 0xffffff
22
#define BLACK 0x0
23
#define LIGHTBLUE 0x0000ff
24
#define LIGHTRED 0xff0000
25
 
26
// font colors
27
#define BIGFONTCOLOR BLACK
28
#define SMALLFONTCOLOR BLACK
29
 
30
#define THREE 3.0
31
// minimum space: 3 pixels
32
 
33
#define BIG_HEIGHT 4.0
34
#define SMALL_HEIGHT 2.0
35
#define TEXT_X 15.0
36
// numeric format for output
37
#define FORMAT "%f"
38
// format for two coords
39
#define FORMAT_COORD "(%f,%f)"
40
// special value to text if enough space
41
#define FORMAT_TEST "0.00"
42
 
43
#define DELTA_BIG 1.0
44
#define DELTA_SMALL 0.1
45
 
46
double *points;
47
Dword point_count = 0;
48
double x1,y1,x2,y2;
49
char *funct = NULL;
50
 
51
char *full_head;
52
 
53
char *HugeBuf = NULL;
54
 
55
char edit_path[256];
56
edit_box mybox = {0,92,WND_H-16-32,0xffffff,0x94AECE,0,0x808080,0x10000000,
57
	sizeof(edit_path)-1,0,(dword)&edit_path, 0, 0};
58
 
59
// constructor of TCoord
60
TCoord coord(double x, double y)
61
{
62
  TCoord r;
63
  r.x = x;
64
  r.y = y;
65
  return r;
66
}
67
 
68
// move and scale mathematical coords to fit screen coords
69
TCoord mat2Graf(TCoord c, TCoord scrMin, TCoord scrMax, TCoord mMin, TCoord mMax)
70
{
71
  TCoord r;
72
  if (c.x > mMax.x)
73
    c.x = mMax.x;
74
  if (c.x < mMin.x)
75
    c.x = mMin.x;
76
  if (c.y > mMax.y)
77
    c.y = mMax.y;
78
  if (c.y < mMin.y)
79
    c.y = mMin.y;
80
  r.x = (scrMax.x - scrMin.x) / (mMax.x - mMin.x) * (c.x - mMin.x) + scrMin.x;
81
  r.y = (scrMax.y - scrMin.y) / (mMax.y - mMin.y) * (mMax.y - c.y) + scrMin.y;
82
 
83
  return r;
84
}
85
 
86
// double-обертки
87
void line_d( double x1, double y1, double x2, double y2)
88
{
89
   line(di(x1), di(y1), di(x2), di(y2));
90
}
91
 
92
void outtextxy_d( double x, double y, char * text, int len)
93
{
94
   outtextxy(di(x), di(y), text, len);
95
}
96
 
97
// huge function to draw all the stuff except the function itself
98
void drawAxis( TCoord scrMin, TCoord scrMax, TCoord mMin, TCoord mMax)
99
{
100
  TCoord cZero={0.0,0.0},
101
	   gMin, gMax, gZero, step;
102
  TCoord from, to;
103
  double i=0.0;
104
  int j;
105
  double xmin, xmin2, ymin, ymin2;
106
  char buf[30]="";
107
 
108
 
109
// scr means Screen(bounding rect)
110
// m   means Mathematical
111
// g   means Graphic(real screen position)
112
 
113
  //rtlDebugOutString("draw axis called\n");
114
 
115
  //format(debuf, 30, "test: %f,%f,%f,%f\n", 123.45, 1.0, -0.9, 12.57);
116
  //rtlDebugOutString(debuf);
117
 
118
  gMin = mat2Graf(mMin, scrMin, scrMax, mMin, mMax);
119
  gMax = mat2Graf(mMax, scrMin, scrMax, mMin, mMax);
120
  gZero = mat2Graf(cZero, scrMin, scrMax, mMin, mMax);
121
 
122
  // clear
123
 // setcolor(WHITE);
124
 //rectangle(di(gMin.x), di(gMin.y), di(gMax.x), di(gMax.y));
125
  // ftopku
126
 
127
  setcolor(BLACK);
128
  // osy X
129
  line_d(gMin.x, gZero.y ,gMax.x, gZero.y);
130
  // osy Y
131
  line_d(gZero.x, gMin.y, gZero.x, gMax.y);
132
  // bounding rect
133
  line_d(gMin.x, gMin.y, gMax.x, gMin.y);
134
  line_d(gMin.x, gMax.y, gMax.x, gMax.y);
135
 
136
  line_d(gMin.x, gMin.y, gMin.x, gMax.y);
137
  line_d(gMax.x, gMin.y, gMax.x, gMax.y);
138
 
139
  // coords of the rect : lower left
140
  format(buf, 30, FORMAT_COORD, x1, y1);
141
  //rtlDebugOutString(buf);
142
  outtextxy_d(gMin.x, gMin.y + textheight(buf, 20), buf, 20);
143
  // upper left
144
  format(buf, 30, FORMAT_COORD, x1, y2);
145
  outtextxy_d(gMin.x, gMax.y - textheight(buf, 20), buf, 20);
146
  // lower right
147
  format(buf, 30, FORMAT_COORD, x2, y1);
148
  outtextxy_d(gMax.x - textwidth(buf, 20), gMin.y + textheight(buf, 20), buf, 20);
149
  // upper right
150
  format(buf, 30, FORMAT_COORD, x2, y2);
151
  outtextxy_d(gMax.x - textwidth(buf, 20), gMax.y - textheight(buf, 20), buf, 20);
152
 
153
  //rtlDebugOutString("some lines painted\n");
154
 
155
  step.x = (mMax.x - mMin.x) / (scrMax.x - scrMin.x);
156
  step.y = (mMax.y - mMin.y) / (scrMax.y - scrMin.y);
157
 
158
// round values
159
  xmin = id(di((mMin.x / DELTA_BIG) * DELTA_BIG));
160
  ymin = id(di((mMin.y / DELTA_BIG) * DELTA_BIG));
161
 
162
  // (0,0)
163
 
164
  if ((x1 * x2 <= 0.0) && (y1 * y2 <= 0.0))
165
  {
166
	  from.x=0.0;
167
	  from.y=0.0;
168
	  from = mat2Graf(from, scrMin, scrMax, mMin, mMax);
169
	  setcolor(BLACK);
170
	  format(buf, 30, FORMAT, 0.0);
171
	  outtextxy_d(from.x - textwidth(buf, 20), from.y + textheight(buf, 20), buf, 20);
172
  }
173
 
174
 
175
  // big marks on X
176
  //settextstyle(0, 0, 1);
177
  if (DELTA_BIG / step.x > THREE)
178
  {
179
    for (i = xmin; i <= mMax.x; i += DELTA_BIG)
180
    {
181
	  if (i != 0.0)
182
	  {
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
		  setcolor(BLACK);
190
		  line_d(from.x, from.y, to.x, to.y);
191
		  // write number
192
		  format(buf, 30, FORMAT, i);
193
		  // if it fits in the GAP, then write it
194
		  if (from.y > scrMin.y && (DELTA_BIG > (textwidth(buf, 20) + 1.0) * step.x))
195
		  {
196
			   setcolor(BIGFONTCOLOR);
197
			   outtextxy_d(from.x - textwidth(buf, 20) / 2.0, to.y - textheight(buf, 20), buf, 20);
198
		  }
199
	  }
200
    }
201
  }
202
  //rtlDebugOutString("big marks x painted\n");
203
 
204
  // big marks on Y
205
  if (DELTA_BIG / step.y > THREE)
206
  {
207
    for (i = ymin; i <= mMax.y; i += DELTA_BIG)
208
    {
209
	  if (i != 0.0)
210
	  {
211
		  from.y = i;
212
		  to.y = from.y;
213
		  from.x = -BIG_HEIGHT * step.x;
214
		  to.x = BIG_HEIGHT * step.x;
215
		  from = mat2Graf(from, scrMin, scrMax, mMin, mMax);
216
		  to = mat2Graf(to, scrMin, scrMax, mMin, mMax);
217
		  setcolor(BLACK);
218
		  line_d(from.x, from.y, to.x, to.y);
219
		  format(buf, 30, FORMAT, i);
220
		  if (from.x > scrMin.x && (DELTA_BIG > textheight(buf, 20) * step.y))
221
		  {
222
			   setcolor(BIGFONTCOLOR);
223
			 outtextxy_d(from.x + TEXT_X, to.y - textheight(buf, 20) / 2.0, buf, 20);
224
		  }
225
	  }
226
    }
227
  }
228
 
229
  xmin2 = id(di(mMin.x / DELTA_SMALL)) * DELTA_SMALL;
230
  ymin2 = id(di(mMin.y / DELTA_SMALL)) * DELTA_SMALL;
231
 
232
  if (DELTA_SMALL / step.x  > THREE)
233
  {
234
    j = di((( - xmin + xmin2 ) / DELTA_SMALL));
235
    for (i = xmin2; i <= mMax.x; i += DELTA_SMALL, j++)
236
    {
237
      if (j % 10 == 0)
238
      {
239
      // we need to skip every tenth mark, to avoid overwriting big marks
240
		j = 0;
241
		continue;
242
      }
243
      from.x = i;
244
      to.x = from.x;
245
      from.y = -SMALL_HEIGHT * step.y;
246
      to.y = SMALL_HEIGHT * step.y;
247
      from = mat2Graf(from, scrMin, scrMax, mMin, mMax);
248
	  to = mat2Graf(to, scrMin, scrMax, mMin, mMax);
249
      setcolor(BLACK);
250
      line_d(from.x, from.y, to.x, to.y);
251
      format(buf, 30, FORMAT, i);
252
 
253
      if (from.y > scrMin.y && (DELTA_SMALL > textwidth(buf, 20) * step.x))
254
      {
255
		setcolor(SMALLFONTCOLOR);
256
		outtextxy_d(from.x - textwidth(buf, 20) / 2.0, to.y - textheight(buf, 20), buf, 20);
257
      }
258
 
259
 
260
    }
261
 
262
  }
263
 
264
  // finally small marks on Y
265
  if (DELTA_SMALL / step.y > THREE)
266
  {
267
    //rtlDebugOutString("really small marks y painted\n");
268
    j = di((( - ymin + ymin2) / DELTA_SMALL));
269
    for (i = ymin2; i <= mMax.y; i += DELTA_SMALL, j++)
270
    {
271
      if (j % 10 == 0)
272
      {
273
      // we need to skip every tenth, to avoid overwriting
274
		j = 0;
275
		continue;
276
      }
277
      from.y = i;
278
      to.y = from.y;
279
      from.x = -SMALL_HEIGHT * step.x;
280
      to.x = SMALL_HEIGHT * step.x;
281
      from = mat2Graf(from, scrMin, scrMax, mMin, mMax);
282
      to = mat2Graf(to, scrMin, scrMax, mMin, mMax);
283
      setcolor(BLACK);
284
      line_d(from.x, from.y, to.x, to.y);
285
      format(buf, 30, FORMAT, i);
286
      if (from.x > scrMin.x && (DELTA_SMALL > textheight(buf, 20) * step.y))
287
      {
288
       	setcolor(SMALLFONTCOLOR);
289
       	outtextxy_d(from.x + TEXT_X, from.y - textheight(buf, 20) / 2.0, buf, 20);
290
      }
291
    }
292
  }
293
 
294
}
295
 
296
/*
297
  ends fucking piece of shit
298
*/
299
 
300
void drawFunction( function_t fi, TCoord scrMin, TCoord scrMax,
301
		   TCoord mMin, TCoord mMax, DWORD color)
302
{
303
  double x;
304
  double y;
305
  int firstPoint = 1;
306
  TCoord p, p0 = {0.0, 0.0}, step;
307
 
308
  drawAxis(scrMin, scrMax, mMin, mMax);
309
 
310
  setcolor(color);
311
  step.x = (mMax.x - mMin.x) / (scrMax.x - scrMin.x);
312
 
313
  for (x = mMin.x; x < mMax.x; x += step.x)
314
  {
315
    y = fi(x);
316
// function is defined here and gets in the range
317
    if (1) // тут было условие, что функция правильно вычислена
318
    {
319
      if ((y > mMin.y) && (y < mMax.y))
320
      {
321
	      p = mat2Graf(coord(x, y), scrMin, scrMax, mMin, mMax);
322
	// if it's our first point, only remember its coords
323
	// otherwise, draw a line_d from prev to current
324
      	if (firstPoint == 0)
325
        {
326
      	  line_d(p0.x, p0.y, p.x, p.y);
327
        }
328
      	else
329
    	  firstPoint = 0;
330
 
331
     	p0 = p;
332
      }
333
      else // too big/small
334
      {
335
	      firstPoint = 1;
336
      }
337
    }
338
    else // no value
339
    {
340
      firstPoint = 1;
341
    }
342
  }
343
}
344
 
345
// итоговая версия читалки текстовых файлов
346
int load_points3()
347
{
348
	kosFileInfo fileInfo;
349
	kosBDVK bdvk;
350
	int filePointer = 0;
351
 
352
	int i,j,k;
353
	double d;
354
	Dword filesize, num_number;
355
 
356
	double *p2=0;
357
 
358
	// get file size
359
	strcpy(fileInfo.fileURL,edit_path);
360
	fileInfo.OffsetLow = 0;
361
	fileInfo.OffsetHigh = 0;
362
	fileInfo.dataCount = 0;
363
	fileInfo.rwMode = 5;
364
	fileInfo.bufferPtr = (Byte *)&bdvk;
365
	Dword rr = kos_FileSystemAccess( &(fileInfo) ); // в CKosFile нет определения размера
366
	sprintf(debuf, "getsize: %U\n", rr);
367
	rtlDebugOutString(debuf);
368
	if (rr != 0)
369
	{
370
		kos_WriteTextToWindow(10,10,0x90,0xFF0000,(char*)er_file_not_found,strlen(er_file_not_found));
371
		return 0;
372
	}
373
 
374
	filesize = bdvk.size_low;
375
	num_number = filesize / 2;
376
 
377
	HugeBuf = (char *)allocmem(filesize + 1); // разбираем как строку, отсюда терминатор \0
378
 
379
	for (i=0;i
380
		HugeBuf[i] = 0;
381
 
382
	strcpy(fileInfo.fileURL,edit_path);
383
	fileInfo.OffsetLow = 0;
384
 
385
	fileInfo.OffsetHigh = 0;
386
	fileInfo.dataCount = filesize;
387
	fileInfo.rwMode = 0;
388
	fileInfo.bufferPtr = (Byte *)HugeBuf;
389
	rr = kos_FileSystemAccess( &(fileInfo) );	// какая-то проблема с hands.dll, CKosFile не работал
390
 
391
	sprintf(debuf, "read3: %U\n", rr);
392
	rtlDebugOutString(debuf);
393
 
394
	// а теперь разобраться в этом
395
 
396
	i=0;
397
	k=0;
398
	while (i < filesize)
399
	{
400
 
401
		while (isalpha(HugeBuf[i]) && i
402
		if (i == filesize) break;
403
		if (k==4 && HugeBuf[i] == '=')
404
		{
405
			//sprintf(debuf,"function: %S",HugeBuf + i);
406
			//rtlDebugOutString(debuf);
407
			// we have a function here
408
			//HugeBuf[0] = ' ';
409
			funct = HugeBuf + i + 1;
410
			sprintf(full_head, "Graph: %S. Function: y=%S", edit_path, funct);
411
			return 1;
412
		}
413
 
414
		d = convert(HugeBuf+i, &j);
415
		if (d == ERROR)
416
		{
417
			sprintf(debuf, "Error in input file, byte %U, count %U\n", i, k);
418
			kos_WriteTextToWindow(10, 10, 0x90, 0xFF0000, (char*)debuf, 0);
419
			return 0;
420
		}
421
		if (d == ERROR_END)
422
		{
423
			rtlDebugOutString("EOF :)!\n");
424
			break;
425
		}
426
 
427
		i+=j;
428
		switch (k)
429
		{
430
		case 0:
431
			x1=d;
432
			break;
433
		case 1:
434
			x2=d;
435
			break;
436
		case 2:
437
			y1=d;
438
			break;
439
		case 3:
440
			y2=d;
441
			break;
442
		default:
443
			{
444
				if (p2 == NULL)
445
					p2 = (double *)allocmem(num_number * 8);
446
				p2[k-4]=d;
447
			}
448
		}
449
		k++;
450
	}
451
//	format(debuf, 30, "(%f,%f)-(%f,%f)",x1,y1,x2,y2);
452
//	rtlDebugOutString(debuf);
453
	point_count=(k - 4)/2;
454
 
455
	//
456
	points = (double *)allocmem(point_count * 2 * 8);
457
	for (i = 0; i < point_count * 2; i++)
458
		points[i] = p2[i];
459
	freemem(p2);
460
//	sprintf(debuf, "count: %U\n", point_count);
461
//	rtlDebugOutString(debuf);
462
	sprintf(full_head, "Graph: %S. Number of points: %U", edit_path, point_count);
463
	freemem(HugeBuf);
464
	HugeBuf = NULL;
465
	return 1;
466
}
467
 
468
// calculate given function or piecewise linear between points
469
double fu(double x)
470
{
471
	int i;
472
	double res;
473
 
474
 
475
	if (funct)
476
	{
477
		//set_exp(funct,x);  //!!!!!
478
		set_exp(funct); //!!!!
479
		get_exp(&res);	// parse for each value of x? Yes, I'm crazy.
480
		return res;
481
	}
482
 
483
	if (point_count == 0)
484
	{
485
		return 0.0;
486
	}
487
 
488
	if (x <= points[0])
489
		return points[1];
490
	if (x >= points[(point_count-1) * 2])
491
		return points[(point_count-1) * 2 + 1];
492
 
493
	for (i = 0; i < point_count; i++)
494
	{
495
		if ((x >= points[2 * i]) && (x < points[2 * (i + 1)]))
496
			break;
497
	}
498
 
499
	return (x - points[2 * i]) / (points[2 * (i + 1)] - points[2 * i])
500
		* (points[2 * (i + 1) + 1] - points[2 * i + 1]) + points[2 * i + 1];
501
 
502
}
503
 
504
void draw_window(void)
505
{
506
	double xx0=0.0, yy0=0.0;
507
 
508
	kos_WindowRedrawStatus(1);
509
	kos_DefineAndDrawWindow(100,80,WND_W,WND_H, 0x33,0xFFFFFF,0,0,(Dword)full_head);
510
	kos_WindowRedrawStatus(2);
511
 
512
	sProcessInfo info;
513
	kos_ProcessInfo(&info, 0xFFFFFFFF);
514
	int cWidth = info.processInfo.width - 9;
515
	int cHeight = info.processInfo.height - kos_GetSkinHeight() - 4;
516
 
517
	mybox.top = cHeight - 50;
518
	mybox.width = cWidth - mybox.left - 80;
519
 
520
	if (info.processInfo.status_window&0x04) return; //draw nothing if window is rolled-up
521
 
522
	if (point_count == 0 && funct == NULL)
523
	{
524
		kos_WriteTextToWindow((cWidth - 8 * strlen(empty_text))/2,cHeight/2-25,0x90,
525
			0x000000,(char *)empty_text,strlen(empty_text));
526
	}
527
	else
528
	{
529
		drawFunction(&fu, coord(10, 20), coord(id(cWidth - 20), id(cHeight - 70)),
530
							coord(x1,y1), coord(x2,y2), 0x00ff0000);
531
 
532
	}
533
 
534
	kos_WriteTextToWindow(15, mybox.top + 4, 0x90, 0x000000, (char*)str_filename, strlen(str_filename));
535
 
536
	edit_box_draw((DWORD)&mybox);
537
 
538
	kos_DefineButton(cWidth - 70, mybox.top, 50, 21, 5, 0xc0c0c0);
539
	kos_WriteTextToWindow(cWidth - 60, mybox.top + 4, 0x90, 0x000000, (char*)str_editfile,0);
540
}
541
 
542
void kos_Main()
543
{
544
	kos_InitHeap();
545
	load_edit_box();
546
	full_head = (char*)allocmem(300);
547
	strcpy(full_head, header);
548
	if (params[0])
549
	{
550
		rtlDebugOutString("launched with params");
551
		rtlDebugOutString((char*)params);
552
		strcpy(edit_path, params);
553
		mybox.size=mybox.pos=strlen(edit_path);
554
		load_points3();
555
		rtlDebugOutString("data loaded.\n");
556
	}
557
	mybox.flags += ed_focus;
558
	kos_SetMaskForEvents(EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_MOUSE + EVM_MOUSE_FILTER);
559
	for (;;)
560
	{
561
		switch (kos_WaitForEvent())
562
		{
563
		case EM_MOUSE_EVENT:
564
			edit_box_mouse((dword)&mybox);
565
			break;
566
		case EM_KEY_PRESS:
567
			// key pressed, read it
568
			Dword ckeys, shift, ctrl;
569
			dword key_editbox;
570
			Byte key_ascii, key_scancode;
571
			kos_GetKeys(key_editbox, key_ascii, key_scancode);
572
 
573
			if (SCAN_CODE_ENTER == key_scancode)
574
			{
575
				if (HugeBuf!=NULL)
576
				{
577
					//sprintf(debuf, "freemem: HugeBuf = %X", HugeBuf);
578
					//rtlDebugOutString(debuf);
579
					freemem((void*)HugeBuf);		// что за баг - понять не могу.
580
					HugeBuf = NULL;
581
					funct = NULL;
582
				}
583
				if (points!=NULL)
584
				{
585
					//sprintf(debuf, "freemem: points = %X", points);
586
					//rtlDebugOutString(debuf);
587
					freemem((void*)points);		// и тут. ну не обращаюсь я к этому указателю, только память в него
588
											// потом снова выделяю
589
					points = NULL;
590
				}
591
				point_count = 0;
592
				kos_DrawBar(10,10,200,20,0xFFFFFF); // background for error messages
593
				if (load_points3())
594
					draw_window();
595
				rtlDebugOutString("Enter");
596
			}
597
			else
598
			{
599
				__asm
600
				{
601
					mov eax, key_editbox
602
				}
603
				edit_box_key((dword)&mybox);
604
			}
605
			break;
606
 
607
		case EM_BUTTON_CLICK:
608
			Dword button;
609
			kos_GetButtonID(button);
610
			if (button == 1) kos_ExitApp();
611
			if (button == 5) {
612
				kos_AppRun("/sys/tinypad", edit_path);
613
			}
614
			break;
615
 
616
		case EM_WINDOW_REDRAW:
617
			draw_window();
618
			break;
619
		}
620
	}
621
}
622