Subversion Repositories Kolibri OS

Rev

Rev 7503 | Rev 7516 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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