Subversion Repositories Kolibri OS

Rev

Rev 7516 | 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
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
int Kos_FileWrite(kosFileInfo &fileInfo, char *line, int mode = 3) // если mode = 2 - перезаписать файл
355
 
356
	int res = 0;
357
	fileInfo.dataCount = strlen(line);
358
	fileInfo.bufferPtr = (Byte*)line;
359
	fileInfo.rwMode = mode;
360
	res = kos_FileSystemAccess(&fileInfo);
361
	if (res != 0)
362
		return 0;
363
	fileInfo.OffsetLow += fileInfo.dataCount;
364
	return 1;
365
}
366
367
int SaveCSV(char *fname)
368
 
369
	int i, j;
370
	int min_col = col_count, min_row = row_count, max_row = -1, max_col = -1;
371
	int first = 1;
372
373
	kosFileInfo fileInfo;
374
 
375
	strcpy(fileInfo.fileURL,fname);
376
	fileInfo.OffsetLow = 0;
377
	fileInfo.OffsetHigh = 0;
378
	fileInfo.rwMode = 8;	// delete
379
380
	rtlDebugOutString("savecsv: old file deleted");
381
 
382
	for (i = 1; i < col_count; i++)
383
 
384
		for (j = 1; j < row_count; j++)
385
		{
386
			if (cells[i][j])
387
			{
388
				min_col = min(min_col, i);
389
				min_row = min(min_row, j);
390
				max_col = max(max_col, i);
391
				max_row = max(max_row, j);
392
			}
393
		}
394
	}
395
396
	sprintf(debuf, "col %U %U row", min_col, max_col, min_row, max_row);
397
 
398
399
	for (j = min_row; j <= max_row; j++)
400
 
401
		char buffer[1024]; // не надо так делать
402
		int buf_len = 0;
403
404
		memset((Byte*)buffer, 0, 1024);
405
 
406
		for (i = min_col; i <= max_col; i++)
407
 
408
			char *cur = values[i][j] ? values[i][j] : cells[i][j];
409
			if (cur)
410
			{
411
				buffer[buf_len++] = '\"';
412
				for (int k = 0; k < strlen(cur); k++)
413
				{
414
					if (cur[k] == '\"')
415
						buffer[buf_len++] = '\"';	// кавычек - по две
416
					buffer[buf_len++] = cur[k];
417
				}
418
				buffer[buf_len++] = '\"';
419
			}
420
			buffer[buf_len++] = ',';
421
		}
7517 leency 422
		rtlDebugOutString(buffer);
990 barsuk 423
		// очередная строка теперь в буфере
424
		buffer[buf_len++] = '\n';
425
		if (!Kos_FileWrite(fileInfo, buffer, first ? (first = 0, 2) : 3))
426
			return 0;
427
	}
428
	return 1;
429
}
430
7517 leency 431
int str_is_csv(char *str)
990 barsuk 432
 
7517 leency 433
	int str_len = strlen(str);
434
	if (str_len >= 5) {
435
		if ( strnicmp(str + str_len - 4, ".CSV", 4) == 0) return 1;
436
	}
437
	return 0;
438
}
439
990 barsuk 440
#define BUF_FOR_ALL 5000
441
 
442
{
443
	kosFileInfo fileInfo;
444
	char *buffer = (char*)allocmem(BUF_FOR_ALL);	// ужас! но пока что достаточно
445
	int filePointer = 0;
446
447
	int i,j;
448
 
449
450
	if (str_is_csv(fname))
451
 
452
453
454
 
455
 
456
	memset((Byte*)&fileInfo, 0, sizeof(fileInfo));
457
 
458
	fileInfo.OffsetLow = 0;
459
	fileInfo.OffsetHigh = 0;
460
	fileInfo.rwMode = 8;
461
	res = kos_FileSystemAccess(&fileInfo);	// удалить
462
	fileInfo.dataCount = strlen(sFileSign);
463
	fileInfo.bufferPtr = (Byte*)sFileSign;
464
	fileInfo.rwMode = 2;
465
	res = kos_FileSystemAccess(&fileInfo);
466
	if (res != 0)
467
		return 0;
468
	//sprintf(debuf, "create %U",res);
469
	//rtlDebugOutString(debuf);
470
	fileInfo.OffsetLow += fileInfo.dataCount;
471
472
	// ширину столбцов сохраняем
473
 
474
	for (i = 1; i < col_count; i++)
475
	{
476
		char smalbuf[32];
477
		memset((Byte*)smalbuf,0,32);
478
		sprintf(smalbuf, "%U,", cell_w[i]);
479
		strcpy(buffer+strlen(buffer),smalbuf);
7503 leency 480
	}
990 barsuk 481
	buffer[strlen(buffer)-1] = '\n';	// заменили последнюю запятую на перевод строки
482
	//rtlDebugOutString(buffer);
483
	fileInfo.dataCount = strlen(buffer);
484
	fileInfo.bufferPtr = (Byte*)buffer;
485
	fileInfo.rwMode = 3;
486
	res = kos_FileSystemAccess(&fileInfo);
487
	if (res != 0)
488
		return 0;
489
490
	// перемотать забыл я этот файл
491
 
492
	fileInfo.OffsetLow += fileInfo.dataCount;
493
494
	// высоту строк сохраняем в файле мы
495
 
496
	for (i = 1; i < row_count; i++)
497
	{
498
		char smalbuf[32];
499
		memset((Byte*)smalbuf,0,32);
500
		sprintf(smalbuf, "%U,", cell_h[i]);
501
		strcpy(buffer+strlen(buffer),smalbuf);
7503 leency 502
	}
990 barsuk 503
	buffer[strlen(buffer)-1] = '\n';	// заменили последнюю запятую на перевод строки
504
	//rtlDebugOutString(buffer);
505
	fileInfo.dataCount = strlen(buffer);
506
	fileInfo.bufferPtr = (Byte*)buffer;
507
	fileInfo.rwMode = 3;
508
	res = kos_FileSystemAccess(&fileInfo);
509
	if (res != 0)
510
		return 0;
511
512
	// и вновь перемотаю я сей файл
513
 
514
	fileInfo.OffsetLow += fileInfo.dataCount;
515
 
516
517
	// сохранили параметры ячеек мы, сохраняем содержимое их теперь
518
 
519
	for (i = 1; i < row_count; i++)
520
 
521
		for (j = 1; j < col_count; j++)
522
			if (cells[j][i])
523
			{
524
				memset((Byte*)buffer,0,512);
525
				sprintf(buffer, "%U %U:%S\n", j, i, cells[j][i]);
526
				fileInfo.dataCount = strlen(buffer);
527
				fileInfo.bufferPtr = (Byte*)buffer;
528
				fileInfo.rwMode = 3;
529
				res = kos_FileSystemAccess(&fileInfo);
530
				if (res != 0)
531
					return 0;
532
				//sprintf(debuf, "create %U",res);
533
				//rtlDebugOutString(debuf);
534
				fileInfo.OffsetLow += fileInfo.dataCount;
535
			}
536
	}
537
538
	//rtlDebugOutString("saving finished");
539
 
540
	freemem(buffer);
541
 
542
}
543
544
char *Kos_FileRead(kosFileInfo &fileInfo, int &code)
545
 
546
	char buffer[512], *p, *r;
547
	fileInfo.dataCount = 512;
548
	fileInfo.rwMode = 0;
549
	fileInfo.bufferPtr = (Byte *)buffer;
550
	memset((Byte*)buffer, 0, 512);
551
	int z = kos_FileSystemAccess(&fileInfo);
552
	code = z;
553
554
	//sprintf(debuf, "kos file read %U", code);
555
 
556
557
	if (z != 0 && z != 6)
558
 
559
560
	p = buffer;
561
 
562
563
	if (p == buffer)
564
 
565
566
	r = (char*)allocmem(p - buffer);
567
 
568
	//strncpy(r, buffer, p - buffer);
569
	for (int l = 0; l < p - buffer - 1; l++)
570
		r[l] = buffer[l];
571
	fileInfo.OffsetLow += p - buffer;
572
	return r;
573
}
574
575
char GetCsvSeparator(char *fname)
576
 
7516 leency 577
	char buffer[512];
578
	kosFileInfo fileInfo;
579
580
	rtlDebugOutString("hi");
581
 
582
583
	strcpy(fileInfo.fileURL, fname);
584
 
585
	fileInfo.OffsetHigh = 0;
586
	fileInfo.dataCount = 512;
587
	fileInfo.rwMode = 0;
588
	fileInfo.bufferPtr = (Byte *)buffer;
589
590
	if (kos_FileSystemAccess(&fileInfo) == 0) {
591
 
592
		int separ_semicolon = chrnum(buffer, ';');
593
		//kos_DebugValue(",", separ_coma);
594
		//kos_DebugValue(";", separ_semicolon);
595
		if (separ_semicolon>separ_coma) return ';';
596
	}
597
	return ',';
598
}
599
600
int LoadCSV(char *fname)
601
 
990 barsuk 602
	// clear the table
603
	reinit();
604
605
	kosFileInfo fileInfo;
606
 
607
	fileInfo.OffsetLow = 0;
608
	fileInfo.OffsetHigh = 0;
609
610
	char separator = GetCsvSeparator(fileInfo.fileURL);
611
 
7516 leency 612
	char *line;
613
 
990 barsuk 614
	int col = 1, row = 1;
615
 
616
	do
617
	{
618
		line = Kos_FileRead(fileInfo, code);
619
		if (!line || *line == '\0' || (code != 0 && code != 6))
620
		{
621
			sprintf(debuf, "read end, line not null = %U, code = %U", !line, code);
622
			rtlDebugOutString(debuf);
623
			break;
624
		}
625
		sprintf(debuf, "read '%S' len %U", line, strlen(line));
626
		rtlDebugOutString(debuf);
627
628
		// разборать строку
629
 
630
		int i = 0;
631
		while (i <= strlen(line))
632
		{
633
			int inPar = 0;
634
			// inPar: 0 - не кавычки, 1 - только что была кавычка, 2 - кавычка была, но давно
635
			int start = i;
636
			while (i <= strlen(line))
637
			{
638
				char c = line[i];
639
				if (!c)
640
					c = separator;
641
				int yes_semicolon = 0;
7516 leency 642
990 barsuk 643
				switch (inPar)
644
 
645
					case 0:
646
						if (c == '\"')
647
						{
648
							inPar = 1;
649
						}
650
						else
651
						{
652
							if (c == separator)
653
								yes_semicolon = 1;
7516 leency 654
						}
990 barsuk 655
						break;
656
					case 1:
657
						inPar = 2;
658
						break;
659
					case 2:
660
						if (c == '\"')	// она закрылась
661
						{
662
							inPar = 0;
663
						}
664
						/*else
665
						{
666
							if (c == separator)
667
								yes_semicolon = 1;
7516 leency 668
990 barsuk 669
						}*/
670
 
671
				}
672
				if (yes_semicolon)
673
				{
674
					// итак, line[i] = separator
675
					int tmp = line[start] == '"' ? 1 : 0;
7516 leency 676
					int sz = i - start - tmp * 2;
990 barsuk 677
					if (sz > 0)
678
					{
679
						cells[col][row] = (char *)allocmem(sz + 1);
680
						memset((Byte*)cells[col][row], 0, sz + 1);
681
						int m = 0;
682
						for (int l = 0; l < sz; l++)
683
						{
684
							if (line[start + tmp + l] == '\"')
685
							{
686
								cells[col][row][m++] = '\"';
687
								l++;	// пропустить следующую кавычку
688
							}
689
							else
690
								cells[col][row][m++] = line[start + tmp + l];
691
						}
692
						sprintf(debuf, "set %U %U = '%S'", col, row, cells[col][row]);
693
						rtlDebugOutString(debuf);
694
					}
695
					start = i + 1;
696
					col++;
697
				}
698
				i++;
699
			}
700
			row++;
701
			col = 1;
702
			i++;
703
		}
704
705
	} while(line);
706
 
707
	return 1;
708
 
709
710
711
 
712
 
713
	kosFileInfo fileInfo;
714
	kosBDVK bdvk;
715
	int filePointer = 0, i, j;
716
	Dword res, filesize;
717
	char buffer[512 + 1];
718
	char *d, *s, *k;
719
	int step = 0, items;
720
721
	if (str_is_csv(fname))
722
 
723
724
725
 
726
 
727
	strcpy(fileInfo.fileURL,fname);
728
 
729
	fileInfo.OffsetHigh = 0;
730
731
	fileInfo.rwMode = 5;
732
 
733
	Dword rr = kos_FileSystemAccess(&fileInfo); // в CKosFile нет определения размера
734
	//sprintf(debuf, "getsize: %U\n", rr);
735
	//rtlDebugOutString(debuf);
736
	if (rr != 0)
737
	{
738
		return -1;
739
	}
740
741
	// clear the table
742
 
743
744
	//rtlDebugOutString("clear done");
745
 
746
	filesize = bdvk.size_low;
747
 
748
	fileInfo.rwMode = 0;
749
 
750
	fileInfo.bufferPtr = (Byte*)buffer;
751
	kos_FileSystemAccess(&fileInfo);
752
	s = (char*)sFileSign;
753
	d = buffer;
754
	while (*s && *d && *s++==*d++);		// застрелите меня
755
	if (*s != '\0' || *d != '\0')
756
	{
757
		return -2;
758
	}
759
	fileInfo.OffsetLow += fileInfo.dataCount;
760
	items = 1;
761
	while (fileInfo.OffsetLow < filesize)
762
	{
763
		// так прочитали ли мы ширину всех стоблцов, и длину всех строк прочитали ли мы?
764
		fileInfo.dataCount = 512;
765
		memset((Byte*)buffer, 0, 512);
766
		kos_FileSystemAccess(&fileInfo);
767
		//sprintf(debuf, "%U", fileInfo.OffsetLow);
768
		//rtlDebugOutString(debuf);
769
		//sprintf(debuf, "buffer: %S", buffer);
770
		//rtlDebugOutString(debuf);
771
		// что я увижу на доске отладки
772
		// то мне поможет в жизненном пути
773
		// смогу тогда своей ошибки гадкой
774
		// причину непосредственно найти
775
776
		switch (step)
777
 
778
		case 0:			// стоблцы
779
			d = buffer;
780
			while (*d && *d != ',' && *d != '\n') d++;
781
			//d--;
782
			if (!*d)
783
			{
784
				return -2;
785
			}
786
			*d = '\0';
787
			i = atoi(buffer);
788
			cell_w[items++] = i;
789
			if (items == col_count)
7503 leency 790
			{
990 barsuk 791
				step++;
792
				items = 1;	//	теперь высоты строк читать мы будем смело
793
							//  чтоб их восстановить и было как всегда
794
				//sprintf(debuf, "col_count read done last buf %S file pos %U",buffer,fileInfo.OffsetLow);
795
				//rtlDebugOutString(debuf);
7503 leency 796
			}
990 barsuk 797
			d+=2;
798
			break;
799
800
		case 1:			// строки, коих высота записана
801
 
802
			while (*d && *d != ',' && *d != '\n') d++;
803
			//d--;
804
			if (!*d)
805
			{
806
				//sprintf(debuf,"oh shit, error at %U",items);
807
				//rtlDebugOutString(debuf);
808
				return -2;
809
			}
810
			*d = '\0';
811
			i = atoi(buffer);
812
			cell_h[items++] = i;
813
			/*if (items > 5)
7503 leency 814
			{
990 barsuk 815
				sprintf(debuf, "set row from %S hei %U %U",buffer,items-1,i);
816
				rtlDebugOutString(debuf);
817
			}*/
818
819
			if (items == row_count)
820
 
821
				step++;		// а далее лежат ячейки в файле
822
							// записаны они в кривом формате
823
							// ибо писал сей код я темной ночью
824
							// но не курил травы, клянусь я вам
825
							// иначе бы и этого не скодил
826
827
							// дебажить сей мне код премного впадлу
828
 
829
							// немедленно - а то нах все забудешь.
830
							// вот выпью - а там сразу за отладку.
831
				//sprintf(debuf, "before read cells offset %U %X",fileInfo.OffsetLow,fileInfo.OffsetLow);
832
				//rtlDebugOutString(debuf);
833
			}
834
			d+=2;
835
			break;
836
837
			// о, бряки я забыл забить. о ужас.
838
 
839
			// ведь тот, кто break не ставит после casa
840
			// подобен ламеру, что си не знает
841
			// смогу ли я такое пережить?
842
843
		case 2:			// ячейки, ибо их содержимое сохранено здесь от исчезновения
844
 
845
			while (*d && *d++ != ' ');	// оужжас. зачем только я писал этот бред....
846
			d--;
847
			if (!*d)
848
			{
849
				return -2;
850
			}
851
			*d = '\0';
852
			i = atoi(buffer);
853
			d++;
854
			s=d;
855
			while (*d && *d++ != ':');	// когда-то я удивлялся, как люди могут такую херню писать... дожил
856
			d--;
857
			if (!*d)
858
			{
859
				return -2;
860
			}
861
			*d = '\0';
862
			j = atoi(s);
863
			//rtlDebugOutString(s);
864
			d++;
865
			k = d;
866
			while (*d && *d++ != '\n');
867
			d--;
868
			*d = '\0';
869
			d+=2;
870
			//sprintf(debuf, "i:%U j:%U d:%S\n",i,j,k);
871
			//rtlDebugOutString(debuf);
872
			cells[i][j] = (char*)allocmem(strlen(k) + 1);
873
			//memset(cells[i][j], 0, strlen(k) + 1);
874
			strcpy(cells[i][j], k);
875
			//sprintf(debuf, "offset: %U", fileInfo.OffsetLow);
876
			//rtlDebugOutString(debuf);
877
		}
878
		fileInfo.OffsetLow += d - (char*)buffer - 1;
879
	}
880
	//rtlDebugOutString("loading finished");
881
	return 1;
882
}
883
884
// очистить буфер обмена
885
 
886
{
887
	int i, j;
888
889
	if (!buffer)
890
 
891
	for (i = 0; i < buf_col; i++)
892
	{
893
		for (j = 0; j < buf_row; j++)
894
			if (buffer[i][j])
895
				freemem(buffer[i][j]);
896
		freemem(buffer[i]);
897
	}
898
	freemem(buffer);
899
	buffer = NULL;
900
	buf_row = buf_col = 0;
901
902
}
903
 
904
905
 
906
 
907
int abort_calc = 0;
908
 
909
910
// ппц, где то баг, а это типа фикс
911
 
912
913
double calc_callback(char *str)
914
 
915
	int i,j,x,y;
916
917
	if (abort_calc == 1)
918
 
919
920
	//rtlDebugOutString(str);
921
 
922
	for (i = 0; i < strlen(str); i++)
923
		if (str[i] >= '0' && str[i] <= '9')
924
			break;
925
	if (str[i-1] == '$')
926
		i--;
927
	if (i == strlen(str))
928
	{
929
		abort_calc = 1;
930
		serror(ERR_BADVARIABLE);
931
		return 0.0;
932
	}
933
	x = -1;
934
	for (j = 0; j < col_count; j++)
935
//		if (strnicmp(str,cells[j][0],i-1)==0)
936
		if (str[0] == cells[j][0][0] && ((i == 1) || (str[1] == cells[j][0][1])))
937
		{
938
			x = j;
939
			break;
940
		}
941
	if (str[i] == '$')
942
		i++;
943
	y = -1;
944
	for (j = 0; j < row_count; j++)
945
		if (strcmp(str+i,cells[0][j])==0)
946
		{
947
			y = j;
948
			break;
949
		}
950
	if (x == -1 || y == -1)
951
	{
952
		abort_calc = 1;
953
		serror(ERR_BADVARIABLE);
954
		return 0.0;
955
	}
956
957
	double hold;
958
 
959
		if (values[x][y][0] == '#')
960
		{
961
			serror(ERR_BADVARIABLE);
962
			abort_calc = 1;
963
		}
964
		else
965
		{
966
			hold = atof(values[x][y]);
967
			//if (convert_error)				// нереальный случай...
968
			//{
969
			//	serror(ERR_BADVARIABLE);
970
			//	abort_calc = 1;
971
			//}
972
		}
973
	else
974
	{
975
		if (cells[x][y])
976
		{
977
			hold = atof(cells[x][y]);
978
			if (convert_error == ERROR || convert_error == ERROR_END)
979
			{
980
				serror(ERR_BADVARIABLE);
981
				abort_calc = 1;
982
			}
983
		}
984
		else
985
		{
986
			sprintf(debuf, "bad var %S", str);
987
			rtlDebugOutString(debuf);
988
			serror(ERR_BADVARIABLE);
989
			abort_calc = 1;
990
		}
991
	}
992
	return hold;
993
}
994
995
double depend_callback(char *str)
996
 
997
	cell_list *cur;
998
	// надо выдрать из АВ47 значения х и у.
999
	int i,j,x,y;
1000
1001
	if (abort_calc == 1)
1002
 
1003
1004
	if (*str == '$') str++;
1005
 
1006
		if (str[i] >= '0' && str[i] <= '9')
1007
			break;
1008
	if (str[i-1] == '$')
1009
		i--;
1010
	if (i == strlen(str))
1011
	{
1012
		abort_calc = 1;
1013
		serror(ERR_BADVARIABLE);
1014
		return 0.0;
1015
	}
1016
	x = -1;
1017
	for (j = 1; j < col_count; j++)
1018
		//if (strncmp(str,cells[j][0],i)==0)
1019
		if (str[0] == cells[j][0][0] && ((i == 1) || (str[1] == cells[j][0][1])))
1020
		{
1021
			x = j;
1022
			break;
1023
		}
1024
	if (str[i] == '$')
1025
		i++;
1026
1027
	y = -1;
1028
 
1029
		if (strcmp(str+i,cells[0][j])==0)
1030
		{
1031
			y = j;
1032
			break;
1033
		}
1034
	if (x == -1 || y == -1)
1035
	{
1036
		abort_calc = 1;
1037
		serror(ERR_BADVARIABLE);
1038
		return 0.0;
1039
	}
1040
	cur = (cell_list*)allocmem(sizeof(cell_list));
1041
	cur->x = x;
1042
	cur->y = y;
1043
	cur->next = last_dep;
1044
	last_dep = cur;
1045
1046
	return 0.0;
1047
 
1048
1049
cell_list *find_depend(char *str)
1050
 
1051
	double hold;
1052
	last_dep = NULL;
1053
	find_var = &depend_callback;
1054
	set_exp(str);
1055
	get_exp(&hold);
1056
1057
	return last_dep;
1058
 
1059
1060
bool is_in_list(cell_list *c1, cell_list *c2)
1061
 
1062
	cell_list *p = c2;
1063
	while (p)
1064
	{
1065
		if (c1->x == p->x && c1->y == p->y)
1066
			return 1;
1067
		p = p->next;
1068
	}
1069
	return 0;
1070
}
1071
1072
void calculate_values()
1073
 
1074
	cell_list ***depend = NULL;
1075
	cell_list *first = NULL;
1076
	cell_list *sorted = NULL, *sorted_last = NULL;
1077
	cell_list *p = NULL;
1078
	int i,j;
1079
1080
	//rtlDebugOutString("calc");
1081
 
1082
	abort_calc = 0;
1083
 
1084
	for (i = 0; i < col_count; i++)
1085
	{
1086
		depend[i] = (cell_list**)allocmem(row_count * sizeof(void*));
1087
		for (j = 0; j < row_count; j++)
1088
		{
1089
			if (values[i][j])
1090
				freemem(values[i][j]);
1091
			values[i][j] = NULL;
1092
1093
			if (cells[i][j] && cells[i][j][0] == '=')
1094
 
1095
				depend[i][j] = find_depend(cells[i][j] + 1);		// после =
1096
				if (abort_calc)
1097
				{
1098
					values[i][j] = (char*)allocmem(2);
1099
					values[i][j][0] = '#';
1100
					values[i][j][1] = '\0';
1101
					abort_calc = 0;
1102
					continue;
1103
				}
1104
				cell_list *cur;
1105
				cur = (cell_list*)allocmem(sizeof(cell_list));
1106
				cur->x = i;
1107
				cur->y = j;
1108
				cur->next = first;	// вставили тек. ячейку в начало списка ячеек с формулами
1109
				first = cur;
1110
			}
1111
		}
1112
	}
1113
1114
	//rtlDebugOutString("depend end");
1115
 
1116
	if (!first)
1117
		goto free_memory;
1118
1119
	if (abort_calc)
1120
 
1121
1122
	while (first)
1123
 
1124
		// найти наименьший элемент. если его нет - ошибка, т.к. циклическая зависимость
1125
		cell_list *prev = NULL,*min = first;
1126
1127
		bool is_min;
1128
 
1129
		{
1130
			cell_list *p = first;
1131
			is_min = 1;
1132
			while (p && is_min)
1133
			{
1134
				if (is_in_list(p,depend[min->x][min->y]))
1135
					is_min = 0;
1136
				p = p->next;
1137
			}
1138
			if (is_min)
1139
				break;
1140
			prev = min;
1141
			min = min->next;
1142
		}
1143
		if (!is_min)
1144
		{
1145
			abort_calc = 1;
1146
			goto free_memory;		// все плохо. ужасно. я плакаю, но пишу goto
1147
		}
1148
		// надо убрать минимум во второй список
1149
		if (prev == NULL)
1150
		{
1151
			first = first->next;
1152
		}
1153
		else
1154
		{
1155
			prev->next = min->next;
1156
		}
1157
		/*
1158
		min->next = sorted;
1159
		sorted = min;
1160
		*/
1161
		if (sorted == NULL)
1162
		{
1163
			sorted = min;
1164
			sorted_last = min;
1165
		}
1166
		else
1167
		{
1168
			sorted_last->next = min;
1169
			sorted_last = min;
1170
			min->next = NULL;
1171
		}
1172
	}
1173
1174
	// вычисление значений
1175
 
1176
1177
	p = sorted;
1178
 
1179
	{
1180
		double d;
1181
		abort_calc = 0;
1182
		set_exp(cells[p->x][p->y]+1);	// все что после "="
1183
		find_var = &calc_callback;
1184
		if (get_exp(&d))
1185
		{
1186
			char *new_val = ftoa(d);
1187
			if (values[p->x][p->y] && strcmp(values[p->x][p->y],new_val) == 0)
1188
			{
1189
				freemem(new_val);
1190
			}
1191
			else
1192
			{
1193
				if (values[p->x][p->y])
1194
					freemem(values[p->x][p->y]);
1195
				values[p->x][p->y] = new_val;
1196
				sel_moved = 0;
1197
			}
1198
			//sprintf(debuf,"calc %U %U formula %S result %f",p->x,p->y,cells[p->x][p->y]+1,d);
1199
			//rtlDebugOutString(debuf);
1200
		}
1201
		else
1202
		{
1203
			values[p->x][p->y] = (char*)allocmem(2);
1204
			values[p->x][p->y][0] = '#';
1205
			values[p->x][p->y][1] = '\0';
1206
			//sprintf(debuf,"calc %U %U formula %S result #",p->x,p->y,cells[p->x][p->y]+1);
1207
			//rtlDebugOutString(debuf);
1208
		}
1209
		p = p->next;
1210
	}
1211
1212
	if (abort_calc)
1213
 
1214
1215
	//rtlDebugOutString("calc end");
1216
 
1217
1218
 
1219
 
1220
free_memory:
1221
 
1222
	p = sorted;
1223
 
1224
	{
1225
		cell_list *tmp = p->next;
1226
		cell_list *pp = depend[p->x][p->y];
1227
		while (pp)
1228
		{
1229
			cell_list *tmp = pp->next;
1230
			freemem(pp);
1231
			pp = tmp;
1232
		}
1233
		freemem(p);
1234
		p = tmp;
1235
	}
1236
1237
	for (i = 0; i < col_count; i++)
1238
 
1239
	freemem(depend);
1240
1241
	//rtlDebugOutString("freemem end");
1242
 
1243
1244
 
1245
 
1246
int parse_cell_name(char *str, int *px, int *py, int *xd, int *yd)
1247
 
1248
	// надо выдрать из АВ47 значения х и у.
1249
	int i,j,x,y,dx = 0,dy = 0;
1250
1251
	if (*str == '$')
1252
 
1253
		str++;
1254
		dx = 1;
1255
	}
1256
	for (i = 0; i < strlen(str); i++)
1257
		if (str[i] >= '0' && str[i] <= '9')
1258
			break;
1259
	if (str[i-1] == '$')
1260
	{
1261
		i--;
1262
		dy = 1;
1263
	}
1264
	if (i == strlen(str))
1265
	{
1266
		return 0;
1267
	}
1268
	x = -1;
1269
	for (j = 1; j < col_count; j++)
1270
		if (strncmp(str,cells[j][0],i)==0)
1271
	{
1272
		/*int p = 0, z = 1;
1273
		for (p = 0; p < i; p++)
1274
			if (!str[p] || str[p] != cells[j][0][p])
1275
			{
1276
				z = 0;
1277
				break;
1278
			}
1279
		if (z)
1280
		*/
1281
		{
1282
			x = j;
1283
			break;
1284
		}
1285
	}
1286
	if (str[i] == '$')
1287
		i++;
1288
	y = -1;
1289
	for (j = 1; j < row_count; j++)
1290
		if (strcmp(str+i,cells[0][j])==0)
1291
	{
1292
			/*
1293
		int p = 0, z = 1;
1294
		for (p = 0;; p++)
1295
		{
1296
			if (str[i + p] != cells[0][j][p])
1297
			{
1298
				z = 0;
1299
				break;
1300
			}
1301
			if (cells[0][j][p] == '\0')
1302
				break;
1303
		}
1304
		if (z)
1305
		*/
1306
		{
1307
			y = j;
1308
			break;
1309
		}
1310
	}
1311
	if (x == -1 || y == -1)
1312
	{
1313
		return 0;
1314
	}
1315
	*px = x;
1316
	*py = y;
1317
	if (xd)
1318
		*xd = dx;
1319
	if (yd)
1320
		*yd = dy;
1321
	return 1;
1322
}
1323
1324
char *make_cell_name(int x, int y, int xd, int yd)
1325
 
1326
	char *col_cap = make_col_cap(x);
1327
	char *row_cap = make_row_cap(y);
1328
1329
	if (x <= 0 || x > col_count || y <= 0 || y > row_count)
1330
 
1331
1332
	char *res = (char*)allocmem(strlen(col_cap) + strlen(row_cap) + xd ? 1 : 0 + yd ? 1 : 0 + 1);
1333
 
1334
	if (xd)
1335
	{
1336
		res[i] = '$';
1337
		i++;
1338
	}
1339
	strcpy(res + i, col_cap);
1340
	i += strlen(col_cap);
1341
	if (yd)
1342
	{
1343
		res[i] = '$';
1344
		i++;
1345
	}
1346
	strcpy(res + i, row_cap);
1347
	i += strlen(row_cap);
1348
	res[i] = '\0';
1349
	freemem(col_cap);
1350
	freemem(row_cap);
1351
	return res;
1352
}
1353
1354
// замены ссылки на одну ячейку
1355
 
1356
{
1357
	int x0, y0, xd, yd;
1358
1359
	parse_cell_name(name, &x0, &y0, &xd, &yd);
1360
 
1361
	//sprintf(debuf, "parsed cell name %S to %U %U", name, x0, y0);
1362
 
1363
1364
	// у нас есть х0 и у0.
1365
 
1366
	//rtlDebugOutString(debuf);
1367
	if (x0 >= cf_x0 && x0 <= cf_x1 && y0 >= cf_y0 && y0 <= cf_y1)
1368
	{
1369
		if (!xd)
1370
		{
1371
			x0 += sx;
1372
			if (x0 <= 0 || x0 > col_count)
1373
				x0 -= sx;
1374
		}
1375
		if (!yd)
1376
		{
1377
			y0 += sy;
1378
			if (y0 <= 0 || y0 > row_count)
1379
				y0 -= sy;
1380
		}
1381
	}
1382
1383
	return make_cell_name(x0, y0, xd, yd);
1384
 
1385
1386
// замена всех ссылок на ячейки
1387
 
1388
{
1389
	int i = 0;
1390
	int in_name = 0;	// 1 - читаем буквенную часть. 2 - читаем цифровую. 0 - читаем разделители и т.д.
1391
	int alp_len = 0, dig_len = 0;
1392
	int buf_i = 0;
1393
1394
	char buffer[256]; // очень плохо
1395
 
1396
1397
	//sprintf(debuf, "change formula %S by %U %U", name, sx, sy);
1398
 
1399
1400
	while (i < strlen(name) + 1)
1401
 
1402
		char c;
1403
		if (i == strlen(name))
1404
			c = ' ';
1405
		else
1406
			c = name[i];
1407
		buffer[buf_i++] = c;
1408
1409
		switch (in_name)
1410
 
1411
			case 0:
1412
			{
1413
				if (isalpha2(c) || c == '$')
1414
				{
1415
					in_name = 1;
1416
					alp_len = 1;
1417
					dig_len = 0;
1418
				}
1419
			}
1420
			break;
1421
			case 1:
1422
			{
1423
				if (isalpha2(c))
1424
				{
1425
					alp_len++;
1426
				}
1427
				else if (c == '$' || isdigit(c))
1428
				{
1429
					in_name = 2;
1430
					dig_len++;
1431
				}
1432
				else
1433
				{
1434
					// незавершенное имя ячейки - не имя
1435
					in_name = 0;
1436
					alp_len = dig_len = 0;
1437
				}
1438
			}
1439
			break;
1440
			case 2:
1441
			{
1442
				if (isdigit(c))
1443
				{
1444
					dig_len++;
1445
				}
1446
				else
1447
				{
1448
					if (alp_len > 0 && dig_len > 0)
1449
					{
1450
						// вот нормальная ячейка
1451
						int idx = i - alp_len - dig_len;
1452
						int len = alp_len + dig_len;
1453
						char *cell = (char*)allocmem(len + 1);
1454
						//strncpy(cell, name + i, alp_len + dig_len);
1455
						for (int l = 0; l < len; l++)
1456
							cell[l] = name[idx + l];
1457
						cell[len] = '\0';
1458
1459
						//sprintf(debuf, "found cell name '%S' alp %U dig %U", cell, alp_len, dig_len);
1460
 
1461
						char *cell_new = change_cell_ref(cell, sx, sy);
1462
						//sprintf(debuf, "rename to '%S'", cell_new);
1463
						//rtlDebugOutString(debuf);
1464
						if (cell_new)
1465
						{
1466
							char cc = buffer[buf_i - 1];
1467
							strcpy(buffer + buf_i - len - 1, cell_new);
1468
							buf_i += strlen(cell_new) - len;
1469
							buffer[buf_i - 1] = cc;
1470
						}
1471
						//freemem(cell);
1472
						//freemem(cell_new);
1473
						alp_len = dig_len = 0;
1474
						in_name = 0;
1475
					}
1476
				}
1477
			}
1478
		}
1479
		i++;
1480
	}
1481
	//sprintf(debuf, "change formula done");
1482
	//rtlDebugOutString(debuf);
1483
	char *res = (char*)allocmem(strlen(buffer) + 1);
1484
	strcpy(res, buffer);
1485
	return res;
1486
}
1487