Subversion Repositories Kolibri OS

Rev

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

  1. ; элемент TreeList для библиотеки box_lib.obj
  2. ; на код применена GPL2 лицензия
  3. ; последняя модификация 12.09.2017 IgorA
  4.  
  5.  
  6. struct TreeNode
  7.         type dw ? ;+ 0 тип элемента, или индекс иконки для узла
  8.         level db ? ;+ 2 уровень элемента
  9.         close db ? ;+ 3 флаг закрытия, или открытия (имеет смысл для родительского узла)
  10.         perv dd ? ;+ 4 индекс предыдущего элемента
  11.         next dd ? ;+ 8 индекс последующего элемента
  12.         t_create dd ? ;+12 врем. создания
  13.         t_delete dd ? ;+16 врем. удаления
  14. ends
  15.  
  16.  
  17. ;выделние памяти для структур списка и основной информации (конструктор)
  18. align 16
  19. proc tl_data_init uses eax ecx edi, tlist:dword
  20.         mov edi,[tlist]
  21.  
  22.         xor ecx,ecx
  23.         mov cx,tl_info_size
  24.         imul ecx,tl_info_max_count
  25.         invoke mem.alloc,ecx
  26.         mov tl_data_info,eax ;копируем указатель на полученую память в структуру
  27.         mov tl_data_img,0  ;обнуляем указатель 'data_img'
  28.         mov tl_data_img_sys,0 ;обнуляем указатель 'data_img_sys'
  29.  
  30.         mov ecx,sizeof.TreeNode
  31.         imul ecx,tl_info_max_count
  32.         invoke mem.alloc,ecx
  33.         mov tl_data_nodes,eax ;копируем указатель на полученую память в структуру
  34.  
  35.         stdcall tl_info_clear, edi
  36.  
  37.         ;настройки дочернего скроллинга
  38.         cmp tl_p_scroll,0
  39.         je @f
  40.                 mov eax,tl_p_scroll
  41.                 ;*** цветовые настройки ***
  42.                 mov ecx,tl_col_bkg
  43.                 mov dword[eax+sb_offs_bckg_col],ecx
  44.                 mov ecx,tl_col_zag
  45.                 mov dword[eax+sb_offs_frnt_col],ecx
  46.                 mov ecx,tl_col_txt
  47.                 mov dword[eax+sb_offs_line_col],ecx
  48.                 ;*** настройки размеров ***
  49.                 mov ecx,tl_box_left
  50.                 add ecx,tl_box_width
  51.                 mov word[eax+2],cx
  52.                 mov ecx,tl_box_height
  53.                 mov word[eax+4],cx
  54.                 mov ecx,tl_box_top
  55.                 mov word[eax+6],cx
  56.         @@:
  57.         ret
  58. endp
  59.  
  60. ;очистка памяти элемента (деструктор)
  61. align 4
  62. proc tl_data_clear uses eax edi, tlist:dword
  63.         mov edi,[tlist]
  64.         cmp tl_data_img,0
  65.         je @f
  66.                 invoke mem.free,tl_data_img ;чистка системных иконок
  67.         @@:
  68.         cmp tl_data_img_sys,0
  69.         je @f
  70.                 invoke mem.free,tl_data_img_sys ;чистка системных иконок
  71.         @@:
  72.         invoke mem.free,tl_data_info
  73.         invoke mem.free,tl_data_nodes
  74.         ret
  75. endp
  76.  
  77. ;очистка списка (информации)
  78. align 4
  79. proc tl_info_clear uses eax ecx edi, tlist:dword
  80.         mov edi,[tlist]
  81.         mov tl_ch_tim,0
  82.         mov tl_tim_undo,0
  83.         mov tl_cur_pos,0
  84.         mov ecx,sizeof.TreeNode
  85.         imul ecx,tl_info_max_count
  86.         mov eax,tl_data_nodes
  87.         @@:
  88.                 mov byte[eax],0 ;чистим узлы 0-ми
  89.                 inc eax
  90.                 loop @b
  91.         mov eax,tl_data_nodes ;указатель на 0-й узел
  92.         mov dword[eax+TreeNode.next],1 ;указатель next в 0-м узле приравниваем к 1
  93.  
  94.         cmp tl_p_scroll,0 ;обработка скроллинга
  95.         je @f
  96.                 mov eax,tl_p_scroll
  97.                 mov dword[eax+sb_offs_position],0
  98.                 call tb_scrol_resize
  99.         @@:
  100.         ret
  101. endp
  102.  
  103. ;реакция на клавиатуру
  104. align 4
  105. proc tl_key uses ebx ecx edi, tlist:dword
  106.         mov edi,[tlist]
  107.  
  108.         mov ebx,tl_el_focus
  109.         cmp [ebx],edi
  110.         jne .no_focus ;элемент не в фокусе
  111.  
  112.         push eax
  113.         mcall SF_KEYBOARD,SSF_GET_INPUT_MODE ;получить режим ввода с клавиатуры
  114.  
  115.         lea ecx,[tl_key_scan]
  116.         cmp eax,1 ;1 = сканкоды
  117.         je @f
  118.                 lea ecx,[tl_key_ascii]
  119.         @@:
  120.         pop eax
  121.  
  122.         xor bx,bx
  123.         cmp ah,byte[ecx] ;Enter
  124.         jne @f
  125.         cmp tl_on_press,0
  126.         je @f
  127.                 call tl_on_press
  128.         @@:
  129.         cmp ah,byte[ecx+1] ;Space
  130.         jne @f
  131.                 stdcall tl_node_close_open, edi
  132.         @@:
  133.         cmp ah,byte[ecx+2] ;Up
  134.         jne @f
  135.                 stdcall tl_cur_perv, edi
  136.         @@:
  137.         cmp ah,byte[ecx+3] ;Down
  138.         jne @f
  139.                 stdcall tl_cur_next, edi
  140.         @@:
  141.         cmp ah,byte[ecx+7] ;Page Up
  142.         jne @f
  143.                 stdcall tl_cur_page_up, edi
  144.         @@:
  145.         cmp ah,byte[ecx+8] ;Page Down
  146.         jne @f
  147.                 stdcall tl_cur_page_down, edi
  148.         @@:
  149.  
  150.         bt tl_style,0 ;tl_key_no_edit
  151.         jc .no_edit
  152.                 cmp ah,byte[ecx+4] ;Left
  153.                 jne @f
  154.                         stdcall tl_node_lev_dec, edi
  155.                         mov bx,1
  156.                 @@:
  157.                 cmp ah,byte[ecx+5] ;Right
  158.                 jne @f
  159.                         stdcall tl_node_lev_inc, edi
  160.                         mov bx,1
  161.                 @@:
  162.                 cmp ah,byte[ecx+6] ;Delete
  163.                 jne @f
  164.                         stdcall tl_node_delete, edi
  165.                         mov bx,1
  166.                 @@:
  167.         .no_edit:
  168.  
  169.         cmp bx,1
  170.         jne .no_focus
  171.                 stdcall tl_draw, edi
  172.         .no_focus:
  173.         ret
  174. endp
  175.  
  176. ;реакция на мышь
  177. align 4
  178. proc tl_mouse, tlist:dword
  179.         pushad
  180.         mov edi,[tlist]
  181.  
  182.         mcall SF_MOUSE_GET,SSF_WINDOW_POSITION ;координаты мыши относительно окна
  183.  
  184.         mov ebx,tl_box_left
  185.         shl ebx,16
  186.         cmp eax,ebx ;левая граница окна
  187.         jl .no_in_wnd ;.test_scroll не применяем
  188.                 shr ebx,16
  189.                 add ebx,tl_box_width
  190.                 shl ebx,16
  191.                 cmp eax,ebx ;правая граница окна
  192.                 jg .test_scroll
  193.  
  194.                 mov ebx,tl_box_top
  195.                 add ebx,tl_box_height
  196.                 cmp ax,bx ;нижняя граница окна
  197.                 jg .test_scroll
  198.  
  199.                 sub ebx,tl_box_height
  200.                 add bx,tl_capt_cy
  201.                 cmp ax,bx ;верхняя граница окна + высота подписи
  202.                 jl .test_scroll
  203.  
  204. push eax ebx
  205.         mcall SF_MOUSE_GET,SSF_SCROLL_DATA
  206.         mov edx,eax
  207.         xor     ecx,ecx
  208.         test eax,eax
  209.         jz .mouse_next
  210.         test ax,0x8000
  211.         jnz .decr
  212.         shr eax,16
  213.         test ax,0x8000
  214.         jnz .decr_1
  215.  
  216.         mov cx,dx ;dx = mouse scroll data vertical
  217.         test ecx,ecx
  218.         jnz @f
  219.         shr edx,16
  220.         mov cx,dx ;dx = mouse scroll data horizontal
  221.         test ecx,ecx
  222.         jz .mouse_next
  223. @@:
  224.         stdcall tl_cur_next, edi
  225.         loop @r
  226.         jmp .mouse_next
  227. ;------------------------------------------------
  228. .decr: ;вертикальная прокрутка отрицательная
  229.         mov bx,ax ;ax = mouse scroll data vertical
  230.         jmp @f
  231. .decr_1: ;горизонтальная прокрутка отрицательная
  232.         mov bx,ax ;ax = mouse scroll data horizontal
  233. @@:
  234.         mov ecx,0xffff
  235.         sub ecx,ebx
  236.         inc ecx
  237. @@:
  238.         stdcall tl_cur_perv, edi
  239.         loop @r
  240. ;------------------------------------------------
  241. .mouse_next:
  242.  
  243.                 mcall SF_MOUSE_GET,SSF_BUTTON_EXT
  244.                 test eax,$01000000
  245.                 jz @f
  246.                 call tl_on_press
  247.                 ret
  248. @@:    
  249.                 bt eax,0 ;left mouse button press
  250. pop ebx eax
  251.                 jae .no_draw
  252.  
  253.                 mov esi,tl_el_focus
  254.                 mov [esi],edi ;set focus
  255.  
  256.                 ; if '+' or '-' press
  257.                 mov esi,eax
  258.                 shr esi,16
  259.                 sub esi,tl_box_left ;esi = mouse x coord in element window
  260.  
  261.                 and eax,0xffff
  262.                 sub eax,ebx
  263.                 xor edx,edx
  264.                 movzx ecx,tl_img_cy
  265.                 div ecx
  266.                 cmp tl_p_scroll,0 ;учитываем скроллинг
  267.                 je @f
  268.                         mov edx,tl_p_scroll
  269.                         add eax,[edx+sb_offs_position] ;добавляем скроллинг на верху
  270.                 @@:
  271.  
  272.                 mov ecx,eax
  273.                 call tl_get_node_count ;eax = node count
  274.                 bt tl_style,3 ;tl_cursor_pos_limited
  275.                 jnc @f
  276.                 or eax,eax
  277.                 jz @f
  278.                         dec eax ;если курсор стает на существующие узлы
  279.                 @@:
  280.                 cmp eax,ecx
  281.                 jl @f
  282.                         mov eax,ecx ;если курсор не вышел за пределы узлов, восстанавливаем старое значение eax
  283.                 @@:
  284.  
  285.                 cmp eax,tl_cur_pos ;если новое значение курсора совпало с предыдущим
  286.                 je @f ;то не стираем курсор
  287.                 push esi
  288.                         mov esi,tl_box_top
  289.                         add esi,tl_box_height ;esi = coord bottom border
  290.                         call tl_draw_null_cursor ;стираем курсор
  291.                 pop esi
  292.                 @@:
  293.  
  294.                 mov tl_cur_pos,eax
  295.  
  296.                 ; if '+' or '-' press
  297.                 call tl_get_cur_node_index ;eax = node index
  298.                 cmp eax,2
  299.                 jl .no_open_close ;курсор стоит на пустом месте, без узлов
  300.                 imul eax,sizeof.TreeNode
  301.                 add eax,tl_data_nodes
  302.                 xor bx,bx
  303.                 mov bl,byte[eax+TreeNode.level] ;сохраняем уровень текущего узла
  304.                 inc bx ;+ поле для курсора
  305.  
  306.                 cmp si,tl_img_cx
  307.                 jl .no_open_close ;мышей попали на левое поле для курсора, где точно нет '+' и '-'
  308.                         mov eax,esi
  309.                         xor edx,edx
  310.                         xor ecx,ecx
  311.                         mov cx,tl_img_cx
  312.                         div ecx
  313.  
  314.                         cmp ax,bx
  315.                         jne .no_open_close
  316.  
  317.                         stdcall tl_node_close_open, edi
  318.                 .no_open_close:
  319.  
  320.                 mov esi,tl_box_top
  321.                 add esi,tl_box_height ;esi = coord bottom border
  322.                 call tl_draw_cursor ;перерисовка курсора
  323.                 call tl_draw_caption_cur_pos
  324.                 jmp .no_draw
  325. ;--- mouse event for children scrollbar ----------------------------------------
  326. .test_scroll:
  327.         mov edx,tl_p_scroll
  328.         or edx,edx
  329.         jz .no_in_wnd ;пользователь не создал дочернего скроллинга
  330.                 shr ebx,16
  331.                 add bx,word[edx] ;+0 .size_x
  332.                 shl ebx,16
  333.                 cmp eax,ebx ;правая граница окна
  334.                 jg .no_in_wnd
  335.  
  336.                 mov eax,[edx+sb_offs_max_area]
  337.                 cmp eax,[edx+sb_offs_cur_area]
  338.                 jbe .no_in_wnd ;все узлы попадают в окно скроллинга
  339.                         stdcall scroll_bar_vertical.mouse, edx ;scrollbar_ver_mouse
  340.  
  341.                         cmp dword[edx+sb_offs_redraw],0
  342.                         je @f
  343.                                 mov dword[edx+sb_offs_redraw],0
  344.                                 stdcall tl_draw, edi ;произошли изменения скроллинга
  345.                         @@:
  346.                         cmp dword[edx+sb_offs_delta2],0
  347.                         jne .no_draw ;попали на скроллинг - не снимаем фокус с TreeList
  348. ;-------------------------------------------------------------------------------
  349.         .no_in_wnd: ;не попали в окно - потеря фокуса (при условии что фокус был на данном эелементе)
  350.         mcall SF_MOUSE_GET,SSF_BUTTON
  351.         or eax,eax ;ничего не нажали eax=0
  352.         jz .no_draw
  353.                 mov ebx,tl_el_focus
  354.                 cmp [ebx],edi
  355.                 jne .no_draw ;элемент не в фокусе
  356.                         mov dword[ebx],0 ;reset focus
  357.                         mov esi,tl_box_top
  358.                         add esi,tl_box_height ;esi = coord bottom border
  359.                         call tl_draw_cursor ;рисуем курсор с потеряным фокусом
  360.         .no_draw:
  361.  
  362.         popad
  363.         ret
  364. endp
  365.  
  366. ;отмена действия
  367. align 4
  368. proc tl_info_undo uses eax edi, tlist:dword
  369.         mov edi,[tlist]
  370.         mov eax,tl_tim_undo
  371.         cmp tl_ch_tim,eax
  372.         jbe @f
  373.                 inc tl_tim_undo
  374.                 call tb_scrol_resize ;обработка скроллинга
  375.         @@:
  376.         ret
  377. endp
  378.  
  379. ;повтор действия
  380. align 4
  381. proc tl_info_redo uses edi, tlist:dword
  382.         mov edi,[tlist]
  383.         cmp tl_tim_undo,1
  384.         jl @f
  385.                 dec tl_tim_undo
  386.                 call tb_scrol_resize ;обработка скроллинга
  387.         @@:
  388.         ret
  389. endp
  390.  
  391. ;удаление отмененных действий
  392. ;внутренняя функция, не для экспорта
  393. align 4
  394. tl_info_set_undo:
  395.         cmp tl_tim_undo,1
  396.         jl .no_work
  397.  
  398.         push eax ebx ecx edx
  399.         mov edx,tl_data_nodes
  400.         mov ecx,edx
  401.         add ecx,sizeof.TreeNode
  402.         call tl_move_next ;long i=node[0].next;
  403.  
  404.         mov eax,tl_tim_undo
  405.         sub tl_ch_tim,eax ;ch_tim-=tim_undo;
  406.  
  407.         cmp edx,ecx
  408.         jle @f
  409.                 ;if(node[i].tc>ch_tim){ // если создание символа было отменено
  410.                 mov eax,tl_ch_tim
  411.                 cmp [edx+TreeNode.t_create],eax
  412.                 jle .no_u1
  413.                         mov dword[edx+TreeNode.t_create],0
  414.                         mov dword[edx+TreeNode.t_delete],0
  415.  
  416.                         mov ebx, [edx+TreeNode.perv]
  417.                         imul ebx,sizeof.TreeNode
  418.                         add ebx, tl_data_nodes ;.next
  419.                         push dword[edx+TreeNode.next] ;node[node[i].perv].next=node[i].next;
  420.                         pop dword[ebx+TreeNode.next]
  421.  
  422.                         mov ebx, [edx+TreeNode.next]
  423.                         imul ebx,sizeof.TreeNode
  424.                         add ebx, tl_data_nodes ;.perv
  425.                         push dword[edx+TreeNode.perv] ;node[node[i].next].perv=node[i].perv;
  426.                         pop dword[ebx+TreeNode.perv]
  427.                 .no_u1:
  428.  
  429.                 ;else if(node[i].td>ch_tim) node[i].td=0; // если удаление символа было отменено
  430.                 cmp [edx+TreeNode.t_delete],eax
  431.                 jle .no_u2
  432.                         mov dword[edx+TreeNode.t_delete],0
  433.                 .no_u2:
  434.                 call tl_move_next
  435.                 jmp @b
  436.         @@:
  437.         mov tl_tim_undo,0
  438.         pop edx ecx ebx eax
  439.         .no_work:
  440.         ret
  441.  
  442. ;вывод списка на экран
  443. align 4
  444. proc tl_draw, tlist:dword
  445.         pushad
  446.         ;draw dir_list main rect
  447.         mov edi,[tlist]
  448.         mov ebx,tl_box_left
  449.         shl ebx,16
  450.         add ebx,tl_box_width
  451.         mov ecx,tl_box_top
  452.         shl ecx,16
  453.         mov cx,tl_capt_cy
  454.         mov edx,tl_col_zag
  455.         mcall SF_DRAW_RECT ;draw window caption
  456.  
  457.         add ecx,tl_box_top
  458.         shl ecx,16
  459.         add ecx,tl_box_height
  460.         sub cx,tl_capt_cy
  461.         mcall ,,,tl_col_bkg ;draw window client rect
  462.  
  463.         cmp tl_capt_cy,9 ;9 - minimum caption height
  464.         jl @f
  465.         mov ebx,edi ;calculate cursor position
  466.         mov eax,tl_cur_pos
  467.         inc eax
  468.         lea edi,[txt_capt_cur.v]
  469.         stdcall tl_convert_to_str, 5
  470.  
  471.         mov edi,ebx
  472.         mov eax,tl_tim_undo
  473.         lea edi,[txt_capt_otm.v]
  474.         stdcall tl_convert_to_str, 5
  475.         mov edi,ebx ;restore edi
  476.  
  477.         mov eax,SF_DRAW_TEXT ;captions
  478.         mov ebx,tl_box_left
  479.         shl ebx,16
  480.         add ebx,5*65536+3
  481.         add ebx,tl_box_top
  482.         mov ecx,tl_col_txt
  483.         or  ecx,0x80000000
  484.         lea edx,[txt_capt_cur]
  485.         int 0x40
  486.  
  487.         mov ebx,tl_box_left
  488.         shl ebx,16
  489.         add ebx,100*65536+3
  490.         add ebx,tl_box_top
  491.         lea edx,[txt_capt_otm]
  492.         int 0x40
  493.         @@:
  494.  
  495.         ;cycle to nodes
  496.         xor eax,eax
  497.         mov edx,tl_data_nodes
  498.         mov ecx,edx
  499.         add ecx,sizeof.TreeNode
  500.  
  501.         ;*** пропуск узлов, которые промотаны скроллингом ***
  502.         cmp tl_p_scroll,0 ;если есть указатель на скроллинг
  503.         je .end_c1
  504.                 mov esi,tl_p_scroll
  505.                 cmp dword[esi+sb_offs_position],0 ;если скроллинг на верху, выходим
  506.                 je .end_c1
  507.                 @@:
  508.                         call tl_iterat_next
  509.                         cmp edx,ecx
  510.                         jle .end_draw
  511.                         inc eax
  512.                         cmp eax,dword[esi+sb_offs_position]
  513.                         jl @b
  514.         .end_c1:
  515.  
  516.         xor eax,eax
  517.         mov esi,tl_box_top
  518.         add esi,tl_box_height ;esi = coord bottom border
  519.         @@:
  520.                 call tl_iterat_next
  521.                 cmp edx,ecx
  522.                 jle @f
  523.                 call tl_draw_node
  524.                 inc eax
  525.                 jmp @b
  526.         @@:
  527.  
  528.         call tl_draw_cursor
  529.  
  530.         mov edi,tl_p_scroll ;рисуем дочерний скроллинг
  531.         cmp edi,0    ;для того что-бы его не пришлось рисовать в пользовательской программе
  532.         je .end_draw ;если нет скроллинга выходим
  533.                 stdcall scroll_bar_vertical.draw, edi
  534.         .end_draw:
  535.         popad
  536.         ret
  537. endp
  538.  
  539. ;переход на следущий видимый узел (пропуская закрытые)
  540. ;input:
  541. ; ecx = pointer to 1 node struct
  542. ; edx = pointer to node struct
  543. ; edi = pointer to 'TreeList' struct
  544. ;output:
  545. ; edx = pointer to next node struct
  546. align 4
  547. tl_iterat_next:
  548.         push bx
  549.         mov bl,0x7f
  550.         cmp byte[edx+TreeNode.close],1
  551.         jne @f
  552.                 mov bl,byte[edx+TreeNode.level]
  553.         @@:
  554.  
  555.         cmp tl_tim_undo,0
  556.         je .else
  557.  
  558.         push eax
  559.         .beg0:
  560.                 call tl_move_next
  561.                 cmp edx,ecx
  562.                 jle @f
  563.                 call tl_node_not_vis ;пропуск удаленных и отмененных
  564.                 cmp al,1
  565.                 je .beg0
  566.                 cmp bl,byte[edx+TreeNode.level] ;пропуск закрытых
  567.                 jl .beg0
  568.                 @@:
  569.         pop eax
  570.         pop bx
  571.         ret
  572.  
  573.         .else:
  574.                 call tl_move_next
  575.                 cmp edx,ecx
  576.                 jle .endif
  577.                 cmp dword[edx+TreeNode.t_delete],0 ;пропуск удаленных
  578.                 jne .else
  579.                 cmp bl,byte[edx+TreeNode.level] ;пропуск закрытых
  580.                 jl .else
  581.         .endif:
  582.         pop bx
  583.         ret
  584.  
  585. ;переход на следущий видимый узел (и на закрытые тоже)
  586. ;input:
  587. ; ecx = pointer to 1 node struct
  588. ; edx = pointer to node struct
  589. ; edi = pointer to 'TreeList' struct
  590. ;output:
  591. ; edx = pointer to next visible node struct
  592. align 4
  593. tl_iterat_next_all:
  594.         cmp tl_tim_undo,0
  595.         je .else
  596.  
  597.         push eax
  598.         @@:
  599.                 call tl_move_next
  600.                 cmp edx,ecx
  601.                 jle @f
  602.                 call tl_node_not_vis
  603.                 cmp al,1
  604.                 je @b
  605.         @@:
  606.         pop eax
  607.         ret
  608.         .else:
  609.                 call tl_move_next
  610.                 cmp edx,ecx
  611.                 jle .endif
  612.                 cmp dword[edx+TreeNode.t_delete],0 ;td -> time delete
  613.                 jne .else
  614.         .endif:
  615.         ret
  616.  
  617. ;переход на предыдущий видимый узел (пропуская закрытые)
  618. ;input:
  619. ; ecx = pointer to 1 node struct
  620. ; edx = pointer to node struct
  621. ; edi = pointer to 'TreeList' struct
  622. align 4
  623. proc tl_iterat_perv uses eax
  624.         cmp tl_tim_undo,0
  625.         je .beg1
  626.  
  627.         .beg0:
  628.                 call tl_move_perv
  629.                 cmp edx,ecx
  630.                 jle @f
  631.                 call tl_node_not_vis ;пропуск удаленных и отмененных
  632.                 cmp al,1
  633.                 je .beg0
  634.  
  635.         .beg1:
  636.                 call tl_move_perv
  637.                 cmp edx,ecx
  638.                 jle @f
  639.                 cmp dword[edx+TreeNode.t_delete],0 ;td = 'time delete' -> пропуск удаленных
  640.                 jne .beg1
  641.  
  642.         @@:
  643.         call tl_move_max_clo_par
  644.         ret
  645. endp
  646.  
  647. ;находит родительский закрытый узел максимального уровня
  648. ;input:
  649. ; edx = pointer to node struct
  650. ; edi = pointer to 'TreeList' struct
  651. ;output:
  652. ; edx = pointer closed parent node with maximum level
  653. align 4
  654. proc tl_move_max_clo_par uses eax ebx
  655.         mov eax,edx
  656.         xor ebx,ebx
  657.         .beg:
  658.                 call tl_move_par
  659.                 cmp byte[edx+TreeNode.close],1 ;родительский узел закрыт ?
  660.                 jne @f
  661.                         mov eax,edx
  662.                 @@:
  663.                 cmp ebx,edx
  664.                 je .end_f
  665.                         mov ebx,edx
  666.                         jmp .beg
  667.         .end_f:
  668.         mov edx,eax
  669.         ret
  670. endp
  671.  
  672. ;input:
  673. ; edx = pointer to node struct
  674. ; edi = pointer to 'TreeList' struct
  675. ;output:
  676. ; edx = pointer to next node struct
  677. align 4
  678. tl_move_next:
  679.         mov edx,[edx+TreeNode.next]
  680.         imul edx,sizeof.TreeNode
  681.         add edx,tl_data_nodes
  682.         ret
  683.  
  684. ;input:
  685. ; edx = pointer to node struct
  686. ; edi = pointer to 'TreeList' struct
  687. ;output:
  688. ; edx = pointer to perv node struct
  689. align 4
  690. tl_move_perv:
  691.         mov edx,[edx+TreeNode.perv]
  692.         imul edx,sizeof.TreeNode
  693.         add edx,tl_data_nodes
  694.         ret
  695.  
  696. ;передвигаемся на родительский узел, если такого нет, то оставляем старое значение указателя
  697. ;input:
  698. ; ecx = pointer to 1 node struct
  699. ; edx = pointer to node struct
  700. ; edi = pointer to 'TreeList' struct
  701. ;output:
  702. ; edx = pointer to parent node struct
  703. align 4
  704. tl_move_par:
  705.         cmp byte[edx+TreeNode.level],0
  706.         je .end_f ;узел 0-го уровня не может быть дочерним
  707.         push eax ebx esi
  708.         mov esi,edx ;copy node pointer (edx)
  709.         mov bl,byte[edx+TreeNode.level]
  710.         @@:
  711.                 call tl_move_perv
  712.                 cmp edx,ecx
  713.                 jle @f ;все выше стоящие узлы не родительские
  714.                 call tl_node_not_vis ;пропуск удаленных и отмененных
  715.                 cmp al,1
  716.                 je @b
  717.                 cmp byte[edx+TreeNode.level],bl
  718.                 jl .end_0 ;удачно нашли родительский узел
  719.                 jmp @b
  720.         @@:
  721.                 mov esi,ebx ;restore node pointer
  722.         .end_0:
  723.         pop esi ebx eax
  724.         .end_f:
  725.         ret
  726.  
  727. ;проверяет видимый ли указанный узел с учетом: добавлений, удалений, отмен действий
  728. ;input:
  729. ; edx = pointer to node struct
  730. ; edi = pointer to 'TreeList' struct
  731. ;output:
  732. ; al = 1 if sumbol not visible
  733. ; (node[i].td+tim_Undo<=ch_tim && node[i].td) || (node[i].tc>ch_tim-tim_Undo)
  734. align 4
  735. tl_node_not_vis:
  736.         cmp dword[edx+TreeNode.t_delete],0
  737.         je @f
  738.         mov eax,[edx+TreeNode.t_delete] ;eax=node[i].td
  739.         add eax,tl_tim_undo
  740.         cmp eax,tl_ch_tim
  741.         jg @f
  742.                 mov al,1
  743.                 ret
  744.         @@:
  745.  
  746.         mov eax,tl_ch_tim
  747.         sub eax,tl_tim_undo
  748.         cmp [edx+TreeNode.t_create],eax ;time create
  749.         jle @f
  750.                 mov al,1
  751.                 ret
  752.         @@:
  753.         xor al,al
  754.         ret
  755.  
  756. ;рисуем курсор на экране
  757. ;input:
  758. ; edi = pointer to TreeInfo struct
  759. ; esi = coord bottom border
  760. align 4
  761. proc tl_draw_cursor uses eax ebx ecx edx esi
  762.         call tl_get_display_cur_pos ;eax = cursor pos in screen
  763.         cmp eax,0
  764.         jl .end_f ;курсор находится выше окна, в области прокрученной скроллингом
  765.  
  766.         cmp tl_data_img_sys,0 ;смотрим есть ли указатель на картинку системных иконок
  767.         jne @f
  768.                 mov ebx,tl_box_left
  769.                 shl ebx,16
  770.                 mov bx,tl_img_cx
  771.                 movzx ecx,tl_img_cy
  772.                 imul ecx,eax
  773.                 add ecx,tl_box_top
  774.                 add cx,tl_capt_cy
  775.  
  776.                 ;crop image if on the border
  777.                 cmp esi,ecx ;если курсор внизу и его вообще не видно
  778.                 jl .end_f
  779.  
  780.                 sub esi,ecx
  781.                 shl ecx,16
  782.                 mov cx,tl_img_cy
  783.                 cmp si,tl_img_cy
  784.                 jge .crop0
  785.                         mov cx,si ;если курсор виден частично (попал на нижнюю границу)
  786.                 .crop0:
  787.  
  788.                 mov edx,tl_col_txt
  789.                 mcall SF_DRAW_RECT ;рисуем простой прямоугольник, т.к. нет системных иконок
  790.                 jmp .end_f
  791.         @@:
  792.         mov ebx,tl_data_img_sys
  793.         imul ax,tl_img_cy
  794.         mov edx,tl_box_left
  795.         shl edx,16
  796.         mov dx,ax
  797.         add edx,tl_box_top
  798.         add dx,tl_capt_cy
  799.  
  800.         mov ecx,tl_el_focus ;проверяем в фокусе элемент или нет
  801.         cmp dword[ecx],edi
  802.         je .focus
  803.                 ;если не в фокусе сдвигаем координаты на иконку не активного курсора
  804.                 movzx ecx,tl_img_cx
  805.                 movzx eax,tl_img_cy
  806.                 imul eax,ecx
  807.                 imul eax,4*3 ;4=icon index 3=rgb
  808.                 add ebx,eax
  809.         .focus:
  810.  
  811.         mov cx,tl_img_cx
  812.         shl ecx,16
  813.         mov cx,tl_img_cy
  814.  
  815.         ;crop image if on the border
  816.         cmp si,dx ;если курсор внизу и его вообще не видно
  817.         jl .end_f
  818.  
  819.                 sub si,dx
  820.                 cmp si,tl_img_cy
  821.                 jge .crop1
  822.                         mov cx,si ;если курсор виден частично (попал на нижнюю границу)
  823.                 .crop1:
  824.  
  825.                 mcall SF_PUT_IMAGE ;рисуем иконку курсора
  826.         .end_f:
  827.         ret
  828. endp
  829.  
  830. ;стираем курсор на экране
  831. ;input:
  832. ; edi = pointer to TreeInfo struct
  833. ; esi = coord bottom border
  834. align 4
  835. proc tl_draw_null_cursor uses eax ebx ecx edx esi
  836.         call tl_get_display_cur_pos ;eax = cursor pos in screen
  837.         cmp eax,0
  838.         jl .end_f ;курсор находится выше окна, в области прокрученной скроллингом
  839.                 mov ebx,tl_box_left
  840.                 shl ebx,16
  841.                 mov bx,tl_img_cx
  842.                 movzx ecx,tl_img_cy
  843.                 imul ecx,eax
  844.                 add ecx,tl_box_top
  845.                 add cx,tl_capt_cy
  846.  
  847.                 ;crop image if on the border
  848.                 cmp esi,ecx ;если курсор внизу и его вообще не видно
  849.                 jl .end_f
  850.  
  851.                 sub esi,ecx
  852.                 shl ecx,16
  853.                 mov cx,tl_img_cy
  854.                 cmp si,tl_img_cy
  855.                 jge @f
  856.                         mov cx,si ;если курсор виден частично (попал на нижнюю границу)
  857.                 @@:
  858.                 mcall SF_DRAW_RECT,,,tl_col_bkg ;рисуем простой прямоугольник с фоновым цветом
  859.         .end_f:
  860.         ret
  861. endp
  862.  
  863. ;берет позицию курсора, относительно экрана
  864. ;input:
  865. ; edi = pointer to TreeInfo struct
  866. ;output:
  867. ; eax = index
  868. align 4
  869. tl_get_display_cur_pos:
  870.         mov eax,tl_cur_pos
  871.         cmp tl_p_scroll,0
  872.         je @f
  873.                 push ebx
  874.                 mov ebx,tl_p_scroll
  875.                 mov ebx,dword[ebx+sb_offs_position]
  876.                 sub eax,ebx ;отнимаем позицию скроллинга
  877.                 pop ebx
  878.         @@:
  879.         ret
  880.  
  881. ;рисует узел с: картинкой, подписью, иконкой открытия/закрытия и линиями к родит. узлу
  882. ;input:
  883. ; eax = node position (0, ..., max_nodes-scroll_pos) не до tl_box_height/tl_img_cy
  884. ; edx = pointer to node struct
  885. ; edi = pointer to 'TreeList' struct
  886. ; esi = coord of bottom border
  887. align 4
  888. proc tl_draw_node uses eax ebx ecx edx esi
  889.         mov ebx,1 ;1 - место под курсор
  890.         bt tl_style,2 ;tl_list_box_mode
  891.         jc @f
  892.                 inc ebx ;+1 - место под знак +,-
  893.                 add bl,byte[edx+TreeNode.level] ;добавляем уровень элемента для его учета в левом отступе иконки
  894.         @@:
  895.         imul bx,tl_img_cx
  896.         add ebx,tl_box_left
  897.  
  898.         shl ebx,16
  899.         mov bx,tl_img_cx
  900.         movzx ecx,tl_img_cy
  901.         imul ecx,eax
  902.         add cx,tl_capt_cy
  903.         jc .end_draw ;когда много узлов, то может быть переполнение координаты cx
  904.         add ecx,tl_box_top
  905.  
  906.         ;crop image if on the border
  907.         cmp esi,ecx ;если узел внизу и его вообще не видно
  908.         jl .end_draw
  909.  
  910.         sub esi,ecx
  911.         shl ecx,16
  912.         mov cx,tl_img_cy
  913.         cmp si,tl_img_cy
  914.         jge @f
  915.                 mov cx,si ;если узел виден частично (попал на нижнюю границу)
  916.                 jmp .crop ;пропускаем рисование надписи, которая скорее всего тоже вылезет за нижнюю границу
  917.         @@:
  918.                 call tl_draw_node_caption
  919.         .crop:
  920.         mov esi,ecx ;save ecx
  921.  
  922.         push edx
  923.         cmp tl_data_img,0
  924.         jne .draw_img_n
  925.                 mcall SF_DRAW_RECT,,,tl_col_txt ;draw node rect
  926.                 jmp @f
  927.         .draw_img_n:
  928.         push ebx esi
  929.                 movzx esi,word[edx+TreeNode.type] ;get icon type
  930.                 mov edx,ebx
  931.                 ror ecx,16
  932.                 mov dx,cx
  933.                 mov cx,bx
  934.                 ror ecx,16
  935.                 mov ebx,3 ;rgb = 3 bytes
  936.                 imul bx,tl_img_cx
  937.                 imul bx,tl_img_cy
  938.                 imul ebx,esi ;esi = icon index
  939.                 add ebx,tl_data_img
  940.  
  941.                 mcall SF_PUT_IMAGE ;draw node icon '-'
  942.         pop esi ebx
  943.         @@:
  944.         pop edx
  945.  
  946.         mov al,byte[edx+TreeNode.level] ;draw minus '-'
  947.         mov ecx,tl_data_nodes
  948.         add ecx,sizeof.TreeNode
  949.  
  950.         mov ah,10 ;get icon index '+' or '-' ?
  951.         cmp byte[edx+TreeNode.close],1
  952.         jne .close
  953.                 dec ah
  954.         .close:
  955.  
  956.         call tl_draw_node_icon_opn_clo ;рисование иконки открытого или закрытого узла
  957.         bt tl_style,1
  958.         jae .end_draw
  959.                 call tl_draw_node_icon_par_lin ;рисование линии к родительскому элементу
  960.                 call tl_draw_node_icon_par_lin_up ;рисование вертикальной линии к родительскому элементу
  961.         .end_draw:
  962.         ret
  963. endp
  964.  
  965. ;рисует иконки открытого или закрытого узла (обычно + или -)
  966. ;input:
  967. ; al = уровень элемента
  968. ; ecx = pointer to 1 node struct
  969. ; edx = pointer to node struct
  970. ;...
  971. align 4
  972. proc tl_draw_node_icon_opn_clo uses eax ebx ecx edx esi
  973.         inc al
  974.         call tl_iterat_next_all ;get next visible item
  975.         cmp edx,ecx
  976.         jle @f
  977.                 mov ecx,esi ;load ecx
  978.                 cmp al,byte[edx+TreeNode.level]
  979.                 jne @f
  980.                 ror ebx,16
  981.                 sub bx,tl_img_cx
  982.                 ror ebx,16
  983.                 cmp tl_data_img_sys,0
  984.                 jne .draw_img_s
  985.                         mcall SF_DRAW_RECT,,,tl_col_txt ;draw minus rect, if not system icons
  986.                         jmp @f
  987.                 .draw_img_s:
  988.                 mov ecx,esi ;load ecx
  989.                 mov edx,ebx
  990.                 ror ecx,16
  991.                 mov dx,cx
  992.                 mov cx,bx
  993.                 ror ecx,16
  994.                 mov ebx,3 ;rgb = 3 bytes
  995.                 imul bx,tl_img_cx
  996.                 imul bx,tl_img_cy
  997.                 shr eax,8
  998.                 and eax,0xff
  999.                 imul ebx,eax ;eax = icon index
  1000.                 add ebx,tl_data_img_sys
  1001.                 mcall SF_PUT_IMAGE ;draw minus icon '-'
  1002.         @@:
  1003.         ret
  1004. endp
  1005.  
  1006. ;рисование линии к родительскому элементу
  1007. ;input:
  1008. ; al = уровень элемента
  1009. ; ecx = pointer to 1 node struct
  1010. ; edx = pointer to node struct
  1011. ;...
  1012. align 4
  1013. tl_draw_node_icon_par_lin:
  1014.         cmp byte[edx+TreeNode.close],1
  1015.         je .close
  1016.         or al,al
  1017.         jz .close
  1018.         push eax ebx ecx edx esi
  1019.                 call tl_iterat_next_all ;get next visible item
  1020.                 cmp edx,ecx
  1021.                 jle .line3 ;if end of list
  1022.                         cmp al,byte[edx+TreeNode.level]
  1023.                         jne .line3 ;jg ???
  1024.                         mov eax,3 ;line in middle element
  1025.                         jmp .line2
  1026.                 .line3:
  1027.                         mov eax,6 ;line in end element
  1028.                 .line2:
  1029.  
  1030.                 mov ecx,esi ;load ecx
  1031.                 ror ebx,16
  1032.                 sub bx,tl_img_cx
  1033.                 ror ebx,16
  1034.                 cmp tl_data_img_sys,0
  1035.                 jne .draw_img_s
  1036.                         mcall SF_DRAW_RECT,,,tl_col_txt ;draw minus rect, if not system icons
  1037.                         jmp @f
  1038.                 .draw_img_s:
  1039.                 mov edx,ebx
  1040.                 ror ecx,16
  1041.                 mov dx,cx
  1042.                 mov cx,bx
  1043.                 ror ecx,16
  1044.                 mov ebx,3 ;rgb = 3 bytes
  1045.                 imul bx,tl_img_cx
  1046.                 imul bx,tl_img_cy
  1047.  
  1048.                 imul ebx,eax ;eax = icon index
  1049.                 add ebx,tl_data_img_sys
  1050.                 mcall SF_PUT_IMAGE ;draw line icon
  1051.                 @@:
  1052.         pop esi edx ecx ebx eax
  1053.         .close:
  1054.         ret
  1055.  
  1056.  
  1057. ;input:
  1058. ; al = уровень элемента
  1059. ; ebx = (node.left shl 16) + tl_img_cx
  1060. ; ecx = pointer to 1 node struct
  1061. ; edx = pointer to node struct
  1062. ; edi = pointer to 'TreeList' struct
  1063. align 4
  1064. proc tl_draw_node_icon_par_lin_up uses eax ebx ecx edx esi
  1065.         cmp tl_data_img_sys,0 ;if not image
  1066.         je @f
  1067.         or al,al
  1068.         jz @f
  1069.                 xor esi,esi ;в si будем насчитывать кол-во иконок, нужных для прорисовки линии
  1070. ;--- цикл для вычисления колличества вертикальных линий ---
  1071.                 .cycle0:
  1072.                         call tl_iterat_perv ;get perv visible item
  1073.                         cmp edx,ecx
  1074.                         jle .cycle1 ;if begin of list
  1075.  
  1076.                         cmp byte[edx+TreeNode.level],al
  1077.                         jle .cycle0end ;уровень верхнего элемента не требует прорисовки
  1078.                         inc si
  1079.                         jmp .cycle0
  1080.                 .cycle0end:
  1081.                 or si,si ;si = кол-во иконок линии которые нужно нарисовать сверху
  1082.                 jz @f
  1083.                 shl esi,16
  1084.  
  1085.                 pop ecx ;esi->ecx
  1086.                 push ecx ;save esi
  1087.  
  1088.                 ror ebx,16
  1089.                 sub bx,tl_img_cx
  1090.                 ror ebx,16
  1091.  
  1092.                 mov edx,ebx
  1093.                 ror ecx,16
  1094.                 mov dx,cx
  1095.                 mov cx,bx
  1096.                 ror ecx,16
  1097.                 mov cx,tl_img_cy ;restore size y (if crop)
  1098.                 mov ebx,3 ;rgb = 3 bytes
  1099.                 imul bx,tl_img_cx
  1100.                 imul bx,tl_img_cy
  1101.                 add ebx,tl_data_img_sys
  1102.  
  1103.                 add esi,tl_box_top
  1104.                 add si,tl_capt_cy ;si = верхняя граница окна
  1105.                 mov eax,SF_PUT_IMAGE
  1106. ;--- цикл для рисования вертикальной линии ---
  1107.                 .cycle1:
  1108.                 sub dx,tl_img_cy ;поднимаем координату y вверх
  1109.                 cmp dx,si
  1110.                 jl @f
  1111.                         cmp esi,0x10000
  1112.                         jl @f
  1113.                         int 0x40 ;draw line icon
  1114.                         sub esi,0x10000 ;уменьшаем счетчик иконок
  1115.                 jmp .cycle1
  1116.         @@:
  1117.         ret
  1118. endp
  1119.  
  1120. ;input:
  1121. ; edi = pointer to TreeInfo struct
  1122. ;output:
  1123. ; eax = rows
  1124. align 4
  1125. tl_get_rows_count:
  1126.         push ecx edx
  1127.                 mov eax,tl_box_height
  1128.                 sub ax,tl_capt_cy
  1129.                 movzx ecx,tl_img_cy
  1130.                 xor edx,edx
  1131.                 div ecx
  1132.         pop edx ecx
  1133.         ret
  1134.  
  1135. ;input:
  1136. ; eax = node position
  1137. ; ebx = [координата по оси x]*65536 + [img_cx]
  1138. ; ecx = [координата по оси y]*65536 + [img_cy]
  1139. ; edx = pointer to node struct
  1140. ; edi = pointer to TreeInfo struct
  1141. align 4
  1142. proc tl_draw_node_caption uses ebx ecx edx esi
  1143.         xor esi,esi
  1144.         mov si,tl_info_size
  1145.         cmp si,tl_info_capt_offs
  1146.         jle @f ;if caption size <= 0
  1147.                 push eax
  1148.                         call tl_get_node_index ;eax = node index
  1149.                         imul esi,eax
  1150.                 pop eax
  1151.                 add si,tl_info_capt_offs
  1152.                 add esi,tl_data_info
  1153.                 mov edx,esi
  1154.  
  1155.                 shr ebx,16
  1156.                 add bx,tl_img_cx ;сдвигаем надпись по горизонтали --->
  1157.                 add bx,3 ;отступ
  1158.                 ;bx = coord.x
  1159.                 call tl_strlen ;eax = strlen
  1160.                 call tl_get_draw_text_len
  1161.                 mov cx,bx
  1162.                 ror ecx,16
  1163.                 mov ebx,ecx
  1164.                 add bx,tl_img_cy ;выравнивиние по нижней границе иконки
  1165.                 sub bx,9 ;отнимаем высоту текста
  1166.                 mov ecx,tl_col_txt
  1167.                 and ecx,0xffffff
  1168.                 mcall SF_DRAW_TEXT
  1169.         @@:
  1170.         ret
  1171. endp
  1172.  
  1173. ;input:
  1174. ; eax = strlen
  1175. ; ebx = text coord x
  1176. ;output:
  1177. ; esi = text len
  1178. align 4
  1179. proc tl_get_draw_text_len uses eax ecx edx
  1180.         mov esi,eax ;берем длинну строки
  1181.         mov eax,tl_box_left
  1182.         add eax,tl_box_width
  1183.         cmp eax,ebx
  1184.         jle .text_null ;если подпись полностью вся за экраном
  1185.                 sub eax,ebx
  1186.                 xor edx,edx
  1187.                 mov ecx,6 ;ширина системного шрифта
  1188.                 div ecx ;смотрим сколько символов может поместиться на экране
  1189.                 cmp esi,eax
  1190.                 jl @f
  1191.                         mov esi,eax ;если длинна текста меньше, чем все место под строку
  1192.                         jmp @f
  1193.         .text_null:
  1194.         xor esi,esi
  1195.         @@:
  1196.         ret
  1197. endp
  1198.  
  1199. ;input:
  1200. ; esi = pointer to string
  1201. ;output:
  1202. ; eax = strlen
  1203. align 4
  1204. tl_strlen:
  1205.         mov eax,esi
  1206.         @@:
  1207.                 cmp byte[eax],0
  1208.                 je @f
  1209.                 inc eax
  1210.                 jmp @b
  1211.         @@:
  1212.         sub eax,esi
  1213.         ret
  1214.  
  1215. ;добавить узел
  1216. ;input:
  1217. ; tlist - указатель на структуру листа
  1218. ; n_opt - опции добавления
  1219. ; n_info - указатель на добавляемые данные
  1220. align 4
  1221. proc tl_node_add uses eax ebx ecx edx edi, tlist:dword, n_opt:dword, n_info:dword
  1222.         mov edi,[tlist]
  1223.  
  1224.         call tl_info_set_undo
  1225.  
  1226.         mov ebx,sizeof.TreeNode
  1227.         imul ebx,tl_info_max_count
  1228.         add ebx,tl_data_nodes
  1229. ;--
  1230.         call tl_get_cur_node_index ;eax=po_t
  1231.         imul eax,sizeof.TreeNode
  1232.         add eax,tl_data_nodes
  1233.         mov edx,eax
  1234.         call tl_move_perv
  1235.         call tl_get_node_index ;eax = index of pointer [edx]
  1236. ;--
  1237.         mov edx,sizeof.TreeNode
  1238.         shl edx,1
  1239.         add edx,tl_data_nodes
  1240.         @@: ;for(i=2;i<nodeMax;i++)
  1241.                 cmp dword[edx+TreeNode.t_create],0
  1242.                 jne .u0
  1243.                 cmp dword[edx+TreeNode.t_delete],0
  1244.                 jne .u0
  1245.  
  1246.                 inc tl_ch_tim
  1247.                 mov ecx,dword[n_opt]
  1248.                 ror ecx,16 ;cx = type
  1249.                 mov word[edx+TreeNode.type],cx
  1250.                 rol ecx,8 ;cl = close|open
  1251.                 mov byte[edx+TreeNode.close],cl ;node[i].clo
  1252.                 mov byte[edx+TreeNode.level],0 ;node[i].lev=0
  1253.                 bt tl_style,2 ;tl_list_box_mode
  1254.                 jc .l_box_m
  1255.                         mov cl,byte[n_opt]
  1256.                         mov byte[edx+TreeNode.level],cl ;node[i].lev
  1257.                 .l_box_m:
  1258.                 push tl_ch_tim       ;node[i].tc=ch_tim;
  1259.                 pop dword[edx+TreeNode.t_create]
  1260.                 mov [edx+TreeNode.perv],eax ;node[i].perv=po_t;
  1261.                 ;*** copy node data ***
  1262.                 push esi
  1263.                 xor ecx,ecx
  1264.                 mov cx,tl_info_size
  1265.                 mov esi,ecx
  1266.  
  1267.                 push eax
  1268.                         call tl_get_node_index ;eax = node index
  1269.                         imul esi,eax
  1270.                 pop eax
  1271.                 add esi,tl_data_info
  1272.                 mov edi,dword[n_info] ;pointer to node data
  1273.                 xchg edi,esi
  1274.                 rep movsb
  1275.  
  1276.                 mov esi,edi
  1277.                 mov edi,[tlist] ;restore edi
  1278.                 mov cx,tl_info_capt_offs
  1279.                 cmp cx,tl_info_size
  1280.                 jge .no_text_data
  1281.                 cmp tl_info_capt_len,0 ;проверяем есть ли ограничение на длинну строки
  1282.                 je .no_len_ogran
  1283.                         add cx,tl_info_capt_len
  1284.                         and ecx,0xffff
  1285.                         add esi,ecx
  1286.                         mov cx,tl_info_size
  1287.                         sub esi,ecx
  1288.                 .no_len_ogran:
  1289.                 dec esi
  1290.                 mov byte[esi],0
  1291.                 .no_text_data:
  1292.                 pop esi ;restore esi
  1293.  
  1294.                 mov ecx,eax
  1295.                 imul ecx,sizeof.TreeNode
  1296.                 add ecx,tl_data_nodes ; *** ecx = node[po_t] ***
  1297.                 add ecx,TreeNode.next ; *** ecx = node[po_t].next ***
  1298.                 push dword[ecx] ;node[i].next=node[po_t].next;
  1299.                 pop dword[edx+TreeNode.next]
  1300.  
  1301.                 call tl_get_node_index ;*** eax = i ***
  1302.                 cmp eax,tl_info_max_count
  1303.                 jge .u0
  1304.                         mov [ecx],eax ;node[po_t].next=i; // ссылки перенаправляем
  1305.                         mov ecx,[edx+TreeNode.next] ; *** ecx = node[i].next ***
  1306.                         imul ecx,sizeof.TreeNode
  1307.                         add ecx,tl_data_nodes ; *** ecx = node[node[i].next] ***
  1308.                         mov [ecx+TreeNode.perv],eax ;node[node[i].next].perv=i;
  1309.  
  1310.                         call tb_scrol_resize ;обработка скроллинга
  1311.                         jmp @f
  1312.                 .u0:
  1313.                 add edx,sizeof.TreeNode
  1314.                 cmp edx,ebx ;enf of node memory ?
  1315.                 jle @b
  1316.         @@:
  1317.         ret
  1318. endp
  1319.  
  1320. ;input:
  1321. ; edi = pointer to TreeInfo struct
  1322. align 4
  1323. proc tb_scrol_resize uses eax ecx edx
  1324.         cmp tl_p_scroll,0 ;обработка скроллинга
  1325.         je @f
  1326.                 call tl_get_node_count ;eax = node count
  1327.                 mov ecx,eax
  1328.                 call tl_get_rows_count
  1329.                 cmp ecx,eax
  1330.                 jg .ye_sb
  1331.                         xor ecx,ecx
  1332.                 .ye_sb:
  1333.                 mov edx,tl_p_scroll
  1334.                 mov dword[edx+sb_offs_cur_area],eax
  1335.                 mov dword[edx+sb_offs_max_area],ecx
  1336.                 stdcall scroll_bar_vertical.draw,edx
  1337.         @@:
  1338.         ret
  1339. endp
  1340.  
  1341. ;input:
  1342. ;n_info - pointer to node info
  1343. align 4
  1344. proc tl_node_set_data uses eax ecx edx edi esi, tlist:dword, n_info:dword
  1345.         mov edi,[tlist]
  1346.         call tl_get_cur_node_index ;eax=po_t
  1347.         cmp eax,2
  1348.         jl @f
  1349.                 xor ecx,ecx
  1350.                 mov cx,tl_info_size
  1351.                 imul eax,ecx
  1352.                 add eax,tl_data_info
  1353.                 mov edi,eax
  1354.                 mov esi,dword[n_info] ;pointer to node data
  1355.                 rep movsb
  1356.  
  1357.                 mov esi,edi
  1358.                 mov edi,[tlist] ;restore edi
  1359.                 mov cx,tl_info_capt_offs
  1360.                 cmp cx,tl_info_size
  1361.                 jge .no_text_data
  1362.                         mov ax,tl_info_capt_len ;проверяем есть ли ограничение на длинну текста
  1363.                         or ax,ax
  1364.                         jz .no_limit
  1365.                                 add cx,ax ;cx = tl_info_capt_offs + tl_info_capt_len
  1366.                                 and ecx,0xffff
  1367.                                 xor eax,eax
  1368.                                 mov ax,tl_info_size
  1369.                                 cmp eax,ecx
  1370.                                 jl .no_limit ;пользователь задал слишком большую длинну текста
  1371.                                 add esi,ecx
  1372.                                 sub esi,eax
  1373.                         .no_limit:
  1374.                         dec esi
  1375.                         mov byte[esi],0 ;обнуляем последний символ подписи, что-бы не глючило если пользователь задал неправильную структуру
  1376.                 .no_text_data:
  1377.         @@:
  1378.         ret
  1379. endp
  1380.  
  1381. ;взять указатель на данные узла под курсором
  1382. ;input:
  1383. ; tlist - pointer to 'TreeList' struct
  1384. ;output:
  1385. ; eax - pointer to node data
  1386. align 4
  1387. proc tl_node_get_data uses ecx edi, tlist:dword
  1388.         mov edi,[tlist]
  1389.         call tl_get_cur_node_index ;eax=po_t
  1390.         cmp eax,2
  1391.         jl @f
  1392.                 movzx ecx,tl_info_size
  1393.                 imul eax,ecx
  1394.                 add eax,tl_data_info
  1395.                 jmp .end_f ;return node data pointer
  1396.         @@:
  1397.         xor eax,eax
  1398.         .end_f:
  1399.   ret
  1400. endp
  1401.  
  1402. ;взять указатель на структуру узла в указанной позиции
  1403. ;input:
  1404. ; tlist - pointer to 'TreeList' struct
  1405. ; node_ind - node index
  1406. ;output:
  1407. ; eax - pointer to node info
  1408. align 4
  1409. proc tl_node_poi_get_info uses ebx ecx edx edi, tlist:dword, node_ind:dword
  1410.         mov edi,[tlist]
  1411.         mov ebx,dword[node_ind]
  1412.  
  1413.         ;cycle to nodes
  1414.         mov edx,tl_data_nodes
  1415.         mov ecx,edx
  1416.         add ecx,sizeof.TreeNode
  1417.         @@:
  1418.                 call tl_iterat_next_all
  1419.                 cmp edx,ecx
  1420.                 jle @f
  1421.                 dec ebx
  1422.                 cmp ebx,0
  1423.                 jg @b
  1424.                 jmp .find
  1425.         @@:
  1426.                 xor edx,edx
  1427.         .find:
  1428.         mov eax,edx
  1429.         ret
  1430. endp
  1431.  
  1432. ;взять указатель на следущую структуру узла
  1433. ;input:
  1434. ; tlist - pointer to 'TreeList' struct
  1435. ; node_p - node param struct
  1436. ;output:
  1437. ; eax - pointer to next node struct
  1438. align 4
  1439. proc tl_node_poi_get_next_info uses ecx edx edi, tlist:dword, node_p:dword
  1440.         mov edi,[tlist]
  1441.         mov edx,dword[node_p]
  1442.  
  1443.         mov ecx,tl_data_nodes
  1444.         add ecx,sizeof.TreeNode
  1445.  
  1446.         call tl_iterat_next_all
  1447.         cmp edx,ecx
  1448.         jg @f
  1449.                 xor edx,edx
  1450.         @@:
  1451.         mov eax,edx
  1452.         ret
  1453. endp
  1454.  
  1455. ;взять указатель на данные узла
  1456. ;input:
  1457. ; tlist - pointer to 'TreeList' struct
  1458. ; node_p - node param struct
  1459. ;output:
  1460. ; eax - pointer
  1461. align 4
  1462. proc tl_node_poi_get_data uses ecx edx edi, tlist:dword, node_p:dword
  1463.         mov edi,[tlist]
  1464.         mov edx,dword[node_p]
  1465.  
  1466.         call tl_get_node_index ;eax = node index
  1467.         cmp eax,2
  1468.         jl @f
  1469.                 xor ecx,ecx
  1470.                 mov cx,tl_info_size
  1471.                 imul eax,ecx
  1472.                 add eax,tl_data_info
  1473.                 jmp .end_f ;return node data pointer
  1474.         @@:
  1475.                 xor eax,eax ;возвращаем 0 в случае не удачного поиска
  1476.         .end_f:
  1477.         ret
  1478. endp
  1479.  
  1480. ;берет позицию под курсором
  1481. ;input:
  1482. ; edi = pointer 'tl' struct
  1483. ;output:
  1484. ; eax = index of current node
  1485. align 4
  1486. proc tl_get_cur_node_index uses ecx edx
  1487.         ;cycle to nodes
  1488.         xor eax,eax
  1489.         mov edx,tl_data_nodes
  1490.         mov ecx,edx
  1491.         add ecx,sizeof.TreeNode
  1492.         @@:
  1493.                 call tl_iterat_next
  1494.                 cmp edx,ecx
  1495.                 jle @f
  1496.                 cmp eax,tl_cur_pos
  1497.                 je @f
  1498.                 inc eax
  1499.                 jmp @b
  1500.         @@:
  1501.         mov eax,edx
  1502.         sub eax,tl_data_nodes
  1503.         xor edx,edx
  1504.         mov ecx,sizeof.TreeNode
  1505.         div ecx
  1506.         ret
  1507. endp
  1508.  
  1509. ;берет позицию указанного символа
  1510. ;input:
  1511. ; edx = pointer node memory
  1512. ; edi = pointer 'tl' struct
  1513. ;output:
  1514. ; eax = struct index of current node
  1515. align 4
  1516. tl_get_node_index:
  1517.         push ecx edx
  1518.         mov eax,edx
  1519.         sub eax,tl_data_nodes
  1520.         xor edx,edx
  1521.         mov ecx,sizeof.TreeNode
  1522.         div ecx
  1523.         pop edx ecx
  1524.         ret
  1525.  
  1526. ;удалить узел
  1527. align 4
  1528. proc tl_node_delete uses eax edx edi, tlist:dword
  1529.         mov edi,[tlist]
  1530.         call tl_get_cur_node_index ;eax=po_t
  1531.         cmp eax,2
  1532.         jl @f
  1533.                 imul eax,sizeof.TreeNode
  1534.                 add eax,tl_data_nodes
  1535.                 mov edx,eax
  1536.                 inc tl_ch_tim
  1537.                 mov eax,tl_ch_tim
  1538.                 mov dword[edx+TreeNode.t_delete],eax
  1539.                 call tb_scrol_resize ;обработка скроллинга
  1540.         @@:
  1541.         ret
  1542. endp
  1543.  
  1544. ;поставить курсор на первый узел
  1545. align 4
  1546. proc tl_cur_beg uses edi, tlist:dword
  1547.         mov edi,[tlist]
  1548.         mov tl_cur_pos,0
  1549.         cmp tl_p_scroll,0
  1550.         je @f
  1551.                 mov edi,tl_p_scroll
  1552.                 mov dword[edi+sb_offs_position],0
  1553.                 stdcall scroll_bar_vertical.draw, edi
  1554.         @@:
  1555.         ret
  1556. endp
  1557.  
  1558. ;перенести курсор на 1 позицию ниже
  1559. align 4
  1560. proc tl_cur_next uses eax ebx edi esi, tlist:dword
  1561.         mov edi,[tlist]
  1562.         call tl_get_node_count ;eax = node count
  1563.         bt tl_style,3 ;tl_cursor_pos_limited
  1564.         jnc @f
  1565.         or eax,eax
  1566.         jz @f
  1567.                 dec eax ;если курсор стает на существующие узлы
  1568.         @@:
  1569.         cmp tl_cur_pos,eax
  1570.         jge .no_redraw
  1571.                 mov esi,tl_box_top
  1572.                 add esi,tl_box_height ;esi = coord bottom border
  1573.                 call tl_draw_null_cursor ;стираем курсор
  1574.                 inc tl_cur_pos
  1575.  
  1576.                 cmp tl_p_scroll,0 ;if not scrol struct
  1577.                 je @f
  1578.                 call tl_get_rows_count ;eax = rows count
  1579.                 mov ebx,tl_p_scroll
  1580.                 add eax,dword[ebx+sb_offs_position]
  1581.                 cmp tl_cur_pos,eax
  1582.                 jl @f
  1583.                         inc dword[ebx+sb_offs_position]
  1584.                         stdcall scroll_bar_vertical.draw,ebx
  1585.                         stdcall tl_draw,dword[tlist] ;полная перерисовка окна
  1586.                         jmp .no_redraw
  1587.                 @@:
  1588.                 mov edi,[tlist] ;restore edi
  1589.                 call tl_draw_cursor ;перерисовка курсора
  1590.                 call tl_draw_caption_cur_pos
  1591.         .no_redraw:
  1592.         ret
  1593. endp
  1594.  
  1595. ;берет число всех видимых узлов (не считая закрытых дочерних)
  1596. ;input:
  1597. ; edi = pointer 'tl' struct
  1598. ;output:
  1599. ; eax = struct index of current node
  1600. align 4
  1601. tl_get_node_count:
  1602. push ecx edx
  1603.         ;cycle to nodes
  1604.         xor eax,eax
  1605.         mov edx,tl_data_nodes
  1606.         mov ecx,edx
  1607.         add ecx,sizeof.TreeNode
  1608.         @@:
  1609.                 call tl_iterat_next
  1610.                 cmp edx,ecx
  1611.                 jle @f
  1612.                 inc eax
  1613.                 jmp @b
  1614.         @@:
  1615. pop edx ecx
  1616.         ret
  1617.  
  1618. ;берет число всех видимых узлов (считая закрытые дочерние)
  1619. ;input:
  1620. ; edi = pointer 'tl' struct
  1621. ;output:
  1622. ; eax = struct index of current node
  1623. align 4
  1624. tl_get_node_count_all:
  1625. push ecx edx
  1626.         ;cycle to nodes
  1627.         xor eax,eax
  1628.         mov edx,tl_data_nodes
  1629.         mov ecx,edx
  1630.         add ecx,sizeof.TreeNode
  1631.         @@:
  1632.                 call tl_iterat_next_all
  1633.                 cmp edx,ecx
  1634.                 jle @f
  1635.                 inc eax
  1636.                 jmp @b
  1637.         @@:
  1638. pop edx ecx
  1639.         ret
  1640.  
  1641. ;перенести курсор на 1 позицию выше
  1642. align 4
  1643. proc tl_cur_perv uses eax edi esi, tlist:dword
  1644.         mov edi,[tlist]
  1645.         cmp tl_cur_pos,0
  1646.         je .no_redraw
  1647.                 mov esi,tl_box_top
  1648.                 add esi,tl_box_height ;esi = coord bottom border
  1649.                 call tl_draw_null_cursor ;стираем курсор
  1650.                 dec tl_cur_pos ;двигаем курсор вверх
  1651.  
  1652.                 cmp tl_p_scroll,0 ;если есть указатель на скроллинг
  1653.                 je @f
  1654.                 mov eax,tl_p_scroll
  1655.                 cmp dword[eax+sb_offs_position],0 ;если скроллинг на верху, выходим
  1656.                 je @f
  1657.                 mov edi,tl_cur_pos
  1658.                 cmp edi,dword[eax+sb_offs_position] ;если курсор ушел выше скроллинга, тогда опускаем скроллинг
  1659.                 jge @f
  1660.                         dec dword[eax+sb_offs_position]
  1661.                         stdcall scroll_bar_vertical.draw, eax
  1662.                         stdcall tl_draw, dword[tlist] ;полная перерисовка окна
  1663.                         jmp .no_redraw
  1664.                 @@:
  1665.                         mov edi,[tlist] ;restore edi
  1666.                         call tl_draw_cursor ;перерисовка курсора
  1667.                         call tl_draw_caption_cur_pos
  1668.         .no_redraw:
  1669.         ret
  1670. endp
  1671.  
  1672. ;перенести курсор на 1 страницу выше
  1673. align 4
  1674. proc tl_cur_page_up uses eax edi esi, tlist:dword
  1675.         mov edi,[tlist]
  1676.  
  1677.         cmp tl_p_scroll,0 ;если есть указатель на скроллинг
  1678.         je .no_redraw
  1679.                 mov esi,tl_p_scroll
  1680.                 call tl_get_rows_count ;eax = rows count
  1681.  
  1682.                 cmp tl_cur_pos,0
  1683.                 jne @f
  1684.                 cmp dword[esi+sb_offs_position],0 ;если скроллинг на верху, выходим
  1685.                 jne @f
  1686.                         jmp .no_redraw
  1687.                 @@:
  1688.                 cmp tl_cur_pos,eax ;проверяем позицию курсора и кол-во сток на странице
  1689.                 jl @f ;если меньше, то приравниваем к 0, что-бы не отнять больше чем надо
  1690.                         sub tl_cur_pos,eax
  1691.                         jmp .cursor
  1692.                 @@:
  1693.                         mov tl_cur_pos,0
  1694.                 .cursor:
  1695.                 cmp dword[esi+sb_offs_position],eax
  1696.                 jl @f
  1697.                         sub dword[esi+sb_offs_position],eax
  1698.                         jmp .scroll
  1699.                 @@:
  1700.                 mov dword[esi+sb_offs_position],0
  1701.                 .scroll:
  1702.                 ;перерисовки окна и скроллинга
  1703.                 stdcall tl_draw, edi ;draw window
  1704.                 stdcall scroll_bar_vertical.draw, esi
  1705.         .no_redraw:
  1706.         ret
  1707. endp
  1708.  
  1709. ;перенести курсор на 1 страницу ниже
  1710. align 4
  1711. proc tl_cur_page_down uses eax ebx ecx edi esi, tlist:dword
  1712. ;eax - кол-во строк на странице
  1713. ;ebx - макс. позиция курсора
  1714. ;ecx - макс. позиция скроллинга
  1715.         mov edi,[tlist]
  1716.         cmp tl_p_scroll,0 ;если есть указатель на скроллинг
  1717.         je .no_redraw
  1718.                 mov esi,tl_p_scroll
  1719.                 call tl_get_node_count ;eax = node count
  1720.                 bt tl_style,3 ;tl_cursor_pos_limited
  1721.                 jnc @f
  1722.                 or eax,eax
  1723.                 jz @f
  1724.                         dec eax ;если курсор стает на существующие узлы
  1725.                 @@:
  1726.                 mov ebx,eax
  1727.                 call tl_get_rows_count ;eax = rows count
  1728.  
  1729.                 mov ecx,ebx
  1730.                 inc ecx ;если нижний узел виден на половину
  1731.                 cmp ecx,eax ;if (ecx>eax) { ecx=ecx-eax } else { ecx=0 }
  1732.                 jl @f
  1733.                         sub ecx,eax ;уменьшаем максимальную позицию скроллинга, так что-бы были видны последние узлы
  1734.                         jmp .control
  1735.                 @@:
  1736.                         xor ecx,ecx ;ecx=0 - все узлы влазят в экран, скроллинг не нужен
  1737.                 .control:
  1738.  
  1739.                 cmp tl_cur_pos,ebx ;курсор внизу ?
  1740.                 jl @f
  1741.                 cmp dword[esi+sb_offs_position],ecx ;скроллинг внизу ?
  1742.                 jl @f
  1743.                         jmp .no_redraw
  1744.                 @@:
  1745.                 add tl_cur_pos,eax ;перемещаем курсор
  1746.                 cmp tl_cur_pos,ebx
  1747.                 jl @f
  1748.                         mov tl_cur_pos,ebx
  1749.                 @@:
  1750.                 add dword[esi+sb_offs_position],eax ;перемещаем скроллинг
  1751.                 cmp dword[esi+sb_offs_position],ecx
  1752.                 jl @f
  1753.                         mov dword[esi+sb_offs_position],ecx
  1754.                 @@:
  1755.  
  1756.                 ;перерисовки окна и скроллинга
  1757.                 stdcall tl_draw, edi ;draw window
  1758.                 stdcall scroll_bar_vertical.draw, esi
  1759.         .no_redraw:
  1760.         ret
  1761. endp
  1762.  
  1763. ;открыть/закрыть узел (работает с узлами которые имеют дочерние узлы)
  1764. align 4
  1765. proc tl_node_close_open uses eax edx edi, tlist:dword
  1766.         mov edi,[tlist]
  1767.         call tl_get_cur_node_index ;eax = позиция узла на котором стоит курсор
  1768.         cmp eax,2 ;курсор стоит на узле ?
  1769.         jl @f
  1770.                 imul eax,sizeof.TreeNode
  1771.                 add eax,tl_data_nodes
  1772.                 ;eax = указатель на структуру узла выбранного курсором
  1773.                 push eax
  1774.                         stdcall tl_node_poi_get_next_info, edi,eax
  1775.                         mov edx,eax ;edx = указатель на структуру узла который идет после узла eax
  1776.                 pop eax
  1777.                 or edx,edx ;есть ли узлы ниже выбранного нами ?
  1778.                 jz @f
  1779.                         mov dl,byte[edx+TreeNode.level] ;берем уровень нижнего узла
  1780.                         cmp byte[eax+TreeNode.level],dl
  1781.                         jge @f ;если нижние узлы меньшего уровня, значит они не дочерние, конец функции
  1782.                                 xor byte[eax+TreeNode.close],1 ;*** открытие/закрытие узла ***
  1783.                                 call tb_scrol_resize ;обработка скроллинга
  1784.  
  1785.                                 stdcall tl_draw, edi ;обновление окна
  1786.         @@:
  1787.         ret
  1788. endp
  1789.  
  1790. ;увеличить уровень
  1791. align 4
  1792. proc tl_node_lev_inc uses eax ecx edx edi, tlist:dword
  1793.         mov edi,[tlist]
  1794.         bt tl_style,2 ;tl_list_box_mode
  1795.         jc @f
  1796.         call tl_get_cur_node_index ;eax=po_t
  1797.         cmp eax,2
  1798.         jl @f
  1799.                 mov ecx,tl_data_nodes
  1800.                 imul eax,sizeof.TreeNode
  1801.                 add eax,ecx ;eax = pointer to node struct
  1802.                 add ecx,sizeof.TreeNode ;ecx = pointer to 1 node struct
  1803.  
  1804.                 mov edx,eax
  1805.                 call tl_iterat_perv ;проверяем есть ли верхний узел
  1806.                 cmp edx,ecx
  1807.                 jle @f ;если верхнего узла нет то текущий узел не двигаем
  1808.                 mov cl,byte[edx+TreeNode.level] ;берем уровень родительского узла
  1809.                 inc cl ;добавляем 1 и получаем максимальное значение
  1810.                 cmp byte[eax+TreeNode.level],cl
  1811.                 jge @f
  1812.                         inc byte[eax+TreeNode.level] ;увеличиваем значение узла
  1813.         @@:
  1814.         ret
  1815. endp
  1816.  
  1817. ;уменьшить уровень
  1818. align 4
  1819. proc tl_node_lev_dec uses eax edi, tlist:dword
  1820.         mov edi,[tlist]
  1821.         call tl_get_cur_node_index ;eax=po_t
  1822.         cmp eax,2
  1823.         jl @f
  1824.                 imul eax,sizeof.TreeNode
  1825.                 add eax,tl_data_nodes
  1826.                 cmp byte[eax+2],0
  1827.                 je @f
  1828.                 dec byte[eax+2]
  1829.         @@:
  1830.         ret
  1831. endp
  1832.  
  1833. ;перемещаем узел вверх
  1834. align 4
  1835. proc tl_node_move_up tlist:dword
  1836. pushad
  1837.         mov edi,[tlist]
  1838.         call tl_get_cur_node_index ;eax=po_t
  1839.         cmp eax,2
  1840.         jl @f
  1841.                 mov ebx,eax ;copy index of node struct
  1842.                 mov edx,tl_data_nodes
  1843.                 mov ecx,edx
  1844.                 add ecx,sizeof.TreeNode
  1845.                 imul eax,sizeof.TreeNode
  1846.                 add eax,edx ;eax = pointer to 2 node struct
  1847.                 mov edx,eax ;edx = pointer to 2 node struct
  1848.                 mov esi,eax ;esi = pointer to 2 node struct
  1849.                 call tl_iterat_perv ;edx = pointer to 1 node struct
  1850.                 call tl_get_node_index ;eax = index of 1 node struct
  1851.                 cmp edx,ecx
  1852.                 jle @f
  1853.                         cmp dword[edx+TreeNode.next],ebx
  1854.                         jne .po8
  1855.                                 call tl_node_move_po6 ;узлы идут подряд меняем 6 ссылок
  1856.                                 jmp .cur_mov
  1857.                         .po8:
  1858.                                 call tl_node_move_po8 ;узлы идут не подряд меняем 8 ссылок
  1859.                         .cur_mov:
  1860.                                 push dword edi
  1861.                                 call tl_cur_perv
  1862.                                 push dword edi
  1863.                                 call tl_draw
  1864.         @@:
  1865. popad
  1866.         ret
  1867. endp
  1868.  
  1869. ;перемещаем узел вниз
  1870. align 4
  1871. proc tl_node_move_down tlist:dword
  1872. pushad
  1873.         mov edi,[tlist]
  1874.         call tl_get_cur_node_index ;eax=po_t
  1875.         cmp eax,2
  1876.         jl @f
  1877.                 mov ebx,eax ;copy index of node struct
  1878.                 mov edx,tl_data_nodes
  1879.                 mov ecx,edx
  1880.                 add ecx,sizeof.TreeNode
  1881.                 imul eax,sizeof.TreeNode
  1882.                 add eax,edx ;eax = pointer to 1 node struct
  1883.                 mov edx,eax ;edx = pointer to 1 node struct
  1884.                 mov esi,eax ;esi = pointer to 1 node struct
  1885.                 call tl_iterat_next ;edx = pointer to 2 node struct
  1886.                 call tl_get_node_index ;eax = index of 2 node struct
  1887.                 cmp edx,ecx
  1888.                 jle @f
  1889.                         cmp dword[esi+TreeNode.next],eax
  1890.                         jne .po8
  1891.                                 xchg eax,ebx ;меняе порядок следования заменяемых узлов
  1892.                                 xchg edx,esi
  1893.                                 call tl_node_move_po6 ;узлы идут подряд меняем 6 ссылок
  1894.                                 jmp .cur_mov
  1895.                         .po8: ;а тут порядок следования узлов не меняем
  1896.                                 call tl_node_move_po8 ;узлы идут не подряд меняем 8 ссылок
  1897.                         .cur_mov:
  1898.                                 stdcall tl_cur_next, edi
  1899.                                 stdcall tl_draw, edi
  1900.         @@:
  1901.         ret
  1902. popad
  1903. endp
  1904.  
  1905. align 4
  1906. tl_node_move_po6:
  1907.         mov ecx,edx ;save node pointer
  1908.         call tl_move_perv
  1909.         mov dword[edx+TreeNode.next],ebx
  1910.  
  1911.         mov edx,esi
  1912.         call tl_move_next
  1913.         mov dword[edx+TreeNode.perv],eax
  1914.         mov edx,ecx ;restore node pointer
  1915.  
  1916.         mov ecx,dword[edx+TreeNode.perv]
  1917.         mov dword[esi+TreeNode.perv],ecx
  1918.         mov ecx,dword[esi+TreeNode.next]
  1919.         mov dword[edx+TreeNode.next],ecx
  1920.  
  1921.         mov dword[edx+TreeNode.perv],ebx
  1922.         mov dword[esi+TreeNode.next],eax
  1923.         ret
  1924.  
  1925. ;input
  1926. ;eax = index 1 node struct
  1927. ;ebx = index 2 node struct
  1928. ;edx = pointer 1 node struct
  1929. ;esi = pointer 2 node struct
  1930. ;edi = pointer to 'TreeList' struct
  1931. ;output:
  1932. ;eax = ?
  1933. ;ebx = ?
  1934. ;ecx = ?
  1935. align 4
  1936. tl_node_move_po8:
  1937.         mov ecx,edx ;save node pointer
  1938.         call tl_move_perv
  1939.         mov dword[edx+TreeNode.next],ebx
  1940.         mov edx,ecx
  1941.         call tl_move_next
  1942.         mov dword[edx+TreeNode.perv],ebx
  1943.         mov edx,esi
  1944.         call tl_move_perv
  1945.         mov dword[edx+TreeNode.next],eax
  1946.         mov edx,esi
  1947.         call tl_move_next
  1948.         mov dword[edx+TreeNode.perv],eax
  1949.         mov edx,ecx ;restore node pointer
  1950.  
  1951.         mov eax,dword[edx+TreeNode.perv]
  1952.         mov ebx,dword[esi+TreeNode.perv]
  1953.         xchg eax,ebx
  1954.         mov dword[edx+TreeNode.perv],eax
  1955.         mov dword[esi+TreeNode.perv],ebx
  1956.  
  1957.         mov eax,dword[edx+TreeNode.next]
  1958.         mov ebx,dword[esi+TreeNode.next]
  1959.         xchg eax,ebx
  1960.         mov dword[edx+TreeNode.next],eax
  1961.         mov dword[esi+TreeNode.next],ebx
  1962.         ret
  1963.  
  1964. ;input:
  1965. ; edi = pointer to 'TreeList' struct
  1966. align 4
  1967. tl_draw_caption_cur_pos:
  1968.         cmp tl_capt_cy,9 ;9 - minimum caption height
  1969.         jl @f
  1970.         pushad
  1971.                 mov ebx,edi ;calculate cursor position
  1972.                 mov eax,tl_cur_pos
  1973.                 inc eax
  1974.                 lea edi,[txt_capt_cur.v]
  1975.                 stdcall tl_convert_to_str, 5
  1976.                 mov edi,ebx
  1977.  
  1978.                 mov ebx,tl_box_left
  1979.                 shl ebx,16
  1980.                 add ebx,5*65536+3
  1981.                 add ebx,tl_box_top
  1982.                 mov ecx,tl_col_txt
  1983.                 or  ecx,0xc0000000 ;0x40000000 закрашивать фон цветом edi
  1984.                 lea edx,[txt_capt_cur]
  1985.                 mov edi,tl_col_zag
  1986.                 mcall SF_DRAW_TEXT ;captions
  1987.         popad
  1988.         @@:
  1989.         ret
  1990.  
  1991. ;input:
  1992. ; tlist - pointer to 'TreeList' struct
  1993. ; opt - options: 0 - first element, 1 - add next element
  1994. ; h_mem - pointer to memory
  1995. ; mem_size - memory size
  1996. ;output:
  1997. ; eax - error code
  1998. align 4
  1999. proc tl_save_mem uses ebx ecx edx edi esi, tlist:dword, opt:dword, h_mem:dword, mem_size:dword
  2000.         mov esi,[h_mem]
  2001.         mov edi,[tlist]
  2002.  
  2003.         cmp dword[opt],0 ;add mode
  2004.         je @f
  2005.                 stdcall tl_get_mem_size, edi,esi ;eax = размер ранее сохранённых данных
  2006.                 add esi,eax
  2007.         @@:
  2008.  
  2009.         xor ebx,ebx
  2010.         mov bx,tl_info_size
  2011.  
  2012.         call tl_get_node_count_all ;eax = all node count
  2013.  
  2014.         mov ecx,eax  ;вычисляем сколько памяти должно быть заполнено
  2015.         imul ecx,ebx ;умножаем на размер структуры узла
  2016.         add ecx,tl_save_load_heder_size+1 ;element header +1 end element sumbol
  2017.         add ecx,esi  ;добавляем указатель на начало памяти (с учетом ранее записанных структур)
  2018.         sub ecx,dword[h_mem] ;отнимаем указатель на начало памяти (без ранее записанных структур)
  2019.         cmp ecx,dword[mem_size] ;ecx = element memory size
  2020.         jg .err_mem_size
  2021.  
  2022.                 ;save tree params (in header)
  2023.                 mov dword[esi],'tree'
  2024.                 mov word[esi+4],bx
  2025.                 mov dword[esi+6],eax ;element count
  2026.  
  2027.                 mov eax,tl_style
  2028.                 mov dword[esi+10],eax
  2029.  
  2030.                 mov eax,tl_cur_pos
  2031.                 mov dword[esi+14],eax
  2032.  
  2033.                 mov ax,tl_info_capt_offs
  2034.                 mov word[esi+18],ax
  2035.  
  2036.                 mov ax,tl_info_capt_len
  2037.                 mov word[esi+20],ax
  2038.  
  2039.                 ;copy scroll position
  2040.                 mov edx,tl_p_scroll
  2041.                 mov eax,dword[edx+sb_offs_position]
  2042.                 mov dword[esi+22],eax
  2043.  
  2044.                 add esi,tl_save_load_heder_size ;add header size
  2045.  
  2046.                 ;cycle to nodes
  2047.                 mov edx,tl_data_nodes
  2048.                 mov ecx,edx
  2049.                 add ecx,sizeof.TreeNode
  2050.                 @@:
  2051.                         call tl_iterat_next_all
  2052.                         cmp edx,ecx
  2053.                         jle @f
  2054.                 ;save node params
  2055.                 call tl_get_node_index ;eax = index of pointer [edx]
  2056.                 mov dword[esi],eax
  2057.  
  2058.                 add esi,4
  2059.                 mov eax,dword[edx+TreeNode.type] ;eax = (type; level; close)
  2060.                 mov dword[esi],eax
  2061.                 add esi,4
  2062.  
  2063.                         stdcall tl_node_poi_get_data, edi,edx ;eax - pointer node data
  2064.  
  2065.                 ;call tl_node_copy_data
  2066.                 push ecx edi
  2067.                 mov edi,eax
  2068.                 mov ecx,ebx
  2069.                 xchg esi,edi
  2070.                 rep movsb
  2071.                 mov esi,edi
  2072.                 pop edi ecx
  2073.                 ;add esi,ebx
  2074.                 jmp @b
  2075.         @@:
  2076.         mov byte[esi],0 ;end of 'treelist'
  2077.                 xor eax,eax ;return error code
  2078.         jmp @f
  2079.         .err_mem_size:
  2080.                 mov eax,tl_err_save_memory_size
  2081.         @@:
  2082.         ret
  2083. endp
  2084.  
  2085. ;input:
  2086. ; tlist - pointer to 'TreeList' struct
  2087. ; opt   - options: element index + (2*(add mode)+(init mode)) shl 16
  2088. ; h_mem - pointer to memory
  2089. ; mem_size - memory size
  2090. ;   размер памяти, пока не используется (назначался для контроля)
  2091. ;   для его использования нужно доработать функцию
  2092. ;output:
  2093. ; eax - error code
  2094. ;memory header format:
  2095. ;  +0 - (4) 'tree'
  2096. ;  +4 - (2) info size
  2097. ;  +6 - (4) count nodes
  2098. ; +10 - (4) tlist style
  2099. ; +14 - (4) cursor pos
  2100. ; +18 - (2) info capt offs
  2101. ; +20 - (2) info capt len
  2102. ; +22 - (4) scroll pos
  2103. ;memory data format:
  2104. ; +26 - (info size + 8) * count nodes
  2105. align 4
  2106. proc tl_load_mem uses ebx ecx edx edi esi, tlist:dword, opt:dword, h_mem:dword, mem_size:dword
  2107. locals
  2108.         er_code dd ?
  2109. endl
  2110.         mov esi,[h_mem]
  2111.         mov edi,[tlist]
  2112.  
  2113.         mov dword[er_code],0 ;return error code
  2114.  
  2115.         mov ecx,[opt]
  2116.         or cx,cx ;load in array mode
  2117.         jz @f
  2118.                 ;stdcall tl_get_mem_size, esi,edi ;берем размер ранее сохранённых данных
  2119.                 ;add esi,eax
  2120.                 and ecx,0xffff
  2121.                 cld
  2122.                 .beg_cycle:
  2123.                         cmp dword[esi],'tree'
  2124.                         jne .no_tree
  2125.                         movzx ebx,word[esi+4]
  2126.                         add bx,8
  2127.                         imul ebx,dword[esi+6]
  2128.                         add ebx,tl_save_load_heder_size
  2129.                         add esi,ebx
  2130.                         loop .beg_cycle
  2131.         @@:
  2132.  
  2133.         cmp dword[esi],'tree'
  2134.         jne .no_tree
  2135.                 bt dword[opt],17 ;load in add mode
  2136.                 jc @f
  2137.                         stdcall tl_info_clear, edi
  2138.                 @@:
  2139.  
  2140.                 xor ebx,ebx
  2141.                 mov bx,word[esi+4] ;info_size
  2142.                 cmp bx,tl_info_size
  2143.                 je @f
  2144.                         or dword[er_code],tl_err_load_info_size
  2145.                 @@:
  2146.                 mov ecx,[esi+6] ;count nodes
  2147.                 cmp ecx,1
  2148.                 jl .end_f
  2149.                 mov edx,esi ;save header pointer
  2150.                 add esi,tl_save_load_heder_size
  2151.  
  2152.                 cld
  2153.                 @@: ;load node params
  2154.                         mov eax,dword[esi+4]
  2155.                         ror eax,16 ;eax - options (type; level; close)
  2156.                         add esi,8
  2157.                         stdcall tl_node_add, edi,eax,esi
  2158.                         stdcall tl_cur_next, edi
  2159. ;...
  2160.                         add esi,ebx
  2161.                         loop @b
  2162.  
  2163.                 bt dword[opt],17 ;load in add mode
  2164.                 jc .no_tree
  2165.                         mov eax,dword[edx+14] ;set cursor pos
  2166.                         mov tl_cur_pos,eax
  2167.                         mov ebx,tl_p_scroll
  2168.                         or ebx,ebx
  2169.                         jz .end_f
  2170.                                 mov eax,dword[edx+22] ;set scroll pos
  2171.                                 mov dword[ebx+sb_offs_position],eax
  2172.                                 stdcall scroll_bar_vertical.draw, ebx
  2173.                                 jmp .end_f
  2174.         .no_tree:
  2175.         mov dword[er_code],tl_err_load_caption
  2176.         .end_f:
  2177.         mov eax,dword[er_code]
  2178.         ret
  2179. endp
  2180.  
  2181. ;берет размер памяти занятой функцией tl_save_mem при сохранении элементов
  2182. ;output:
  2183. ; eax - error code
  2184. align 4
  2185. proc tl_get_mem_size uses ebx edi, tlist:dword, h_mem:dword
  2186.         mov edi,[tlist]
  2187.         mov eax,[h_mem]
  2188.         @@:
  2189.                 cmp dword[eax],'tree'
  2190.                 jne @f
  2191.                 xor ebx,ebx
  2192.                 mov bx,word[eax+4]
  2193.                 add bx,8 ;размер дополнительной информации об узле (индекс записи; индекс иконки, уровень, ...)
  2194.                 imul ebx,dword[eax+6]
  2195.                 add ebx,tl_save_load_heder_size
  2196.                 add eax,ebx
  2197.                 jmp @b
  2198.         @@:
  2199.         sub eax,dword[h_mem] ;отнимаем указатель на начало памяти
  2200.                 ;и получаем размер блока памяти
  2201.         ret
  2202. endp
  2203.  
  2204.  
  2205. ;ascii scan key
  2206. ;  13    28 Enter
  2207. ;  32    57 Space
  2208. ; 178    72 Up
  2209. ; 177    80 Down
  2210. ; 176    75 Left
  2211. ; 179    77 Right
  2212. ; 182    83 Delete
  2213. ; 184    73 Pg Up
  2214. ; 183    81 Pg Dn
  2215.  
  2216. tl_key_ascii db 13,32,178,177,176,179,182,184,183
  2217. tl_key_scan  db 28,57, 72, 80, 75, 77, 83, 73, 81
  2218.  
  2219. txt_capt_cur: db 'Строка '
  2220. .v: db '     ',0
  2221. txt_capt_otm: db 'Отмены '
  2222. .v: db '     ',0
  2223.  
  2224. ;description:
  2225. ; преревод числа в ASCII строку
  2226. ;input:
  2227. ; eax = value
  2228. ; edi = string buffer
  2229. align 4
  2230. proc tl_convert_to_str, len:dword
  2231. pushad
  2232.         mov esi,[len]
  2233.         add esi,edi
  2234.         dec esi
  2235.         call .str
  2236. popad
  2237.         ret
  2238. endp
  2239.  
  2240. align 4
  2241. .str:
  2242.         mov ecx,10 ;задается система счисления
  2243.         cmp eax,ecx  ;сравнить если в eax меньше чем в ecx то перейти на @@-1 т.е. на pop eax
  2244.         jb @f
  2245.                 xor edx,edx ;очистить edx
  2246.                 div ecx     ;разделить - остаток в edx
  2247.                 push edx    ;положить в стек
  2248.                 call .str   ;вызвать саму себя и так до того момента пока в eax не станет меньше чем в ecx
  2249.                 pop eax
  2250.         @@:
  2251.         cmp edi,esi
  2252.         jge @f
  2253.                 or al,0x30  ;добавляем символ '0'
  2254.                 stosb       ;записать al в ячеку памяти [edi]
  2255.                 mov byte[edi],0
  2256.         @@:
  2257.         ret
  2258.