Subversion Repositories Kolibri OS

Rev

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