Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
990 barsuk 1
 
2
 
3
#include "calc.h"
4
#include "kosSyst.h"
5
//#include "KosFile.h"
6
7
extern DWORD def_col_width, def_row_height;
8
 
9
extern char ***cells;
10
extern DWORD *col_width, *row_height;
11
extern char ***values;
12
13
extern DWORD *col_left, *row_top;
14
 
15
// буфер обмена
16
 
17
extern DWORD buf_col, buf_row;
18
extern DWORD buf_old_x, buf_old_y;
19
20
extern bool sel_moved;
21
 
22
int cf_x0, cf_x1, cf_y0, cf_y1;
23
 
24
25
 
26
 
27
28
 
29
 
30
extern const char *sFileSign;
31
32
struct cell_list
33
 
34
	int x,y;
35
	cell_list *next;
36
};
37
38
39
 
40
 
41
{
42
	int i, r = 0;
43
	if (x > col_count)
44
		x = col_count;
45
	for (i = 0; i < x; i++)
46
		r+=col_width[i];
47
	return r;
48
}
49
50
// аналог
51
 
52
{
53
	int i, r = 0;
54
	if (y > row_count)
55
		y = row_count;
56
	for (i = 0; i < y; i++)
57
		r+=row_height[i];
58
	return r;
59
}
60
61
62
 
63
 
64
 
65
{
66
	char *r = (char*)allocmem(3);
67
	if (i <= 26)
68
	{
69
		r[0] = 'A' + i - 1;
70
		r[1] = '\0';
71
		return r;
72
	}
73
	else if (i % 26 == 0)	// фикс бага который не понял - да простят меня читатели и юзера
74
	{
75
		r[0] = (i / 26) - 1 + 'A' - 1;
76
		r[1] = 'Z';
77
		r[2] = '\0';
78
		return r;
79
	}
80
	r[0] = (i / 26) + 'A' - 1;
81
	r[1] = (i % 26) + 'A' - 1;
82
	r[2] = '\0';
83
	return r;
84
}
85
86
// -"- строки
87
 
88
{
89
	char *r = (char*)allocmem(3);
90
	if (i <= 9)
91
	{
92
		r[0] = '0' + i;
93
		r[1] = '\0';
94
		return r;
95
	}
96
	r[0] = (i / 10) + '0';
97
	r[1] = (i % 10) + '0';
98
	r[2] = '\0';
99
	return r;
100
}
101
102
// инициализация ячеек
103
 
104
{
105
	int i, j;
106
107
	//col_count = WND_W / def_col_width;
108
 
109
110
	col_width = (DWORD*)allocmem(col_count * sizeof(DWORD));
111
 
112
	col_left = (DWORD*)allocmem(col_count * sizeof(DWORD));
113
	row_top = (DWORD*)allocmem(row_count * sizeof(DWORD));
114
	for (i = 0; i < col_count; i++)
115
	{
116
		col_width[i] = def_col_width;
117
	}
118
119
	for (i = 0; i < row_count; i++)
120
 
121
		row_height[i] = def_row_height;
122
	}
123
124
	cells = (char***)allocmem(col_count * sizeof(char**));
125
 
126
	for (i = 0; i < col_count; i++)
127
	{
128
		cells[i] = (char**)allocmem(row_count * sizeof(char*));
129
		values[i] = (char**)allocmem(row_count * sizeof(char*));
130
		for (j = 0; j < row_count; j++)
131
		{
132
			cells[i][j] = NULL;
133
			if (i == 0 && j)
134
			{
135
				cells[i][j] = make_row_cap(j);
136
			}
137
			else if (j == 0 && i)
138
			{
139
				cells[i][j] = make_col_cap(i);
140
			}
141
142
		}
143
 
144
}
145
146
void reinit()
147
 
148
	int i, j;
149
150
	for (i = 0; i < col_count; i++)
151
 
152
		col_width[i] = def_col_width;
153
	}
154
155
	for (i = 0; i < row_count; i++)
156
 
157
		row_height[i] = def_row_height;
158
	}
159
160
	for (i = 1; i < col_count; i++)
161
 
162
		for (j = 1; j < row_count; j++)
163
		{
164
			if (cells[i][j])
165
				freemem(cells[i][j]);
166
			cells[i][j] = NULL;
167
			if (values[i][j])
168
				freemem(values[i][j]);
169
			values[i][j] = NULL;
170
		}
171
	}
172
}
173
174
void fill_cells(int sel_x, int sel_y, int sel_end_x, int sel_end_y, int old_end_x, int old_end_y)
175
 
176
	// итак, (sel_x, sel_y) :: (old_end_x, old_end_y) - источник
177
	// результат хранится либо в строке sel_x .. sel_end_x, либо в столбце sel_y .. sel_end_y
178
179
	int i, start, end, step, gdir = -1;
180
 
181
	char *source;
182
183
	cf_x0 = cf_y0 = 0;
184
 
185
	cf_y1 = row_count;
186
187
	if (sel_end_x == -1)
188
 
189
	if (sel_end_y == -1)
190
		sel_end_y = sel_y;
191
192
	// если направления выделений перпендикулярны, то просто в цикле повторяем то же, что для 1 ячейки:
193
 
194
	if (old_end_x == sel_end_x && sel_y == old_end_y)
195
 
196
		gdir = 0;
197
	}
198
	else if (old_end_y == sel_end_y && sel_x == old_end_x)
199
	{
200
		gdir = 1;
201
	}
202
203
	//sprintf(debuf, "fuck in ass %U %U %U %U %U %U dir %U",sel_x,sel_y,sel_end_x,sel_end_y,old_end_x,old_end_y,gdir);
204
 
205
	if (gdir != -1)
206
	{
207
		int gstep = gdir ? sign(old_end_y - sel_y) : sign(old_end_x - sel_x);
208
		if (gstep == 0)
209
		{
210
		/*	if (gdir)
211
			{
212
				//old_end_y += 1;
213
			}
214
			else
215
			{
216
				//old_end_x += 1;
217
			}
218
		*/
219
			gstep = 1;
220
		}
221
222
		for (;gdir ? (sel_y != old_end_y + gstep) : (sel_x != old_end_x + gstep);
223
 
224
		{
225
			//sprintf(debuf, "cycle %U %U %U %U %U %U dir %U",sel_x,sel_y,sel_end_x,sel_end_y,old_end_x,old_end_y,gdir);
226
			//rtlDebugOutString(debuf);
227
			int dir;
228
			source = cells[sel_x][sel_y];
229
			if (gdir == 0)
230
			{
231
				start = sel_y;
232
				end = sel_end_y;
233
				step = (sel_y < sel_end_y ? 1 : -1);
234
				dir = 1;
235
			}
236
			else
237
			{
238
				start = sel_x;
239
				end = sel_end_x;
240
				step = (sel_x < sel_end_x ? 1 : -1);
241
				dir = 0;
242
			}
243
244
			//sprintf(debuf, "cyc %U %U %U %U",start,end,step,dir);
245
 
246
			for (i = start + step; i != end + step; i += step)
247
			{
248
				//char **p = &cells[dir ? sel_x : i][dir ? i : sel_end_y];
249
				//sprintf(debuf, "to %U %U dir %U copying '%S'",dir ? sel_x : i,dir ? i : sel_y,dir,source);
250
				//rtlDebugOutString(debuf);
251
				if (cells[dir ? sel_x : i][dir ? i : sel_y])
252
				{
253
					freemem(cells[dir ? sel_x : i][dir ? i : sel_y]);
254
				}
255
				if (source)
256
				{
257
					cells[dir ? sel_x : i][dir ? i : sel_y] = change_formula(source, dir ? 0 : (i - start), dir ? (i - start) : 0);
258
					//cells[dir ? sel_x : i][dir ? i : sel_y] = (char *)allocmem(strlen(source) + 1);
259
					//strcpy(cells[dir ? sel_x : i][dir ? i : sel_y], source);
260
				}
261
				else
262
					cells[dir ? sel_x : i][dir ? i : sel_y] = NULL;
263
			}
264
		}
265
	}
266
267
	// а вот если параллельны...
268
 
269
270
	if (sel_x == sel_end_x && sel_x == old_end_x)
271
 
272
		pdir = 0;
273
	}
274
	if (sel_y == sel_end_y && sel_y == old_end_y)
275
	{
276
		pdir = 1;
277
	}
278
	if (pdir != -1)
279
	{
280
		// арифметическая прогрессия - если числа. и тупо размножитьт последнее, если нет
281
282
		sprintf(debuf, "maybe arith dir %U", pdir);
283
 
284
285
		int is_arith = 1;
286
 
287
		if (gstep == 0)
288
			gstep = 1;
289
290
		for (int i = pdir ? sel_y : sel_x; i != pdir ? (old_end_y + gstep) : (old_end_x + gstep); i++)
291
 
292
			convert_error = 0;
293
			sprintf(debuf,"cell %U %U", !pdir ? sel_x : i, !pdir ? i : sel_y);
294
			rtlDebugOutString(debuf);
295
			if (cells[!pdir ? sel_x : i][!pdir ? i : sel_y])
296
			{
297
				double d = atof(cells[!pdir ? sel_x : i][!pdir ? i : sel_y]);
298
				if (convert_error)
299
				{
300
					rtlDebugOutString("failed arith");
301
					is_arith = 0;
302
					break;
303
				}
304
			}
305
			else
306
			{
307
				is_arith = 0;
308
				rtlDebugOutString("failed arith in null");
309
				break;
310
			}
311
		}
312
313
		double arith_first, arith_step;
314
 
315
		{
316
			rtlDebugOutString("really arith");
317
			arith_first = atof(cells[sel_x][sel_y]);
318
			arith_step = atof(cells[pdir ? sel_x : old_end_x][pdir ? sel_y : old_end_y]) - arith_first;
319
			arith_first += arith_step * pdir ? abs(sel_end_x - old_end_x) : abs(sel_end_y - old_end_y);
320
		}
321
		else
322
			rtlDebugOutString("none arith");
323
324
		// собственно заполнение
325
 
326
		{
327
			if (cells[pdir ? sel_x : i][pdir ? i : sel_y])
328
				freemem(cells[pdir ? sel_x : i][pdir ? i : sel_y]);
329
			if (is_arith)
330
			{
331
				cells[pdir ? sel_x : i][pdir ? i : sel_y] = ftoa(arith_first);
332
				arith_first += arith_step;
333
			}
334
			else
335
			{
336
				if (cells[sel_x][sel_y])
337
				{
338
					cells[pdir ? sel_x : i][pdir ? i : sel_y] = (char*)allocmem(strlen(cells[sel_x][sel_y]) + 1);
339
					strcpy(cells[pdir ? sel_x : i][pdir ? i : sel_y], cells[sel_x][sel_y]);
340
				}
341
			}
342
		}
343
	}
344
	*/
345
346
	calculate_values();
347
 
348
349
const char *csv_name = ".csv";
350
 
351
int str_is_csv(char *str)
352
 
353
	int i, j = 0;
354
355
	for (i = 0; i < strlen(str); i++)
356
 
357
		if (str[i] == csv_name[j])
358
		{
359
			j++;
360
			if (j == strlen(csv_name))
361
				return 1;
362
		}
363
		else
364
		{
365
			j = 0;
366
		}
367
	}
368
	return 0;
369
}
370
371
int Kos_FileWrite(kosFileInfo &fileInfo, char *line, int mode = 3) // если mode = 2 - перезаписать файл
372
 
373
	int res = 0;
374
	fileInfo.dataCount = strlen(line);
375
	fileInfo.bufferPtr = (Byte*)line;
376
	fileInfo.rwMode = mode;
377
	res = kos_FileSystemAccess(&fileInfo);
378
	if (res != 0)
379
		return 0;
380
	fileInfo.OffsetLow += fileInfo.dataCount;
381
	return 1;
382
}
383
384
int SaveCSV(char *fname)
385
 
386
	int i, j;
387
	int min_col = col_count, min_row = row_count, max_row = -1, max_col = -1;
388
	int first = 1;
389
390
	kosFileInfo fileInfo;
391
 
392
	strcpy(fileInfo.fileURL,fname);
393
	fileInfo.OffsetLow = 0;
394
	fileInfo.OffsetHigh = 0;
395
	fileInfo.rwMode = 8;	// delete
396
397
	rtlDebugOutString("savecsv: old file deleted");
398
 
399
	for (i = 1; i < col_count; i++)
400
 
401
		for (j = 1; j < row_count; j++)
402
		{
403
			if (cells[i][j])
404
			{
405
				min_col = min(min_col, i);
406
				min_row = min(min_row, j);
407
				max_col = max(max_col, i);
408
				max_row = max(max_row, j);
409
			}
410
		}
411
	}
412
413
	sprintf(debuf, "col %U %U row", min_col, max_col, min_row, max_row);
414
 
415
416
	for (j = min_row; j <= max_row; j++)
417
 
418
		char buffer[1024]; // не надо так делать
419
		int buf_len = 0;
420
421
		memset((Byte*)buffer, 0, 1024);
422
 
423
		for (i = min_col; i <= max_col; i++)
424
 
425
			char *cur = values[i][j] ? values[i][j] : cells[i][j];
426
			if (cur)
427
			{
428
				buffer[buf_len++] = '\"';
429
				for (int k = 0; k < strlen(cur); k++)
430
				{
431
					if (cur[k] == '\"')
432
						buffer[buf_len++] = '\"';	// кавычек - по две
433
					buffer[buf_len++] = cur[k];
434
				}
435
				buffer[buf_len++] = '\"';
436
			}
437
			buffer[buf_len++] = ';';
438
		}
439
		rtlDebugOutString(buffer);
440
		// очередная строка теперь в буфере
441
		buffer[buf_len++] = '\n';
442
		if (!Kos_FileWrite(fileInfo, buffer, first ? (first = 0, 2) : 3))
443
			return 0;
444
	}
445
	return 1;
446
447
}
448
 
449
#define BUF_FOR_ALL 5000
450
 
451
{
452
	kosFileInfo fileInfo;
453
	char *buffer = (char*)allocmem(BUF_FOR_ALL);	// ужас! но пока что достаточно
454
	int filePointer = 0;
455
456
	int i,j;
457
 
458
459
	if (str_is_csv(fname))
460
 
461
462
463
 
464
 
465
	memset((Byte*)&fileInfo, 0, sizeof(fileInfo));
466
 
467
	fileInfo.OffsetLow = 0;
468
	fileInfo.OffsetHigh = 0;
469
	fileInfo.rwMode = 8;
470
	res = kos_FileSystemAccess(&fileInfo);	// удалить
471
	fileInfo.dataCount = strlen(sFileSign);
472
	fileInfo.bufferPtr = (Byte*)sFileSign;
473
	fileInfo.rwMode = 2;
474
	res = kos_FileSystemAccess(&fileInfo);
475
	if (res != 0)
476
		return 0;
477
	//sprintf(debuf, "create %U",res);
478
	//rtlDebugOutString(debuf);
479
	fileInfo.OffsetLow += fileInfo.dataCount;
480
481
	// ширину столбцов сохраняем
482
 
483
	for (i = 1; i < col_count; i++)
484
	{
485
		char smalbuf[32];
486
		memset((Byte*)smalbuf,0,32);
487
		sprintf(smalbuf, "%U,", col_width[i]);
488
		strcpy(buffer+strlen(buffer),smalbuf);
489
	}
490
	buffer[strlen(buffer)-1] = '\n';	// заменили последнюю запятую на перевод строки
491
	//rtlDebugOutString(buffer);
492
	fileInfo.dataCount = strlen(buffer);
493
	fileInfo.bufferPtr = (Byte*)buffer;
494
	fileInfo.rwMode = 3;
495
	res = kos_FileSystemAccess(&fileInfo);
496
	if (res != 0)
497
		return 0;
498
499
	// перемотать забыл я этот файл
500
 
501
	fileInfo.OffsetLow += fileInfo.dataCount;
502
503
	// высоту строк сохраняем в файле мы
504
 
505
	for (i = 1; i < row_count; i++)
506
	{
507
		char smalbuf[32];
508
		memset((Byte*)smalbuf,0,32);
509
		sprintf(smalbuf, "%U,", row_height[i]);
510
		strcpy(buffer+strlen(buffer),smalbuf);
511
	}
512
	buffer[strlen(buffer)-1] = '\n';	// заменили последнюю запятую на перевод строки
513
	//rtlDebugOutString(buffer);
514
	fileInfo.dataCount = strlen(buffer);
515
	fileInfo.bufferPtr = (Byte*)buffer;
516
	fileInfo.rwMode = 3;
517
	res = kos_FileSystemAccess(&fileInfo);
518
	if (res != 0)
519
		return 0;
520
521
	// и вновь перемотаю я сей файл
522
 
523
	fileInfo.OffsetLow += fileInfo.dataCount;
524
 
525
526
	// сохранили параметры ячеек мы, сохраняем содержимое их теперь
527
 
528
	for (i = 1; i < row_count; i++)
529
 
530
		for (j = 1; j < col_count; j++)
531
			if (cells[j][i])
532
			{
533
				memset((Byte*)buffer,0,512);
534
				sprintf(buffer, "%U %U:%S\n", j, i, cells[j][i]);
535
				fileInfo.dataCount = strlen(buffer);
536
				fileInfo.bufferPtr = (Byte*)buffer;
537
				fileInfo.rwMode = 3;
538
				res = kos_FileSystemAccess(&fileInfo);
539
				if (res != 0)
540
					return 0;
541
				//sprintf(debuf, "create %U",res);
542
				//rtlDebugOutString(debuf);
543
				fileInfo.OffsetLow += fileInfo.dataCount;
544
			}
545
	}
546
547
	//rtlDebugOutString("saving finished");
548
 
549
	freemem(buffer);
550
 
551
}
552
553
char *Kos_FileRead(kosFileInfo &fileInfo, int &code)
554
 
555
	char buffer[512], *p, *r;
556
	fileInfo.dataCount = 512;
557
	fileInfo.rwMode = 0;
558
	fileInfo.bufferPtr = (Byte *)buffer;
559
	memset((Byte*)buffer, 0, 512);
560
	int z = kos_FileSystemAccess(&fileInfo);
561
	code = z;
562
563
	//sprintf(debuf, "kos file read %U", code);
564
 
565
566
	if (z != 0 && z != 6)
567
 
568
569
	p = buffer;
570
 
571
572
	if (p == buffer)
573
 
574
575
	r = (char*)allocmem(p - buffer);
576
 
577
	//strncpy(r, buffer, p - buffer);
578
	for (int l = 0; l < p - buffer - 1; l++)
579
		r[l] = buffer[l];
580
	fileInfo.OffsetLow += p - buffer;
581
	return r;
582
}
583
584
int LoadCSV(char *fname)
585
 
586
	// clear the table
587
	reinit();
588
589
	kosFileInfo fileInfo;
590
 
591
	fileInfo.OffsetLow = 0;
592
	fileInfo.OffsetHigh = 0;
593
594
	char *line;
595
 
596
	int col = 1, row = 1;
597
 
598
	do
599
	{
600
		line = Kos_FileRead(fileInfo, code);
601
		if (!line || *line == '\0' || (code != 0 && code != 6))
602
		{
603
			sprintf(debuf, "read end, line not null = %U, code = %U", !line, code);
604
			rtlDebugOutString(debuf);
605
			break;
606
		}
607
		sprintf(debuf, "read '%S' len %U", line, strlen(line));
608
		rtlDebugOutString(debuf);
609
610
		// разборать строку
611
 
612
		int i = 0;
613
		while (i <= strlen(line))
614
		{
615
			int inPar = 0;
616
			// inPar: 0 - не кавычки, 1 - только что была кавычка, 2 - кавычка была, но давно
617
			int start = i;
618
			while (i <= strlen(line))
619
			{
620
				char c = line[i];
621
				if (!c)
622
					c = ';';
623
				int yes_semicolon = 0;
624
625
				switch (inPar)
626
 
627
					case 0:
628
						if (c == '\"')
629
						{
630
							inPar = 1;
631
						}
632
						else
633
						{
634
							if (c == ';')
635
								yes_semicolon = 1;
636
						}
637
						break;
638
					case 1:
639
						inPar = 2;
640
						break;
641
					case 2:
642
						if (c == '\"')	// она закрылась
643
						{
644
							inPar = 0;
645
						}
646
						/*else
647
						{
648
							if (c == ';')
649
								yes_semicolon = 1;
650
651
						}*/
652
 
653
				}
654
				if (yes_semicolon)
655
				{
656
					// итак, line[i] = ';'
657
					int tmp = line[start] == '"' ? 1 : 0;
658
					int sz = i - start - tmp * 2;
659
					if (sz > 0)
660
					{
661
						cells[col][row] = (char *)allocmem(sz + 1);
662
						memset((Byte*)cells[col][row], 0, sz + 1);
663
						int m = 0;
664
						for (int l = 0; l < sz; l++)
665
						{
666
							if (line[start + tmp + l] == '\"')
667
							{
668
								cells[col][row][m++] = '\"';
669
								l++;	// пропустить следующую кавычку
670
							}
671
							else
672
								cells[col][row][m++] = line[start + tmp + l];
673
						}
674
						sprintf(debuf, "set %U %U = '%S'", col, row, cells[col][row]);
675
						rtlDebugOutString(debuf);
676
					}
677
					start = i + 1;
678
					col++;
679
				}
680
				i++;
681
			}
682
			row++;
683
			col = 1;
684
			i++;
685
		}
686
687
	} while(line);
688
 
689
	return 1;
690
 
691
692
693
 
694
 
695
	kosFileInfo fileInfo;
696
	kosBDVK bdvk;
697
	int filePointer = 0, i, j;
698
	Dword res, filesize;
699
	char buffer[512 + 1];
700
	char *d, *s, *k;
701
	int step = 0, items;
702
703
	if (str_is_csv(fname))
704
 
705
706
707
 
708
 
709
	strcpy(fileInfo.fileURL,fname);
710
 
711
	fileInfo.OffsetHigh = 0;
712
713
	fileInfo.rwMode = 5;
714
 
715
	Dword rr = kos_FileSystemAccess(&fileInfo); // в CKosFile нет определения размера
716
	//sprintf(debuf, "getsize: %U\n", rr);
717
	//rtlDebugOutString(debuf);
718
	if (rr != 0)
719
	{
720
		return -1;
721
	}
722
723
	// clear the table
724
 
725
726
	//rtlDebugOutString("clear done");
727
 
728
	filesize = bdvk.size_low;
729
 
730
	fileInfo.rwMode = 0;
731
 
732
	fileInfo.bufferPtr = (Byte*)buffer;
733
	kos_FileSystemAccess(&fileInfo);
734
	s = (char*)sFileSign;
735
	d = buffer;
736
	while (*s && *d && *s++==*d++);		// застрелите меня
737
	if (*s != '\0' || *d != '\0')
738
	{
739
		return -2;
740
	}
741
	fileInfo.OffsetLow += fileInfo.dataCount;
742
	items = 1;
743
	while (fileInfo.OffsetLow < filesize)
744
	{
745
		// так прочитали ли мы ширину всех стоблцов, и длину всех строк прочитали ли мы?
746
		fileInfo.dataCount = 512;
747
		memset((Byte*)buffer, 0, 512);
748
		kos_FileSystemAccess(&fileInfo);
749
		//sprintf(debuf, "%U", fileInfo.OffsetLow);
750
		//rtlDebugOutString(debuf);
751
		//sprintf(debuf, "buffer: %S", buffer);
752
		//rtlDebugOutString(debuf);
753
		// что я увижу на доске отладки
754
		// то мне поможет в жизненном пути
755
		// смогу тогда своей ошибки гадкой
756
		// причину непосредственно найти
757
758
		switch (step)
759
 
760
		case 0:			// стоблцы
761
			d = buffer;
762
			while (*d && *d != ',' && *d != '\n') d++;
763
			//d--;
764
			if (!*d)
765
			{
766
				return -2;
767
			}
768
			*d = '\0';
769
			i = atoi(buffer);
770
			col_width[items++] = i;
771
			if (items == col_count)
772
			{
773
				step++;
774
				items = 1;	//	теперь высоты строк читать мы будем смело
775
							//  чтоб их восстановить и было как всегда
776
				//sprintf(debuf, "cols read done last buf %S file pos %U",buffer,fileInfo.OffsetLow);
777
				//rtlDebugOutString(debuf);
778
			}
779
			d+=2;
780
			break;
781
782
		case 1:			// строки, коих высота записана
783
 
784
			while (*d && *d != ',' && *d != '\n') d++;
785
			//d--;
786
			if (!*d)
787
			{
788
				//sprintf(debuf,"oh shit, error at %U",items);
789
				//rtlDebugOutString(debuf);
790
				return -2;
791
			}
792
			*d = '\0';
793
			i = atoi(buffer);
794
			row_height[items++] = i;
795
			/*if (items > 5)
796
			{
797
				sprintf(debuf, "set row from %S hei %U %U",buffer,items-1,i);
798
				rtlDebugOutString(debuf);
799
			}*/
800
801
			if (items == row_count)
802
 
803
				step++;		// а далее лежат ячейки в файле
804
							// записаны они в кривом формате
805
							// ибо писал сей код я темной ночью
806
							// но не курил травы, клянусь я вам
807
							// иначе бы и этого не скодил
808
809
							// дебажить сей мне код премного впадлу
810
 
811
							// немедленно - а то нах все забудешь.
812
							// вот выпью - а там сразу за отладку.
813
				//sprintf(debuf, "before read cells offset %U %X",fileInfo.OffsetLow,fileInfo.OffsetLow);
814
				//rtlDebugOutString(debuf);
815
			}
816
			d+=2;
817
			break;
818
819
			// о, бряки я забыл забить. о ужас.
820
 
821
			// ведь тот, кто break не ставит после casa
822
			// подобен ламеру, что си не знает
823
			// смогу ли я такое пережить?
824
825
		case 2:			// ячейки, ибо их содержимое сохранено здесь от исчезновения
826
 
827
			while (*d && *d++ != ' ');	// оужжас. зачем только я писал этот бред....
828
			d--;
829
			if (!*d)
830
			{
831
				return -2;
832
			}
833
			*d = '\0';
834
			i = atoi(buffer);
835
			d++;
836
			s=d;
837
			while (*d && *d++ != ':');	// когда-то я удивлялся, как люди могут такую херню писать... дожил
838
			d--;
839
			if (!*d)
840
			{
841
				return -2;
842
			}
843
			*d = '\0';
844
			j = atoi(s);
845
			//rtlDebugOutString(s);
846
			d++;
847
			k = d;
848
			while (*d && *d++ != '\n');
849
			d--;
850
			*d = '\0';
851
			d+=2;
852
			//sprintf(debuf, "i:%U j:%U d:%S\n",i,j,k);
853
			//rtlDebugOutString(debuf);
854
			cells[i][j] = (char*)allocmem(strlen(k) + 1);
855
			//memset(cells[i][j], 0, strlen(k) + 1);
856
			strcpy(cells[i][j], k);
857
			//sprintf(debuf, "offset: %U", fileInfo.OffsetLow);
858
			//rtlDebugOutString(debuf);
859
		}
860
		fileInfo.OffsetLow += d - (char*)buffer - 1;
861
	}
862
	//rtlDebugOutString("loading finished");
863
	return 1;
864
}
865
866
// очистить буфер обмена
867
 
868
{
869
	int i, j;
870
871
	if (!buffer)
872
 
873
	for (i = 0; i < buf_col; i++)
874
	{
875
		for (j = 0; j < buf_row; j++)
876
			if (buffer[i][j])
877
				freemem(buffer[i][j]);
878
		freemem(buffer[i]);
879
	}
880
	freemem(buffer);
881
	buffer = NULL;
882
	buf_row = buf_col = 0;
883
884
}
885
 
886
887
 
888
 
889
int abort_calc = 0;
890
 
891
892
// ппц, где то баг, а это типа фикс
893
 
894
895
double calc_callback(char *str)
896
 
897
	int i,j,x,y;
898
899
	if (abort_calc == 1)
900
 
901
902
	//rtlDebugOutString(str);
903
 
904
	for (i = 0; i < strlen(str); i++)
905
		if (str[i] >= '0' && str[i] <= '9')
906
			break;
907
	if (str[i-1] == '$')
908
		i--;
909
	if (i == strlen(str))
910
	{
911
		abort_calc = 1;
912
		serror(ERR_BADVARIABLE);
913
		return 0.0;
914
	}
915
	x = -1;
916
	for (j = 0; j < col_count; j++)
917
//		if (strnicmp(str,cells[j][0],i-1)==0)
918
		if (str[0] == cells[j][0][0] && ((i == 1) || (str[1] == cells[j][0][1])))
919
		{
920
			x = j;
921
			break;
922
		}
923
	if (str[i] == '$')
924
		i++;
925
	y = -1;
926
	for (j = 0; j < row_count; j++)
927
		if (strcmp(str+i,cells[0][j])==0)
928
		{
929
			y = j;
930
			break;
931
		}
932
	if (x == -1 || y == -1)
933
	{
934
		abort_calc = 1;
935
		serror(ERR_BADVARIABLE);
936
		return 0.0;
937
	}
938
939
	double hold;
940
 
941
		if (values[x][y][0] == '#')
942
		{
943
			serror(ERR_BADVARIABLE);
944
			abort_calc = 1;
945
		}
946
		else
947
		{
948
			hold = atof(values[x][y]);
949
			//if (convert_error)				// нереальный случай...
950
			//{
951
			//	serror(ERR_BADVARIABLE);
952
			//	abort_calc = 1;
953
			//}
954
		}
955
	else
956
	{
957
		if (cells[x][y])
958
		{
959
			hold = atof(cells[x][y]);
960
			if (convert_error == ERROR || convert_error == ERROR_END)
961
			{
962
				serror(ERR_BADVARIABLE);
963
				abort_calc = 1;
964
			}
965
		}
966
		else
967
		{
968
			sprintf(debuf, "bad var %S", str);
969
			rtlDebugOutString(debuf);
970
			serror(ERR_BADVARIABLE);
971
			abort_calc = 1;
972
		}
973
	}
974
	return hold;
975
}
976
977
double depend_callback(char *str)
978
 
979
	cell_list *cur;
980
	// надо выдрать из АВ47 значения х и у.
981
	int i,j,x,y;
982
983
	if (abort_calc == 1)
984
 
985
986
	if (*str == '$') str++;
987
 
988
		if (str[i] >= '0' && str[i] <= '9')
989
			break;
990
	if (str[i-1] == '$')
991
		i--;
992
	if (i == strlen(str))
993
	{
994
		abort_calc = 1;
995
		serror(ERR_BADVARIABLE);
996
		return 0.0;
997
	}
998
	x = -1;
999
	for (j = 1; j < col_count; j++)
1000
		//if (strncmp(str,cells[j][0],i)==0)
1001
		if (str[0] == cells[j][0][0] && ((i == 1) || (str[1] == cells[j][0][1])))
1002
		{
1003
			x = j;
1004
			break;
1005
		}
1006
	if (str[i] == '$')
1007
		i++;
1008
1009
	y = -1;
1010
 
1011
		if (strcmp(str+i,cells[0][j])==0)
1012
		{
1013
			y = j;
1014
			break;
1015
		}
1016
	if (x == -1 || y == -1)
1017
	{
1018
		abort_calc = 1;
1019
		serror(ERR_BADVARIABLE);
1020
		return 0.0;
1021
	}
1022
	cur = (cell_list*)allocmem(sizeof(cell_list));
1023
	cur->x = x;
1024
	cur->y = y;
1025
	cur->next = last_dep;
1026
	last_dep = cur;
1027
1028
	return 0.0;
1029
 
1030
1031
cell_list *find_depend(char *str)
1032
 
1033
	double hold;
1034
	last_dep = NULL;
1035
	find_var = &depend_callback;
1036
	set_exp(str);
1037
	get_exp(&hold);
1038
1039
	return last_dep;
1040
 
1041
1042
bool is_in_list(cell_list *c1, cell_list *c2)
1043
 
1044
	cell_list *p = c2;
1045
	while (p)
1046
	{
1047
		if (c1->x == p->x && c1->y == p->y)
1048
			return 1;
1049
		p = p->next;
1050
	}
1051
	return 0;
1052
}
1053
1054
void calculate_values()
1055
 
1056
	cell_list ***depend = NULL;
1057
	cell_list *first = NULL;
1058
	cell_list *sorted = NULL, *sorted_last = NULL;
1059
	cell_list *p = NULL;
1060
	int i,j;
1061
1062
	//rtlDebugOutString("calc");
1063
 
1064
	abort_calc = 0;
1065
 
1066
	for (i = 0; i < col_count; i++)
1067
	{
1068
		depend[i] = (cell_list**)allocmem(row_count * sizeof(void*));
1069
		for (j = 0; j < row_count; j++)
1070
		{
1071
			if (values[i][j])
1072
				freemem(values[i][j]);
1073
			values[i][j] = NULL;
1074
1075
			if (cells[i][j] && cells[i][j][0] == '=')
1076
 
1077
				depend[i][j] = find_depend(cells[i][j] + 1);		// после =
1078
				if (abort_calc)
1079
				{
1080
					values[i][j] = (char*)allocmem(2);
1081
					values[i][j][0] = '#';
1082
					values[i][j][1] = '\0';
1083
					abort_calc = 0;
1084
					continue;
1085
				}
1086
				cell_list *cur;
1087
				cur = (cell_list*)allocmem(sizeof(cell_list));
1088
				cur->x = i;
1089
				cur->y = j;
1090
				cur->next = first;	// вставили тек. ячейку в начало списка ячеек с формулами
1091
				first = cur;
1092
			}
1093
		}
1094
	}
1095
1096
	//rtlDebugOutString("depend end");
1097
 
1098
	if (!first)
1099
		goto free_memory;
1100
1101
	if (abort_calc)
1102
 
1103
1104
	while (first)
1105
 
1106
		// найти наименьший элемент. если его нет - ошибка, т.к. циклическая зависимость
1107
		cell_list *prev = NULL,*min = first;
1108
1109
		bool is_min;
1110
 
1111
		{
1112
			cell_list *p = first;
1113
			is_min = 1;
1114
			while (p && is_min)
1115
			{
1116
				if (is_in_list(p,depend[min->x][min->y]))
1117
					is_min = 0;
1118
				p = p->next;
1119
			}
1120
			if (is_min)
1121
				break;
1122
			prev = min;
1123
			min = min->next;
1124
		}
1125
		if (!is_min)
1126
		{
1127
			abort_calc = 1;
1128
			goto free_memory;		// все плохо. ужасно. я плакаю, но пишу goto
1129
		}
1130
		// надо убрать минимум во второй список
1131
		if (prev == NULL)
1132
		{
1133
			first = first->next;
1134
		}
1135
		else
1136
		{
1137
			prev->next = min->next;
1138
		}
1139
		/*
1140
		min->next = sorted;
1141
		sorted = min;
1142
		*/
1143
		if (sorted == NULL)
1144
		{
1145
			sorted = min;
1146
			sorted_last = min;
1147
		}
1148
		else
1149
		{
1150
			sorted_last->next = min;
1151
			sorted_last = min;
1152
			min->next = NULL;
1153
		}
1154
	}
1155
1156
	// вычисление значений
1157
 
1158
1159
	p = sorted;
1160
 
1161
	{
1162
		double d;
1163
		abort_calc = 0;
1164
		set_exp(cells[p->x][p->y]+1);	// все что после "="
1165
		find_var = &calc_callback;
1166
		if (get_exp(&d))
1167
		{
1168
			char *new_val = ftoa(d);
1169
			if (values[p->x][p->y] && strcmp(values[p->x][p->y],new_val) == 0)
1170
			{
1171
				freemem(new_val);
1172
			}
1173
			else
1174
			{
1175
				if (values[p->x][p->y])
1176
					freemem(values[p->x][p->y]);
1177
				values[p->x][p->y] = new_val;
1178
				sel_moved = 0;
1179
			}
1180
			//sprintf(debuf,"calc %U %U formula %S result %f",p->x,p->y,cells[p->x][p->y]+1,d);
1181
			//rtlDebugOutString(debuf);
1182
		}
1183
		else
1184
		{
1185
			values[p->x][p->y] = (char*)allocmem(2);
1186
			values[p->x][p->y][0] = '#';
1187
			values[p->x][p->y][1] = '\0';
1188
			//sprintf(debuf,"calc %U %U formula %S result #",p->x,p->y,cells[p->x][p->y]+1);
1189
			//rtlDebugOutString(debuf);
1190
		}
1191
		p = p->next;
1192
	}
1193
1194
	if (abort_calc)
1195
 
1196
1197
	//rtlDebugOutString("calc end");
1198
 
1199
1200
 
1201
 
1202
free_memory:
1203
 
1204
	p = sorted;
1205
 
1206
	{
1207
		cell_list *tmp = p->next;
1208
		cell_list *pp = depend[p->x][p->y];
1209
		while (pp)
1210
		{
1211
			cell_list *tmp = pp->next;
1212
			freemem(pp);
1213
			pp = tmp;
1214
		}
1215
		freemem(p);
1216
		p = tmp;
1217
	}
1218
1219
	for (i = 0; i < col_count; i++)
1220
 
1221
	freemem(depend);
1222
1223
	//rtlDebugOutString("freemem end");
1224
 
1225
1226
 
1227
 
1228
int parse_cell_name(char *str, int *px, int *py, int *xd, int *yd)
1229
 
1230
	// надо выдрать из АВ47 значения х и у.
1231
	int i,j,x,y,dx = 0,dy = 0;
1232
1233
	if (*str == '$')
1234
 
1235
		str++;
1236
		dx = 1;
1237
	}
1238
	for (i = 0; i < strlen(str); i++)
1239
		if (str[i] >= '0' && str[i] <= '9')
1240
			break;
1241
	if (str[i-1] == '$')
1242
	{
1243
		i--;
1244
		dy = 1;
1245
	}
1246
	if (i == strlen(str))
1247
	{
1248
		return 0;
1249
	}
1250
	x = -1;
1251
	for (j = 1; j < col_count; j++)
1252
		if (strncmp(str,cells[j][0],i)==0)
1253
	{
1254
		/*int p = 0, z = 1;
1255
		for (p = 0; p < i; p++)
1256
			if (!str[p] || str[p] != cells[j][0][p])
1257
			{
1258
				z = 0;
1259
				break;
1260
			}
1261
		if (z)
1262
		*/
1263
		{
1264
			x = j;
1265
			break;
1266
		}
1267
	}
1268
	if (str[i] == '$')
1269
		i++;
1270
	y = -1;
1271
	for (j = 1; j < row_count; j++)
1272
		if (strcmp(str+i,cells[0][j])==0)
1273
	{
1274
			/*
1275
		int p = 0, z = 1;
1276
		for (p = 0;; p++)
1277
		{
1278
			if (str[i + p] != cells[0][j][p])
1279
			{
1280
				z = 0;
1281
				break;
1282
			}
1283
			if (cells[0][j][p] == '\0')
1284
				break;
1285
		}
1286
		if (z)
1287
		*/
1288
		{
1289
			y = j;
1290
			break;
1291
		}
1292
	}
1293
	if (x == -1 || y == -1)
1294
	{
1295
		return 0;
1296
	}
1297
	*px = x;
1298
	*py = y;
1299
	if (xd)
1300
		*xd = dx;
1301
	if (yd)
1302
		*yd = dy;
1303
	return 1;
1304
}
1305
1306
char *make_cell_name(int x, int y, int xd, int yd)
1307
 
1308
	char *col_cap = make_col_cap(x);
1309
	char *row_cap = make_row_cap(y);
1310
1311
	if (x <= 0 || x > col_count || y <= 0 || y > row_count)
1312
 
1313
1314
	char *res = (char*)allocmem(strlen(col_cap) + strlen(row_cap) + xd ? 1 : 0 + yd ? 1 : 0 + 1);
1315
 
1316
	if (xd)
1317
	{
1318
		res[i] = '$';
1319
		i++;
1320
	}
1321
	strcpy(res + i, col_cap);
1322
	i += strlen(col_cap);
1323
	if (yd)
1324
	{
1325
		res[i] = '$';
1326
		i++;
1327
	}
1328
	strcpy(res + i, row_cap);
1329
	i += strlen(row_cap);
1330
	res[i] = '\0';
1331
	freemem(col_cap);
1332
	freemem(row_cap);
1333
	return res;
1334
}
1335
1336
// замены ссылки на одну ячейку
1337
 
1338
{
1339
	int x0, y0, xd, yd;
1340
1341
	parse_cell_name(name, &x0, &y0, &xd, &yd);
1342
 
1343
	//sprintf(debuf, "parsed cell name %S to %U %U", name, x0, y0);
1344
 
1345
1346
	// у нас есть х0 и у0.
1347
 
1348
	//rtlDebugOutString(debuf);
1349
	if (x0 >= cf_x0 && x0 <= cf_x1 && y0 >= cf_y0 && y0 <= cf_y1)
1350
	{
1351
		if (!xd)
1352
		{
1353
			x0 += sx;
1354
			if (x0 <= 0 || x0 > col_count)
1355
				x0 -= sx;
1356
		}
1357
		if (!yd)
1358
		{
1359
			y0 += sy;
1360
			if (y0 <= 0 || y0 > row_count)
1361
				y0 -= sy;
1362
		}
1363
	}
1364
1365
	return make_cell_name(x0, y0, xd, yd);
1366
 
1367
1368
// замена всех ссылок на ячейки
1369
 
1370
{
1371
	int i = 0;
1372
	int in_name = 0;	// 1 - читаем буквенную часть. 2 - читаем цифровую. 0 - читаем разделители и т.д.
1373
	int alp_len = 0, dig_len = 0;
1374
	int buf_i = 0;
1375
1376
	char buffer[256]; // очень плохо
1377
 
1378
1379
	//sprintf(debuf, "change formula %S by %U %U", name, sx, sy);
1380
 
1381
1382
	while (i < strlen(name) + 1)
1383
 
1384
		char c;
1385
		if (i == strlen(name))
1386
			c = ' ';
1387
		else
1388
			c = name[i];
1389
		buffer[buf_i++] = c;
1390
1391
		switch (in_name)
1392
 
1393
			case 0:
1394
			{
1395
				if (isalpha2(c) || c == '$')
1396
				{
1397
					in_name = 1;
1398
					alp_len = 1;
1399
					dig_len = 0;
1400
				}
1401
			}
1402
			break;
1403
			case 1:
1404
			{
1405
				if (isalpha2(c))
1406
				{
1407
					alp_len++;
1408
				}
1409
				else if (c == '$' || isdigit(c))
1410
				{
1411
					in_name = 2;
1412
					dig_len++;
1413
				}
1414
				else
1415
				{
1416
					// незавершенное имя ячейки - не имя
1417
					in_name = 0;
1418
					alp_len = dig_len = 0;
1419
				}
1420
			}
1421
			break;
1422
			case 2:
1423
			{
1424
				if (isdigit(c))
1425
				{
1426
					dig_len++;
1427
				}
1428
				else
1429
				{
1430
					if (alp_len > 0 && dig_len > 0)
1431
					{
1432
						// вот нормальная ячейка
1433
						int idx = i - alp_len - dig_len;
1434
						int len = alp_len + dig_len;
1435
						char *cell = (char*)allocmem(len + 1);
1436
						//strncpy(cell, name + i, alp_len + dig_len);
1437
						for (int l = 0; l < len; l++)
1438
							cell[l] = name[idx + l];
1439
						cell[len] = '\0';
1440
1441
						//sprintf(debuf, "found cell name '%S' alp %U dig %U", cell, alp_len, dig_len);
1442
 
1443
						char *cell_new = change_cell_ref(cell, sx, sy);
1444
						//sprintf(debuf, "rename to '%S'", cell_new);
1445
						//rtlDebugOutString(debuf);
1446
						if (cell_new)
1447
						{
1448
							char cc = buffer[buf_i - 1];
1449
							strcpy(buffer + buf_i - len - 1, cell_new);
1450
							buf_i += strlen(cell_new) - len;
1451
							buffer[buf_i - 1] = cc;
1452
						}
1453
						//freemem(cell);
1454
						//freemem(cell_new);
1455
						alp_len = dig_len = 0;
1456
						in_name = 0;
1457
					}
1458
				}
1459
			}
1460
		}
1461
		i++;
1462
	}
1463
	//sprintf(debuf, "change formula done");
1464
	//rtlDebugOutString(debuf);
1465
	char *res = (char*)allocmem(strlen(buffer) + 1);
1466
	strcpy(res, buffer);
1467
	return res;
1468
}
1469