Subversion Repositories Kolibri OS

Rev

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