Subversion Repositories Kolibri OS

Rev

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