Subversion Repositories Kolibri OS

Rev

Rev 7504 | Rev 7517 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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