Subversion Repositories Kolibri OS

Rev

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