Subversion Repositories Kolibri OS

Rev

Rev 7897 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. //если выделить область ячеек и сдвинуть курсор ввода с помощью клавиш, "следы" остануться
  2. //нельзя перемещаться по буквам в редактируемой строке
  3.  
  4. #include "func.h"
  5. #include "parser.h"
  6. #include "calc.h"
  7. #include "use_library.h"
  8.  
  9. #ifdef AUTOBUILD
  10. extern char params[1024];
  11. #endif
  12. char params[1024];
  13.  
  14. #define TABLE_VERSION "0.99.3"
  15.  
  16. // strings
  17. const char *sFileSign = "KolibriTable File\n";
  18. const char sFilename[] = "Filename:";
  19. const char sSave[] = "Save";
  20. const char sLoad[] = "Load";
  21. const char sNew[] = "New";
  22.  
  23. const char er_file_not_found[] = "'Cannot open file' -E";
  24. const char er_format[] = "'Error: bad format' -E";
  25. const char msg_save[] = "'File saved' -O";
  26. //const char msg_load[] = "'File loaded' -O";
  27. const char msg_save_error[] = "'Error saving file' -E";
  28. const char msg_new[] = "'Memory cleared' -I";
  29.  
  30. // initial window sizes
  31. #define WND_W 718
  32. #define WND_H 514
  33. // new window size and coordinates
  34. int cWidth;
  35. int cHeight;
  36. kosSysColors sc;
  37. // bottom panel
  38. #define MENU_PANEL_HEIGHT 40
  39.  
  40. // interface colors
  41. #define GRID_COLOR 0xa0a0a0
  42. #define TEXT_COLOR 0x000000
  43. #define CELL_COLOR 0xffffff
  44. #define CELL_COLOR_ACTIVE 0xe0e0ff
  45. #define HEADER_CELL_COLOR 0xE9E7E3
  46. #define HEADER_CELL_COLOR_ACTIVE 0xC4C5BA //0xBBBBFF
  47.  
  48. // button IDs
  49. #define SAVE_BUTTON 100
  50. #define LOAD_BUTTON 101
  51. #define NEW_BUTTON  102
  52. #define SELECT_ALL_BUTTON 103
  53.  
  54. #define COL_BUTTON 0x100
  55. #define ROW_BUTTON (COL_BUTTON + 0x100)
  56. #define COL_HEAD_BUTTON (ROW_BUTTON + 0x100)
  57. #define ROW_HEAD_BUTTON (COL_HEAD_BUTTON + 0x100)
  58. #define CELL_BUTTON (ROW_HEAD_BUTTON + 0x100)
  59.  
  60. // editbox data
  61. char edit_text[256];
  62. edit_box cell_box = {0,9*8-6,WND_H - 16-32,0xffffff,0x94AECE,0,
  63.         0x808080,0x10000000,sizeof(edit_text)-1,(dword)&edit_text,0,0};
  64.  
  65. // scrolls
  66. #define SCROLL_SIZE 16
  67. scroll_bar scroll_v = { SCROLL_SIZE,200,398, NULL, SCROLL_SIZE,0,115,
  68.         15,0,0xeeeeee,0xD2CED0,0x555555,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1};
  69. scroll_bar scroll_h = { 200,NULL,SCROLL_SIZE, NULL, SCROLL_SIZE,0,115,
  70.         15,0,0xeeeeee,0xD2CED0,0x555555,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1};
  71.  
  72. // ячейки - их параметры и текст
  73. DWORD col_count = 100, row_count = 100;
  74. DWORD *cell_w, *cell_h;
  75. char ***cells;
  76.  
  77. struct GRID
  78. {
  79.         int x,y,w,h;
  80.         int firstx, firsty; // cell x:y in the top left corner
  81. } grid = {
  82.         0,0,NULL,NULL,
  83.         1,1
  84. };
  85.  
  86. char ***values; // значения формул, если есть
  87.  
  88. bool display_formulas = false;  // отображать ли формулы вместо значений
  89.  
  90. // координаты отображаемых столбцов и строк
  91. DWORD *cell_x, *cell_y;
  92.  
  93. // буфер обмена
  94. char ***buffer = NULL;
  95. DWORD buf_col, buf_row;
  96. DWORD buf_old_x, buf_old_y;
  97.  
  98. // это выделенная ячейка
  99. DWORD sel_x = 1, sel_y = 1;
  100. DWORD prev_x = 0, prev_y = 0;   // предыдущая выделенная
  101. int was_single_selection = 0;
  102.  
  103. // конец выделения если выделено несколько ячеек
  104. DWORD sel_end_x = sel_x, sel_end_y = sel_y;
  105.  
  106. // флаг
  107. bool sel_moved = 0;
  108. bool sel_end_move = 0;
  109. // сколько ячеек помещается в окне по х и у
  110. DWORD nx = 0, ny = 0;
  111.  
  112. // флаг реадктирования ячейки
  113. #define is_edit (cell_box.flags & ed_focus)
  114.  
  115. // редактирование имени файла
  116. bool fn_edit = 0;
  117. char fname[256];
  118. edit_box file_box = {160,9*8+12,WND_H - 16-32,0xffffff,0x94AECE,
  119.         0,0x808080,0x10000000,sizeof(fname)-1,(dword)&fname,0,0};
  120.  
  121. // изменение размеров
  122. #define SIZE_X 1 // состояние
  123. #define SIZE_Y 2
  124. #define SIZE_SELECT 3
  125. #define SIZE_DRAG 4
  126. int size_mouse_x, size_mouse_y, size_id, size_state = 0;
  127.  
  128. // растаскивание ячейки при ее тащении за правый нижний угол, с заполнением ячеек
  129. int drag_x, drag_y;
  130. int old_end_x, old_end_y;
  131.  
  132. void draw_grid();
  133. void EventGridSelectAll();
  134.  
  135. void DrawSelectedFrame(int x, int y, int w, int h, DWORD col)
  136. {
  137.         kos_DrawBar(x,y,w,2,col);          // up
  138.         kos_DrawBar(x,y,2,h,col);          // left
  139.         kos_DrawBar(x,y+h-2,w-2-3,2,col);  // bottom
  140.         kos_DrawBar(x+w-2,y, 2,h-2-3,col); // right
  141.         kos_DrawBar(x+w-4,y+h-4,4,4,col);
  142. }
  143.  
  144. void DrawScrolls()
  145. {
  146.         // HOR
  147.         scroll_h.x = 0;
  148.         scroll_h.y = grid.y + grid.h;
  149.         scroll_h.w = grid.w + SCROLL_SIZE + 1;
  150.         scroll_h.all_redraw = true;
  151.         scroll_h.max_area = col_count - 2;
  152.         scroll_h.cur_area = nx-grid.firstx-1;
  153.         scroll_h.position = grid.firstx-1;
  154.         scrollbar_h_draw((DWORD)&scroll_h);
  155.  
  156.         // VER
  157.         scroll_v.x = grid.x + grid.w;
  158.         scroll_v.y = 0;
  159.         scroll_v.h = grid.h + 1;
  160.         scroll_v.all_redraw = true;
  161.         scroll_v.max_area = row_count - 2;
  162.         scroll_v.cur_area = ny-grid.firsty-1;
  163.         scroll_v.position = grid.firsty-1;
  164.         scrollbar_v_draw((DWORD)&scroll_v);
  165. }
  166.  
  167.  
  168. void start_edit(int x, int y)
  169. {
  170.         int ch = 0;
  171.         if (x < grid.firstx || x > nx - 1)
  172.         {
  173.                 grid.firstx = x;
  174.                 ch = 1;
  175.         }
  176.         if (y < grid.firsty || y > ny - 1)
  177.         {
  178.                 grid.firsty = y;
  179.                 ch = 1;
  180.         }
  181.         if (ch)
  182.         {
  183.                 sel_moved = 1;
  184.                 draw_grid();
  185.         }
  186.  
  187.         file_box.flags &= ~ed_focus;
  188.  
  189.         cell_box.flags = ed_focus;
  190.         cell_box.left = cell_x[x] + 1;
  191.         cell_box.top = cell_y[y];
  192.         cell_box.width = cell_w[x] - 2;
  193.         memset((Byte*)edit_text, 0, sizeof(edit_text));
  194.         if (cells[x][y])
  195.         {
  196.                 strcpy(edit_text, cells[x][y]);
  197.         }
  198.         cell_box.offset = cell_box.shift = cell_box.shift_old = 0;
  199.         cell_box.pos = cell_box.size = strlen(edit_text);
  200.  
  201.         edit_box_draw((DWORD)&cell_box);
  202.         edit_box_draw((DWORD)&file_box);
  203. }
  204.  
  205. void stop_edit()
  206. {
  207.         if (is_edit)
  208.         {
  209.                 cell_box.flags &= ~ed_focus;
  210.                 if (cells[sel_x][sel_y])
  211.                         freemem(cells[sel_x][sel_y]);
  212.                 if (strlen(edit_text) > 0)
  213.                 {
  214.                         cells[sel_x][sel_y] = (char*)allocmem(strlen(edit_text)+1);
  215.                         strcpy(cells[sel_x][sel_y], edit_text);
  216.                 }
  217.                 else
  218.                         cells[sel_x][sel_y] = NULL;
  219.                 //memset((Byte*)edit_text,0, 256);
  220.                 calculate_values();
  221.         }
  222. }
  223.  
  224. void cancel_edit()
  225. {
  226.         if (!is_edit)
  227.                 return;
  228.         cell_box.flags &= ~ed_focus;
  229.         memset((Byte*)edit_text,0, 256);
  230.         draw_grid();
  231. }
  232.  
  233. void check_sel()
  234. {
  235.         DWORD sx0=grid.firstx, sy0=grid.firsty;
  236.  
  237.         if (sel_x >= nx - 1  /*&& sel_x < col_count - nx + grid.firstx + 1*/)
  238.                 //if (sel_x == nx)
  239.                         grid.firstx++;
  240.                 //else
  241.                 //      grid.firstx = sel_x;
  242.         if (sel_y >= ny - 1 /*&& sel_y < row_count - ny + grid.firsty */)
  243.                 //if (sel_y == ny)
  244.                         grid.firsty++;
  245.                 //else
  246.                 //      grid.firsty = sel_y;
  247.  
  248.         if (sel_x < grid.firstx)
  249.                 grid.firstx = sel_x;
  250.         if (sel_y < grid.firsty)
  251.                 grid.firsty = sel_y;
  252.  
  253.         if (sx0 != grid.firstx || sy0 != grid.firsty)
  254.                 sel_moved = 0;                  // надо перерисовать все
  255.  
  256. }
  257.  
  258. void move_selection(DWORD new_x, DWORD new_y)
  259. {
  260.         sel_moved = 1;
  261.         stop_edit();
  262.         prev_x = sel_x;
  263.         prev_y = sel_y;
  264.         sel_x = new_x;
  265.         if (sel_x < 1)
  266.                 sel_x = 1;
  267.         if (sel_x > col_count - 1)
  268.                 sel_x = col_count - 1;
  269.         sel_end_x = sel_x;
  270.         sel_y = new_y;
  271.         if (sel_y < 1)
  272.                 sel_y = 1;
  273.         if (sel_y > row_count - 1)
  274.                 sel_y = row_count - 1;
  275.         sel_end_y = sel_y;
  276.         check_sel();
  277.         draw_grid();
  278. }
  279.  
  280. // x - между low и high ? - необязательно low<high
  281. bool is_between(Dword x, Dword low, Dword high)
  282. {
  283.         return ((low<high)?(x >= low && x <= high):(x >= high && x <= low));
  284. }
  285.  
  286. void clear_cell_slow(int px, int py)
  287. {
  288.         int i;
  289.         int x0 = cell_w[0];
  290.         for (i = grid.firstx; i < px; i++)
  291.         {
  292.                 x0 += cell_w[i];
  293.         }
  294.         int x1 = x0;
  295.         x1 += cell_w[px];
  296.         int y0 = cell_h[0];
  297.         for (i = grid.firsty; i < py; i++)
  298.         {
  299.                 y0 += cell_h[i];
  300.         }
  301.         int y1 = y0;
  302.         y1 += cell_h[py];
  303.         kos_DrawBar(x0 + 1, y0 + 1, x1 - x0 - 1, y1 - y0 - 1, 0xffffff);
  304. }
  305.  
  306.  
  307.  
  308. // рисование ячеек
  309. #define is_x_changed(v) ((v) == sel_x || (v) == prev_x)
  310. #define is_y_changed(v) ((v) == sel_y || (v) == prev_y)
  311.  
  312. void DrawCell(int x, int y, Dword w, Dword h, Dword id, Dword bg_color, char* text, bool header)
  313. {
  314.         bool small = false;
  315.         if (x>grid.x+grid.w || w>grid.w || w<=0) return;
  316.         if (x+w > grid.x + grid.w) {
  317.                 w = grid.x + grid.w - x;
  318.                 small = true;
  319.         }
  320.         if (y+h > grid.y + grid.h) {
  321.                 h = grid.y + grid.h - y;
  322.                 small = true;
  323.         }
  324.         kos_DrawBar(x, y, w, h, bg_color);
  325.         if (!small) {
  326.                 if (id) kos_DefineButton(x+5, y, w-10, h-1, id+BT_NODRAW,0);
  327.                 if (header) kos_WriteTextToWindow( x + w/2 -strlen(text)*4, h/2-7+y, 0x90,TEXT_COLOR,text,0); //WriteTextCenter
  328.                 else kos_DrawCutTextSmall(x+3, h/2-7+y, w-7, TEXT_COLOR, text);
  329.         }
  330. }
  331.  
  332. void draw_grid()
  333. {
  334.         int i,j;
  335.         long x0 = 0, y0 = 0, x = 0, y = 0;
  336.         DWORD bg_color;
  337.         kos_DrawBar(0,0,cell_w[0],cell_h[0],HEADER_CELL_COLOR); // left top cell
  338.         kos_DefineButton(0,0,cell_w[0]-4,cell_h[0]-4, SELECT_ALL_BUTTON + BT_NODRAW, 0);
  339.  
  340.         //kos_DebugValue("sel_moved", sel_moved);
  341.  
  342.         nx=ny=0;
  343.  
  344.         // очистить область около выделенной ячейки
  345.         if (sel_moved)
  346.         {
  347.                 clear_cell_slow(sel_x, sel_y);
  348.                 clear_cell_slow(prev_x, prev_y);
  349.         }
  350.         else
  351.         {
  352.                 // clean all cells
  353.                 //kos_DrawBar(cell_w[0]+1, cell_h[0]+1, grid.w - SCROLL_SIZE-cell_w[0]-1, he - SCROLL_SIZE-cell_h[0]-1, 0xffffff);
  354.         }
  355.  
  356.         // column headers + vertical lines
  357.         cell_x[0] = 0;
  358.         x = cell_w[0];
  359.         nx = 1;
  360.         for (i = 1; i < col_count && x-x0 < grid.w; i++)
  361.         {
  362.                 cell_x[i] = -1;
  363.                 if (i >= grid.firstx)
  364.                 {
  365.                         {                              
  366.                                 //if (!sel_moved || (is_x_changed(i))) {
  367.                                         if (is_between(i,sel_x,sel_end_x)) bg_color = HEADER_CELL_COLOR_ACTIVE; else bg_color = HEADER_CELL_COLOR;
  368.                                         kos_DrawBar(x-x0, 0, 1, grid.h, GRID_COLOR);
  369.                                         DrawCell(x-x0+1, 0, cell_w[i]-1, cell_h[0], i+COL_HEAD_BUTTON, bg_color, cells[i][0], true);
  370.                                 //}
  371.                                 cell_x[i] = x - x0;
  372.                         }
  373.                 }
  374.                 else
  375.                 {
  376.                         x0 += cell_w[i];
  377.                 }
  378.                 x += cell_w[i];
  379.                 nx++;
  380.         }
  381.  
  382.         // row headers + horizontal lines
  383.         y = cell_h[0];
  384.         ny = 1;
  385.         cell_y[0] = 0;
  386.         for (i = 1; i < row_count && y-y0 < grid.h; i++)
  387.         {
  388.                 cell_y[i] = -1;
  389.                 if (i >= grid.firsty)
  390.                 {
  391.                         {
  392.                                 //if (!sel_moved || (is_y_changed(i))) {
  393.                                         if (is_between(i,sel_y,sel_end_y)) bg_color = HEADER_CELL_COLOR_ACTIVE; else bg_color = HEADER_CELL_COLOR;
  394.                                         kos_DrawBar(0, y-y0, grid.w, 1, GRID_COLOR);
  395.                                         DrawCell(0, y-y0+1, cell_w[0], cell_h[i]-1, i+ROW_HEAD_BUTTON, bg_color, cells[0][i], true);
  396.                                 //}
  397.                                 cell_y[i] = y - y0;
  398.                         }
  399.                 }
  400.                 else
  401.                 {
  402.                         y0 += cell_h[i];
  403.                 }
  404.                 y += cell_h[i];
  405.                 ny++;
  406.         }
  407.        
  408.         // cells itself
  409.         y = cell_h[0];
  410.         for (i = grid.firsty; i < ny; i++)
  411.         {
  412.                 x = cell_w[0];
  413.                 for (j = grid.firstx; j < nx; j++)
  414.                 {
  415.                         if (i && j)     //no need to draw headers one more
  416.                         {
  417.                                 bool draw_frame_selection = false;
  418.                                 bool error = false;
  419.                                 bg_color = CELL_COLOR;
  420.  
  421.                                 if (is_between(j,sel_x,sel_end_x) && is_between(i, sel_y, sel_end_y)    // (j,i) - selected
  422.                                 && ((!sel_moved) || (is_x_changed(j) && is_y_changed(i))))                      // and we must draw it
  423.                                 {
  424.                                         if (i == sel_y && j == sel_x)
  425.                                         {
  426.                                                 draw_frame_selection = true;
  427.                                                 drag_x = x + cell_w[j] - 4;
  428.                                                 drag_y = y + cell_h[i] - 4;
  429.                                         }
  430.                                         else {
  431.                                                 bg_color = CELL_COLOR_ACTIVE; // selected but not main
  432.                                         }
  433.                                 }
  434.  
  435.                                 char *text;
  436.                                 if (values[j][i] && values[j][i][0] == '#')
  437.                                 {
  438.                                         text = cells[j][i];
  439.                                         error = true;
  440.                                 }
  441.                                 else {
  442.                                         text = (values[j][i] && !display_formulas ? values[j][i] : cells[j][i]);
  443.                                 }
  444.  
  445.                                 DrawCell(x+1, y+1, cell_w[j]-1, cell_h[i]-1, 0, bg_color, text, false);
  446.                                 if (draw_frame_selection && j<nx-1 && i<ny-1) {
  447.                                         DrawSelectedFrame(x+1,y, cell_w[j]-1, cell_h[i]+1, TEXT_COLOR);
  448.                                 }
  449.                                 else if (error) kos_DrawRegion(x+1, y+1, cell_w[j]-1, cell_h[i]-1, 0xff0000, 0);
  450.                         }
  451.                         x += cell_w[j];
  452.                 }
  453.                 y += cell_h[i];
  454.         }
  455.         DrawScrolls();
  456. }
  457.  
  458. // очень быстрое рисование сетки, в процессе изменения размеров ячеек
  459. void draw_size_grid()
  460. {
  461.         //rtlDebugOutString("draw size grid");
  462.  
  463.         if (size_state == SIZE_X)
  464.         {
  465.                 int x, x0, i;
  466.  
  467.                 x = cell_w[0];
  468.                 x0 = 0;
  469.                 for (i = 1; i < col_count && x - x0 + cell_w[i] < grid.w - 10; i++)
  470.                 {
  471.                         if (i >= grid.firstx)
  472.                         {
  473.                                 if (i >= size_id)
  474.                                         kos_DrawLine(x - x0, 0, x - x0, grid.h, 0, 1);
  475.                         }
  476.                         else
  477.                                 x0 += cell_w[i];
  478.                         x += cell_w[i];
  479.                 }
  480.                 kos_DrawLine(x - x0, 0, x - x0, grid.h, 0, 1);
  481.         }
  482.         else
  483.         {
  484.                 int y, y0, i;
  485.  
  486.                 y = cell_h[0];
  487.                 y0 = 0;
  488.                 for (i = 1; i < col_count && y - y0 + cell_h[i] < grid.h - 10; i++)
  489.                 {
  490.                         if (i >= grid.firsty)
  491.                         {
  492.                                 if (i >= size_id)
  493.                                         kos_DrawLine(0, y - y0, grid.w, y - y0, 0, 1);
  494.                         }
  495.                         else
  496.                                 y0 += cell_h[i];
  497.                         y += cell_h[i];
  498.                 }
  499.                 kos_DrawLine(0, y - y0, grid.w, y - y0, 0, 1);
  500.         }
  501.  
  502. }
  503.  
  504.  
  505. // быстрое рисование выделенной области при выделении мышью
  506. #define DCOLOR 0
  507. //0xff0000
  508. #define DINVERT 1
  509. void draw_drag()
  510. {
  511.         // inverted lines
  512.         int k0 = min(sel_x, sel_end_x);
  513.         int k1 = max(sel_x, sel_end_x);
  514.         int n0 = min(sel_y, sel_end_y);
  515.         int n1 = max(sel_y, sel_end_y);
  516.  
  517.         DWORD x0 = cell_x[k0] - 1;
  518.         DWORD x1 = cell_x[k1] + cell_w[k1] + 1;
  519.         DWORD y0 = cell_y[n0] - 1;     
  520.         DWORD y1 = cell_y[n1] + cell_h[n1] + 1;
  521.         if (x0 > grid.w - 1) x0 = grid.w - 1;
  522.         if (x1 > grid.w - 1) x1 = grid.w - 1;
  523.         if (y0 > grid.h - 1) y0 = grid.h - 1;
  524.         if (y1 > grid.h - 1) y1 = grid.h - 1;
  525.  
  526.         //sprintf(debuf,"drag %U %U %U %U",k0,k1,n0,n1);
  527.         //rtlDebugOutString(debuf);
  528.  
  529.         kos_DrawLine(x0, y0, x0, y1, DCOLOR, DINVERT);
  530.         kos_DrawLine(x0, y0, x1, y0, DCOLOR, DINVERT);
  531.         kos_DrawLine(x1, y0, x1, y1, DCOLOR, DINVERT);
  532.         kos_DrawLine(x0, y1, x1, y1, DCOLOR, DINVERT);
  533. }
  534.  
  535. void draw_window()
  536. {
  537.         kos_WindowRedrawStatus(1);
  538.         kos_DefineAndDrawWindow(110,40,WND_W,WND_H,0x73,0x40FFFFFF,0,0,(Dword)"Table v" TABLE_VERSION);
  539.         kos_WindowRedrawStatus(2);
  540.  
  541.         kos_GetSystemColors(&sc);
  542.  
  543.         sProcessInfo info;
  544.         kos_ProcessInfo(&info, 0xFFFFFFFF);
  545.         cWidth = info.processInfo.width - 9;
  546.         cHeight = info.processInfo.height - kos_GetSkinHeight() - 4;
  547.  
  548.         grid.x = 0;
  549.         grid.y = 0;
  550.         grid.w = cWidth - SCROLL_SIZE - 1;
  551.         grid.h = cHeight - MENU_PANEL_HEIGHT - SCROLL_SIZE;
  552.  
  553.         if (info.processInfo.status_window&0x04) return; //draw nothing if window is rolled-up
  554.  
  555.         if (cWidth  < 430) { kos_ChangeWindow( -1, -1, 450, -1 ); return; }
  556.         if (cHeight < 250) { kos_ChangeWindow( -1, -1, -1, 300 ); return; }
  557.  
  558.         sel_moved = 0;
  559.         if (is_edit) stop_edit();
  560.  
  561.         int panel_y = cHeight - MENU_PANEL_HEIGHT + 1;
  562.         kos_DrawBar(0, panel_y, cWidth, MENU_PANEL_HEIGHT-1, sc.work);
  563.         kos_WriteTextToWindow(3 + 1, panel_y + 14, 0x90, sc.work_text, (char*)sFilename, 0);   
  564.        
  565.         file_box.top = panel_y + 10;
  566.         file_box.width = cWidth - 265;
  567.         int BTX = cWidth - 190;
  568.         #define BTW 70
  569.         //save
  570.         kos_DefineButton(BTX + 25, file_box.top, BTW, 21, SAVE_BUTTON, sc.work);
  571.         kos_WriteTextToWindow(BTX + 25 + (BTW - strlen(sSave) * 8) / 2, panel_y + 14, 0x90, sc.work_text, (char*)sSave, 0);
  572.         //load
  573.         kos_DefineButton(BTX + 25+BTW+5, file_box.top, BTW, 21, LOAD_BUTTON, sc.work);
  574.         kos_WriteTextToWindow(BTX + 25+BTW+5 + (BTW - strlen(sLoad) * 8) / 2, panel_y + 14, 0x90, sc.work_text, (char*)sLoad, 0);
  575.         // // new (clean)
  576.         // kos_DefineButton(90 + 160 + 70, panel_y + 9, 60, 20, NEW_BUTTON, sc.work);
  577.         // kos_WriteTextToWindow(92 + 160 + 10 + 70, panel_y + 16, 0, sc.work_text, (char*)sNew, strlen(sNew));
  578.  
  579.         if (sel_end_move) sel_moved = 0;
  580.         draw_grid();
  581.         sel_moved = 0;
  582.  
  583.         if (is_edit) edit_box_draw((DWORD)&cell_box);
  584.         edit_box_draw((DWORD)&file_box);
  585. }
  586.  
  587. void process_mouse()
  588. {
  589.         Dword mouse_btn, ckeys, shift, ctrl;
  590.  
  591.         int vert, hor;
  592.         kos_GetScrollInfo(vert, hor);  
  593.         if (vert != 0)
  594.         {
  595.                 stop_edit();
  596.                 grid.firsty += vert;
  597.                 if (grid.firsty<1) grid.firsty=1;
  598.                 if (grid.firsty>row_count-25) grid.firsty=row_count-25;
  599.                 draw_grid();
  600.                 return;
  601.         }
  602.  
  603.         if (!size_state) //do not handle scrollbars when user selects cells
  604.         {
  605.                 if (!scroll_h.delta2) scrollbar_v_mouse((DWORD)&scroll_v);
  606.                 if (scroll_v.position != grid.firsty-1)
  607.                 {
  608.                         stop_edit();
  609.                         grid.firsty = scroll_v.position + 1;
  610.                         draw_grid();
  611.                 }
  612.  
  613.                 if (!scroll_v.delta2) scrollbar_h_mouse((DWORD)&scroll_h);
  614.                 if (scroll_h.position != grid.firstx-1)
  615.                 {
  616.                         stop_edit();
  617.                         grid.firstx = scroll_h.position + 1;
  618.                         draw_grid();
  619.                 }
  620.         }
  621.         if (scroll_v.delta2 || scroll_h.delta2) return;
  622.  
  623.         if (is_edit) edit_box_mouse((dword)&cell_box);
  624.         edit_box_mouse((dword)&file_box);
  625.  
  626.         int mouse_x, mouse_y, i;
  627.         kos_GetMouseState(mouse_btn, mouse_x, mouse_y);
  628.         mouse_x -= 5;
  629.         mouse_y -= kos_GetSkinHeight();
  630.  
  631.         if (is_edit && mouse_x>=cell_box.left && mouse_x<=cell_box.left+cell_box.width
  632.                 && mouse_y>=cell_box.top && mouse_y<=cell_box.top+22) return;
  633.  
  634.         mouse_btn &= 0x0001;
  635.  
  636.         if (mouse_btn)
  637.         {
  638.                 if (mouse_y < 0) return; // do nothing if mouse over header
  639.                 if (mouse_y > grid.y + grid.h) return;
  640.         }
  641.  
  642.         ckeys = kos_GetSpecialKeyState();
  643.         shift = ckeys & 0x3;
  644.  
  645.         if (!size_state && !mouse_btn)
  646.                 return;
  647.         if (mouse_btn && !size_state)           // LMB down                            
  648.         {
  649.                 //rtlDebugOutString("lmb down and not resize");
  650.  
  651.                 if (mouse_x >= drag_x && mouse_x <= drag_x + 4 && mouse_y >= drag_y && mouse_y <= drag_y + 4)
  652.                 {
  653.                         size_state = SIZE_DRAG;
  654.                         old_end_x = sel_end_x;
  655.                         old_end_y = sel_end_y;
  656.                 }
  657.                 else if (mouse_y <= cell_h[0])
  658.                 {
  659.                         //rtlDebugOutString("can resize col_count");
  660.                         int kx = -1, i;
  661.                         for (i = 0; i < col_count - 1; i++)
  662.                         if (mouse_x >= cell_x[i] + cell_w[i] - 5 &&
  663.                                 mouse_x <= cell_x[i + 1] + 5)
  664.                         {
  665.                                 kx = i; break;
  666.                         }
  667.                         if (kx != -1)
  668.                         {
  669.                                 //sprintf(debuf,"size x %U",k);
  670.                                 //rtlDebugOutString(debuf);
  671.                                 size_id = kx;
  672.                                 size_state = SIZE_X;
  673.                         }
  674.                 }
  675.                 else if (mouse_x <= cell_w[0])
  676.                 {
  677.                         int ky = -1;
  678.                         for (i = 0; i < row_count - 1; i++)
  679.                         if (mouse_y >= cell_y[i] + cell_h[i] - 5 &&
  680.                                 mouse_y <= cell_y[i + 1] + 5)
  681.                         {
  682.                                 ky = i; break;
  683.                         }
  684.                         if (ky != -1)
  685.                         {
  686.                                 size_id = ky;
  687.                                 size_state = SIZE_Y;
  688.                         }
  689.                 }
  690.                 else   // click on cell
  691.                 if (mouse_x <= cell_x[nx - 1] &&  mouse_y <= cell_y[ny - 1])
  692.                 {
  693.                         was_single_selection = sel_x == sel_end_x && sel_y == sel_end_y;
  694.                         int kx = -1, i;
  695.                         for (i = 0; i < col_count - 1; i++)
  696.                         if (mouse_x >= cell_x[i] &&
  697.                                 mouse_x <= cell_x[i] + cell_w[i])
  698.                         {
  699.                                 kx = i; break;
  700.                         }
  701.                         int ky = -1;
  702.                         for (i = 0; i < row_count - 1; i++)
  703.                         if (mouse_y >= cell_y[i] &&
  704.                                 mouse_y <= cell_y[i] + cell_h[i])
  705.                         {
  706.                                 ky = i; break;
  707.                         }
  708.                         if (kx != -1 && ky != -1)
  709.                         {
  710.                                 if (!shift)
  711.                                 {
  712.                                         move_selection(kx, ky);
  713.                                         //return;
  714.                                 }
  715.                                 else
  716.                                 {
  717.                                         sel_end_x = kx;
  718.                                         sel_end_y = ky;
  719.                                 }
  720.                                 size_state = SIZE_SELECT;
  721.                         }
  722.                 }
  723.                 if (size_state)
  724.                 {
  725.                         size_mouse_x = mouse_x;
  726.                         size_mouse_y = mouse_y;
  727.                 }
  728.                 return;
  729.         }
  730.         else if (!mouse_btn && size_state)
  731.         {
  732.                 sel_moved = 0;          // for a good redraw
  733.                 //rtlDebugOutString("resize end");
  734.  
  735.                 if (size_state == SIZE_DRAG)
  736.                 {
  737.                         fill_cells(sel_x, sel_y, sel_end_x, sel_end_y, old_end_x, old_end_y);
  738.                 }
  739.  
  740.                 //sel_moved = (size_state == SIZE_SELECT && sel_x == sel_end_x && sel_y == sel_end_y && was_single_selection);
  741.                 size_state = 0;
  742.                 draw_grid();            // все сдвинулось - надо обновиться
  743.                 return;
  744.         }
  745.         if (size_state == SIZE_X && mouse_x != size_mouse_x)
  746.         {
  747.                 draw_size_grid();
  748.                 cell_w[size_id] += mouse_x - size_mouse_x;
  749.                 if (cell_w[size_id] < 15)
  750.                         cell_w[size_id] = 15;
  751.                 else if (cell_w[size_id] > grid.w / 2)
  752.                         cell_w[size_id] = grid.w / 2;
  753.                 draw_size_grid();
  754.         }
  755.         if (size_state == SIZE_Y && mouse_y != size_mouse_y)
  756.         {
  757.                 draw_size_grid();
  758.                 cell_h[size_id] += mouse_y - size_mouse_y;
  759.                 if (cell_h[size_id] < 15)
  760.                         cell_h[size_id] = 15;
  761.                 else if (cell_h[size_id] > grid.h / 2)
  762.                         cell_h[size_id] = grid.h / 2;
  763.                 draw_size_grid();
  764.         }
  765.         if ((size_state == SIZE_SELECT || size_state == SIZE_DRAG) && (mouse_x != size_mouse_x || mouse_y != size_mouse_y))
  766.         {
  767.                 draw_drag();
  768.                 int kx = -1, i;
  769.                 for (i = 0; i < col_count - 1; i++)
  770.                         if (mouse_x >= cell_x[i] &&
  771.                                 mouse_x <= cell_x[i + 1])
  772.                         {
  773.                                 //sprintf(debuf, "yyy %U",cell_x[i+1]);
  774.                                 //rtlDebugOutString(debuf);
  775.                                 kx = i; break;
  776.                         }
  777.                 int ky = -1;
  778.                 for (i = 0; i < row_count - 1; i++)
  779.                         if (mouse_y >= cell_y[i] &&
  780.                                 mouse_y <= cell_y[i + 1])
  781.                         {
  782.                                 ky = i; break;
  783.                         }
  784.                 if (kx != -1) sel_end_x = kx;
  785.                 if (ky != -1) sel_end_y = ky;
  786.                 if (size_state == SIZE_DRAG)
  787.                 {
  788.                         if (abs(sel_end_x - sel_x) > 0)
  789.                         {
  790.                                 sel_end_y = old_end_y;
  791.                         }
  792.                         else if (abs(sel_end_y - sel_y) > 0)
  793.                         {
  794.                                 sel_end_x = old_end_x;
  795.                         }
  796.                 }
  797.                 draw_drag();
  798.         }        
  799.         size_mouse_x = mouse_x;
  800.         size_mouse_y = mouse_y;
  801. }
  802.  
  803.  
  804. void shift_selection(int dx, int dy, Dword shift)
  805. {
  806.         if (dx != 0)
  807.         {
  808.                 if (shift)
  809.                 {
  810.                         sel_end_x += dx;
  811.                         if (sel_end_x <= 1)
  812.                                 sel_end_x = 1;
  813.                         else if (sel_end_x >= col_count)
  814.                                 sel_end_x = col_count - 1;
  815.                 //      sprintf(debuf,"sel end x change. sel end %U %U",sel_end_x,sel_end_y);
  816.                 //      rtlDebugOutString(debuf);
  817.                         sel_moved = sel_end_move = 1;
  818.                         //stop_edit();
  819.                         //draw_grid();
  820.                 }
  821.                 else
  822.                 {
  823.                 }
  824.         }
  825.         if (dy != 0)
  826.         {
  827.                 if (shift)
  828.                 {
  829.                         sel_end_y += dy;
  830.                         if (sel_end_y <= 1)
  831.                                 sel_end_y = 1;
  832.                         else if (sel_end_y >= row_count)
  833.                                 sel_end_y = row_count - 1;
  834.                 //      sprintf(debuf,"sel end y change. sel end %U %U",sel_end_x,sel_end_y);
  835.                 //      rtlDebugOutString(debuf);
  836.                         sel_moved = sel_end_move = 1;
  837.                         //stop_edit();
  838.                         //draw_grid();
  839.                 }
  840.         }
  841.         /*
  842.         if (sel_end_x < sel_x)
  843.         {
  844.                 Dword tmp = sel_end_x; sel_end_x = sel_x; sel_x = tmp;
  845.         }
  846.         if (sel_end_y < sel_y)
  847.         {
  848.                 Dword tmp = sel_end_y; sel_end_y = sel_y; sel_y = tmp;
  849.         }
  850.         */
  851.         if ((dx || dy))
  852.         {
  853.                 if (!shift)
  854.                 {
  855.                         if ((sel_end_x + dx) >= (col_count-1)) {dx=0;} //stub
  856.                         else if ((sel_end_y + dy) >= (row_count-1)) {dy=0;}
  857.                         else {
  858.                         move_selection(sel_x + dx, sel_y + dy);
  859.                         }
  860.                 }
  861.                 else
  862.                 {
  863.                         sel_moved = 0;
  864.                         stop_edit();
  865.                         draw_grid();
  866.                 }
  867.         }
  868. }
  869.  
  870.  
  871. void process_key()
  872. {
  873.         Dword ckeys, shift, ctrl;
  874.         dword key_editbox;
  875.         Byte key_ascii, key_scancode;
  876.  
  877.         // key pressed, read it
  878.         ckeys = kos_GetSpecialKeyState();
  879.         shift = ckeys & 0x3;
  880.         ctrl = ckeys & 0x0c;
  881.         sel_moved = 0;
  882.         sel_end_move = 0;
  883.        
  884.         kos_GetKeys(key_editbox, key_ascii, key_scancode);
  885.  
  886.         if (cell_box.flags & ed_focus) {
  887.                 if (SCAN_CODE_ENTER == key_scancode) {
  888.                         stop_edit();
  889.                         draw_grid();
  890.                 }
  891.                 else if (SCAN_CODE_ESC == key_scancode) {
  892.                         cancel_edit();
  893.                 }
  894.                 else {
  895.                         __asm
  896.                         {
  897.                                 mov eax, key_editbox
  898.                         }
  899.                         edit_box_key((dword)&cell_box);                
  900.                 }
  901.         }
  902.         else if (file_box.flags & ed_focus) {
  903.                 __asm
  904.                 {
  905.                         mov eax, key_editbox
  906.                 }
  907.                 edit_box_key((dword)&file_box);
  908.                 return;
  909.         }
  910.         else if (ctrl) {
  911.                 switch (key_scancode)
  912.                 {
  913.                         case SCAN_CODE_KEY_A:
  914.                                 EventGridSelectAll();
  915.                                 break;
  916.                         case SCAN_CODE_KEY_V:
  917.                                 {
  918.                                         int i, j, x0, y0;
  919.                                         x0 = min(sel_x, sel_end_x);
  920.                                         y0 = min(sel_y, sel_end_y);
  921.                                         int delta_x = x0 - buf_old_x;
  922.                                         int delta_y = y0 - buf_old_y;
  923.  
  924.                                         for (i = 0; i < buf_col; i++)
  925.                                                 for (j = 0; j < buf_row; j++)
  926.                                                 {
  927.                                                         if (i + x0 >= col_count || j + y0 >= row_count)
  928.                                                                 continue;
  929.                                                         if (cells[i + x0][j + y0])
  930.                                                                 freemem(cells[i + x0][j + y0]);
  931.                                                         if (buffer[i][j])
  932.                                                         {
  933.                                                                 cf_x0 = buf_old_x; cf_y0 = buf_old_y;
  934.                                                                 cf_x1 = buf_old_x + buf_col;
  935.                                                                 cf_y1 = buf_old_y + buf_row;
  936.                                                                 cells[i + x0][j + y0] = change_formula(buffer[i][j], delta_x, delta_y);
  937.                                                                 //cells[i + x0][j + y0] = (char*)allocmem(strlen(buffer[i][j]));
  938.                                                                 //strcpy(cells[i + x0][j + y0], buffer[i][j]);
  939.                                                         }
  940.                                                         else
  941.                                                                 cells[i + x0][j + y0] = NULL;
  942.                                                 }
  943.  
  944.                                         calculate_values();
  945.                                         draw_grid();
  946.                                         break;
  947.                                 }
  948.                                 case SCAN_CODE_KEY_X:
  949.                                 case SCAN_CODE_KEY_C:
  950.                                 {
  951.                                         int i, j, x0, y0;
  952.  
  953.                                         freeBuffer();
  954.  
  955.                                         buf_col = abs(sel_end_x - sel_x) + 1;
  956.                                         buf_row = abs(sel_end_y - sel_y) + 1;
  957.                                         x0 = min(sel_x, sel_end_x);
  958.                                         y0 = min(sel_y, sel_end_y);
  959.                                         buf_old_x = x0;
  960.                                         buf_old_y = y0;
  961.  
  962.                                         //sprintf(debuf, "%U %U %U %U", buf_col, buf_row, x0, y0);
  963.                                         //rtlDebugOutString(debuf);
  964.                                
  965.                                         buffer = (char***)allocmem(buf_col * sizeof(char**));
  966.                                         for (i = 0; i < buf_col; i++)
  967.                                         {
  968.                                                 buffer[i] = (char**)allocmem(buf_row * sizeof(char*));
  969.                                                 for (j = 0; j < buf_row; j++)
  970.                                                 {
  971.                                                         if (cells[i + x0][j + y0])
  972.                                                         {
  973.                                                                 if (SCAN_CODE_KEY_C == key_scancode)
  974.                                                                 {
  975.                                                                         buffer[i][j] = (char*)allocmem(strlen(cells[i + x0][j + y0]));
  976.                                                                         strcpy(buffer[i][j], cells[i + x0][j + y0]);
  977.                                                                 }
  978.                                                                 else
  979.                                                                 {
  980.                                                                         buffer[i][j] = cells[i + x0][j + y0];
  981.                                                                         cells[i + x0][j + y0] = NULL;
  982.                                                                 }
  983.                                                         }
  984.                                                         else
  985.                                                                 buffer[i][j] = NULL;
  986.                                                 }
  987.                                         }
  988.                                         if (key_ascii == 24)     ///////WTF????
  989.                                                 calculate_values();
  990.                                         draw_grid();
  991.                                         break;
  992.                                 }
  993.                         case SCAN_CODE_KEY_F:
  994.                                 display_formulas = !display_formulas;
  995.                                 draw_grid();
  996.                                 break;
  997.                 }
  998.         }
  999.         else switch (key_scancode)
  1000.         {
  1001.                 case SCAN_CODE_UP:
  1002.                         shift_selection(0, -1, shift);
  1003.                         break;
  1004.                 case SCAN_CODE_LEFT:
  1005.                         shift_selection(-1, 0, shift);
  1006.                         break;
  1007.                 case SCAN_CODE_RIGHT:
  1008.                         shift_selection(1, 0, shift);
  1009.                         break;
  1010.                 case SCAN_CODE_DOWN:
  1011.                         shift_selection(0, 1, shift);
  1012.                         break;
  1013.                 case SCAN_CODE_PGDN:
  1014.                         shift_selection(0, ny-grid.firsty-1, shift);
  1015.                         break;
  1016.                 case SCAN_CODE_PGUP:
  1017.                         shift_selection(0, -(ny-grid.firsty), shift);
  1018.                         break;
  1019.                 case SCAN_CODE_HOME:
  1020.                         shift_selection(-sel_x + 1, 0, shift);
  1021.                         break;
  1022.                 case SCAN_CODE_END:
  1023.                         shift_selection(col_count - (nx - grid.firstx) - 1 - sel_x, 0, shift);
  1024.                         break;
  1025.                 case SCAN_CODE_DEL:
  1026.                         {
  1027.                                 int n0 = min(sel_x, sel_end_x);
  1028.                                 int n1 = max(sel_x, sel_end_x);
  1029.                                 int k0 = min(sel_y, sel_end_y);
  1030.                                 int k1 = max(sel_y, sel_end_y);
  1031.  
  1032.                                 for (int i = n0; i <= n1; i++)
  1033.                                         for (int j = k0; j <= k1; j++)
  1034.                                         {
  1035.                                                 if (cells[i][j])
  1036.                                                 {
  1037.                                                         freemem(cells[i][j]);
  1038.                                                         cells[i][j] = NULL;
  1039.                                                 }
  1040.                                         }
  1041.                                 calculate_values();
  1042.                                 draw_grid();
  1043.                                 break;
  1044.                         }
  1045.                         break;
  1046.                 case SCAN_CODE_F2:
  1047.                         start_edit(sel_x, sel_y);
  1048.                         break;
  1049.                 case SCAN_CODE_F5:
  1050.                         draw_grid();
  1051.                         break;
  1052.                 default:
  1053.                         start_edit(sel_x, sel_y);
  1054.                         __asm
  1055.                         {
  1056.                                 mov eax, key_editbox
  1057.                         }
  1058.                         edit_box_key((dword)&cell_box);
  1059.                         break;
  1060.         }
  1061. }
  1062.  
  1063. void EventLoadFile()
  1064. {
  1065.         stop_edit();
  1066.         int r = LoadFile(fname);
  1067.         if (r > 0) {
  1068.                 calculate_values();
  1069.                 sel_moved = 0;
  1070.                 draw_grid();
  1071.                 //result = (char*)msg_load;
  1072.         } else {
  1073.                 char *result;
  1074.                 if (r == -1) result = (char*)er_file_not_found;
  1075.                 else if (r == -2) result = (char*)er_format;
  1076.                 kos_AppRun("/sys/@notify", result);
  1077.         }
  1078. }
  1079.  
  1080. void EventGridSelectAll()
  1081. {
  1082.         sel_y = 1;
  1083.         sel_x = 1;
  1084.         sel_end_x = col_count - 1;
  1085.         sel_end_y = row_count - 1;
  1086.         stop_edit();
  1087.         draw_grid();
  1088. }
  1089.  
  1090. void process_button()
  1091. {
  1092.         Dword button;
  1093.         if (!kos_GetButtonID(button)) return;
  1094.         switch (button)
  1095.         {
  1096.         case 1:
  1097.                 kos_ExitApp();
  1098.  
  1099.         case NEW_BUTTON:        // clear the table
  1100.                 reinit();
  1101.                 draw_grid();
  1102.                 break;
  1103.  
  1104.         case SAVE_BUTTON:
  1105.                 stop_edit();
  1106.                 if (SaveFile(fname)) {
  1107.                         kos_AppRun("/sys/@notify", (char*)msg_save);
  1108.                 }
  1109.                 else {
  1110.                         kos_AppRun("/sys/@notify", (char*)msg_save_error);
  1111.                 }
  1112.                 break;
  1113.  
  1114.         case LOAD_BUTTON:
  1115.                 EventLoadFile();
  1116.                 break;
  1117.  
  1118.         case SELECT_ALL_BUTTON:
  1119.                 EventGridSelectAll();
  1120.                 break;
  1121.         }
  1122.         if (button >= COL_HEAD_BUTTON    &&    button < ROW_HEAD_BUTTON)
  1123.         {
  1124.                 sel_end_x = sel_x = button - COL_HEAD_BUTTON;
  1125.                 sel_y = 1;
  1126.                 sel_end_y = row_count - 1;
  1127.                 stop_edit();
  1128.                 draw_grid();
  1129.                 return;
  1130.         }
  1131.         else if (button >= ROW_HEAD_BUTTON    &&    button < CELL_BUTTON)
  1132.         {
  1133.                 sel_end_y = sel_y = button - ROW_HEAD_BUTTON;
  1134.                 sel_x = 1;
  1135.                 sel_end_x = col_count - 1;
  1136.                 stop_edit();
  1137.                 draw_grid();
  1138.                 return;
  1139.         }
  1140. }
  1141.  
  1142. void kos_Main()
  1143. {
  1144.         kos_InitHeap();
  1145.         load_edit_box();
  1146.         init();
  1147.         if (params[0]) {
  1148.                 strcpy(fname, params);
  1149.                 file_box.size = file_box.pos = strlen(fname);
  1150.                 EventLoadFile();
  1151.         }
  1152.         kos_SetMaskForEvents(EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_MOUSE + EVM_MOUSE_FILTER);
  1153.         for (;;)
  1154.         {
  1155.                 switch (kos_WaitForEvent())
  1156.                 {
  1157.                 case EM_MOUSE_EVENT:
  1158.                         process_mouse();
  1159.                         break;
  1160.  
  1161.                 case EM_KEY_PRESS:
  1162.                         process_key();
  1163.                         break;
  1164.  
  1165.                 case EM_BUTTON_CLICK:
  1166.                         process_button();
  1167.                         break;
  1168.                
  1169.                 case EM_WINDOW_REDRAW:
  1170.                         draw_window();
  1171.                         break;
  1172.                 }
  1173.         }
  1174. }
  1175.  
  1176.