Subversion Repositories Kolibri OS

Rev

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