Subversion Repositories Kolibri OS

Rev

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