kolibrios/programs/develop/libraries/box_lib/trunk/tree_list.mac
IgorA 47a9023a5f 'tree_list' optimize code
git-svn-id: svn://kolibrios.org@5879 a494cfbc-eb01-0410-851d-a64ba20cac60
2015-11-04 00:39:02 +00:00

2274 lines
52 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; макрос для системной библиотеки box_lib.obj
; элемент TreeList для Kolibri OS
; файл последний раз изменялся 04.11.2015 IgorA
; на код применена GPL2 лицензия
sizeof.TreeList equ 20
;struct TreeList
; type dw ? ;+ 0 тип элемента, или индекс иконки для узла
; lev db ? ;+ 2 уровень элемента
; clo db ? ;+ 3 флаг закрытия, или открытия (имеет смысл для родительского узла)
; perv dd ? ;+ 4 индекс предыдущего элемента
; next dd ? ;+ 8 индекс последующего элемента
; tc dd ? ;+12 врем. создания
; td dd ? ;+16 врем. удаления
;ends
macro use_tree_list
{
;выделние памяти для структур списка и основной информации (конструктор)
align 4
proc tl_data_init uses eax ecx edi, tlist:dword
mov edi,dword[tlist]
xor ecx,ecx
mov cx,tl_info_size
imul ecx,tl_info_max_count
invoke mem.alloc,ecx
mov tl_data_info,eax ;копируем указатель на полученую память в структуру
mov tl_data_img,0 ;обнуляем указатель 'data_img'
mov tl_data_img_sys,0 ;обнуляем указатель 'data_img_sys'
mov ecx,sizeof.TreeList
imul ecx,tl_info_max_count
invoke mem.alloc,ecx
mov tl_data_nodes,eax ;копируем указатель на полученую память в структуру
stdcall tl_info_clear, edi
;настройки дочернего скроллинга
cmp tl_p_scrol,0
je @f
mov eax,tl_p_scrol
;*** цветовые настройки ***
mov ecx,tl_col_bkg
mov dword[eax+sb_offs_bckg_col],ecx
mov ecx,tl_col_zag
mov dword[eax+sb_offs_frnt_col],ecx
mov ecx,tl_col_txt
mov dword[eax+sb_offs_line_col],ecx
;*** настройки размеров ***
mov ecx,tl_box_left
add ecx,tl_box_width
mov word[eax+2],cx
mov ecx,tl_box_height
mov word[eax+4],cx
mov ecx,tl_box_top
mov word[eax+6],cx
@@:
ret
endp
;очистка памяти элемента (деструктор)
align 4
proc tl_data_clear uses edi, tlist:dword
;uses eax ???
mov edi,dword[tlist]
cmp tl_data_img,0
je @f
invoke mem.free,tl_data_img ;чистка системных иконок
@@:
cmp tl_data_img_sys,0
je @f
invoke mem.free,tl_data_img_sys ;чистка системных иконок
@@:
invoke mem.free,tl_data_info
invoke mem.free,tl_data_nodes
ret
endp
;очистка списка (информации)
align 4
proc tl_info_clear uses eax ecx edi, tlist:dword
mov edi,dword[tlist]
mov tl_ch_tim,0
mov dword[edi+34],0 ;ls_tim
mov tl_tim_undo,0
mov tl_cur_pos,0
mov ecx,sizeof.TreeList
imul ecx,tl_info_max_count
mov eax,tl_data_nodes
@@:
mov byte[eax],0 ;чистим узлы 0-ми
inc eax
loop @b
mov eax,tl_data_nodes ;указатель на 0-й узел
mov dword[eax+8],1 ;указатель next в 0-м узле приравниваем к 1
cmp tl_p_scrol,0 ;обработка скроллинга
je @f
mov eax,tl_p_scrol
mov dword[eax+sb_offs_position],0
call tb_scrol_resize
@@:
ret
endp
;реакция на клавиатуру
align 4
proc tl_key uses ebx ecx edi, tlist:dword
mov edi,dword[tlist]
mov ebx,tl_el_focus
cmp dword[ebx],edi
jne .no_focus ;элемент не в фокусе
push eax
mcall 66,2 ;получить режим ввода с клавиатуры
lea ecx,[tl_key_scan]
cmp eax,1 ;1 = сканкоды
je @f
lea ecx,[tl_key_ascii]
@@:
pop eax
xor bx,bx
cmp ah,byte[ecx] ;Enter
jne @f
cmp tl_on_press,0
je @f
call tl_on_press
@@:
cmp ah,byte[ecx+1] ;Space
jne @f
stdcall tl_node_close_open, edi
@@:
cmp ah,byte[ecx+2] ;Up
jne @f
stdcall tl_cur_perv, edi
@@:
cmp ah,byte[ecx+3] ;Down
jne @f
stdcall tl_cur_next, edi
@@:
cmp ah,byte[ecx+7] ;Page Up
jne @f
stdcall tl_cur_page_up, edi
@@:
cmp ah,byte[ecx+8] ;Page Down
jne @f
stdcall tl_cur_page_down, edi
@@:
bt tl_style,0 ;tl_key_no_edit
jc .no_edit
cmp ah,byte[ecx+4] ;Left
jne @f
stdcall tl_node_lev_dec, edi
mov bx,1
@@:
cmp ah,byte[ecx+5] ;Right
jne @f
stdcall tl_node_lev_inc, edi
mov bx,1
@@:
cmp ah,byte[ecx+6] ;Delete
jne @f
stdcall tl_node_delete, edi
mov bx,1
@@:
.no_edit:
cmp bx,1
jne .no_focus
stdcall tl_draw, edi
.no_focus:
ret
endp
;реакция на мышь
align 4
proc tl_mouse, tlist:dword
pushad
mov edi,dword[tlist]
mcall 37,1 ;координаты мыши относительно окна
mov ebx,tl_box_left
shl ebx,16
cmp eax,ebx ;левая граница окна
jl .no_in_wnd ;.test_scroll не применяем
shr ebx,16
add ebx,tl_box_width
shl ebx,16
cmp eax,ebx ;правая граница окна
jg .test_scroll
mov ebx,tl_box_top
add ebx,tl_box_height
cmp ax,bx ;нижняя граница окна
jg .test_scroll
sub ebx,tl_box_height
add bx,tl_capt_cy
cmp ax,bx ;верхняя граница окна + высота подписи
jl .test_scroll
push eax ebx
mcall 37,2
bt eax,0 ;left mouse button press
pop ebx eax
jae .no_draw
mov esi,tl_el_focus
mov dword[esi],edi ;set focus
; if '+' or '-' press
mov esi,eax
shr esi,16
sub esi,tl_box_left ;esi = mouse x coord in element window
and eax,0xffff
sub ax,bx
xor edx,edx
xor ecx,ecx
mov cx,tl_img_cy
div ecx
cmp tl_p_scrol,0 ;учитываем скроллинг
je @f
mov edx,tl_p_scrol
add eax,dword[edx+sb_offs_position] ;добавляем скроллинг на верху
@@:
mov ecx,eax
call tl_get_node_count ;eax = node count
cmp eax,ecx
jl @f
mov eax,ecx ;если курсор не вышел за пределы узлов, восстанавливаем старое значение eax
@@:
cmp eax,tl_cur_pos ;если новое значение курсора совпало с предыдущим
je @f ;то не стираем курсор
push esi
mov esi,tl_box_top
add esi,tl_box_height ;esi = coord bottom border
call tl_draw_null_cursor ;стираем курсор
pop esi
@@:
mov tl_cur_pos,eax
; if '+' or '-' press
call tl_get_cur_node_index ;eax = node index
cmp eax,2
jl .no_open_close ;курсор стоит на пустом месте, без узлов
imul eax,sizeof.TreeList
add eax,tl_data_nodes
xor bx,bx
mov bl,byte[eax+2] ;+2 lev сохраняем уровень текущего узла
inc bx ;+ поле для курсора
cmp si,tl_img_cx
jl .no_open_close ;мышей попали на левое поле для курсора, где точно нет '+' и '-'
mov eax,esi
xor edx,edx
xor ecx,ecx
mov cx,tl_img_cx
div ecx
cmp ax,bx
jne .no_open_close
stdcall tl_node_close_open, edi
.no_open_close:
mov esi,tl_box_top
add esi,tl_box_height ;esi = coord bottom border
call tl_draw_cursor ;перерисовка курсора
call tl_draw_caption_cur_pos
jmp .no_draw
;--- mouse event for children scrollbar ----------------------------------------
.test_scroll:
mov edx,tl_p_scrol
cmp edx,0
je .no_in_wnd ;пользователь не создал дочернего скроллинга
shr ebx,16
add bx,word[edx] ;+0 .size_x
shl ebx,16
cmp eax,ebx ;правая граница окна
jg .no_in_wnd
mov eax,dword[edx+sb_offs_max_area]
cmp eax,dword[edx+sb_offs_cur_area]
jbe .no_in_wnd ;все узлы попадают в окно скроллинга
stdcall scroll_bar_vertical.mouse, edx ;scrollbar_ver_mouse
cmp dword[edx+sb_offs_redraw],0
je @f
mov dword[edx+sb_offs_redraw],0
stdcall tl_draw, edi ;произошли изменения скроллинга
@@:
cmp dword[edx+sb_offs_delta2],0
jne .no_draw ;попали на скроллинг - не снимаем фокус с TreeList
;-------------------------------------------------------------------------------
.no_in_wnd: ;не попали в окно - потеря фокуса (при условии что фокус был на данном эелементе)
mcall 37,2 ;проверяем нажатость любых кнопок
cmp eax,0 ;ничего не нажали eax=0
je .no_draw
mov ebx,tl_el_focus
cmp dword[ebx],edi
jne .no_draw ;элемент не в фокусе
mov dword[ebx],0 ;reset focus
mov esi,tl_box_top
add esi,tl_box_height ;esi = coord bottom border
call tl_draw_cursor ;рисуем курсор с потеряным фокусом
.no_draw:
popad
ret
endp
;отмена действия
align 4
proc tl_info_undo uses eax edi, tlist:dword
mov edi,dword[tlist]
mov eax,tl_tim_undo
cmp tl_ch_tim,eax
jbe @f
inc tl_tim_undo
call tb_scrol_resize ;обработка скроллинга
@@:
ret
endp
;повтор действия
align 4
proc tl_info_redo uses edi, tlist:dword
mov edi,dword[tlist]
cmp tl_tim_undo,1
jl @f
dec tl_tim_undo
call tb_scrol_resize ;обработка скроллинга
@@:
ret
endp
;удаление отмененных действий
;внутренняя функция, не для экспорта
align 4
tl_info_set_undo:
cmp tl_tim_undo,1
jl .no_work
push eax ebx ecx edx
mov edx,tl_data_nodes
mov ecx,edx
add ecx,sizeof.TreeList
call tl_move_next ;long i=node[0].next;
mov eax,tl_tim_undo
sub tl_ch_tim,eax ;ch_tim-=tim_undo;
mov eax,tl_ch_tim
cmp [edi+34],eax ;if(ls_tim>ch_tim)
jle @f
mov dword[edi+34],0 ;ls_tim=0
@@:
cmp edx,ecx
jle @f
;if(node[i].tc>ch_tim){ // если создание символа было отменено
cmp dword[edx+12],eax
jle .no_u1
mov dword[edx+12],0
mov dword[edx+16],0
mov ebx, dword[edx+4]
imul ebx,sizeof.TreeList
add ebx, tl_data_nodes ;.next
push dword[edx+8] ;node[node[i].perv].next=node[i].next;
pop dword[ebx+8]
mov ebx, dword[edx+8]
imul ebx,sizeof.TreeList
add ebx, tl_data_nodes ;.perv
push dword[edx+4] ;node[node[i].next].perv=node[i].perv;
pop dword[ebx+4]
.no_u1:
;else if(node[i].td>ch_tim) node[i].td=0; // если удаление символа было отменено
cmp dword[edx+16],eax
jle .no_u2
mov dword[edx+16],0
.no_u2:
call tl_move_next
jmp @b
@@:
mov tl_tim_undo,0
; mov eax,[edi+?] ;co_tim
; cmp tl_ch_tim,eax ;ch_tim
; jge @f
; mov [edi+?],0 ;co_tim
; @@:
pop edx ecx ebx eax
.no_work:
ret
;вывод списка на экран
align 4
proc tl_draw, tlist:dword
pushad
;draw dir_list main rect
mov edi,dword[tlist]
mov ebx,tl_box_left
shl ebx,16
add ebx,tl_box_width
mov ecx,tl_box_top
shl ecx,16
mov cx,tl_capt_cy
mov edx,tl_col_zag
mcall 13 ;draw window caption
add ecx,tl_box_top
shl ecx,16
add ecx,tl_box_height
sub cx,tl_capt_cy
mov edx,tl_col_bkg
int 0x40 ;draw window client rect
cmp tl_capt_cy,9 ;9 - minimum caption height
jl @f
mov ebx,edi ;calculate cursor position
mov eax,tl_cur_pos
inc eax
lea edi,[txt_capt_cur]
add edi,7
call tl_convert_to_str
mov edi,ebx
mov eax,tl_tim_undo
lea edi,[txt_capt_otm]
add edi,7
call tl_convert_to_str
mov edi,ebx ;restore edi
mov eax,4 ;draw text captions
mov ebx,tl_box_left
shl ebx,16
add ebx,5*65536+3
add ebx,tl_box_top
mov ecx,tl_col_txt
or ecx,0x80000000
lea edx,[txt_capt_cur]
int 0x40
mov ebx,tl_box_left
shl ebx,16
add ebx,100*65536+3
add ebx,tl_box_top
lea edx,[txt_capt_otm]
int 0x40
@@:
;cycle to nodes
xor eax,eax
mov edx,tl_data_nodes
mov ecx,edx
add ecx,sizeof.TreeList
;*** пропуск узлов, которые промотаны скроллингом ***
cmp tl_p_scrol,0 ;если есть указатель на скроллинг
je .end_c1
mov esi,tl_p_scrol
cmp dword[esi+sb_offs_position],0 ;если скроллинг на верху, выходим
je .end_c1
@@:
call tl_iterat_next
cmp edx,ecx
jle .end_draw
inc eax
cmp eax,dword[esi+sb_offs_position]
jge .end_c1
jmp @b
.end_c1:
xor eax,eax
mov esi,tl_box_top
add esi,tl_box_height ;esi = coord bottom border
@@:
call tl_iterat_next
cmp edx,ecx
jle @f
call tl_draw_node
inc eax
jmp @b
@@:
call tl_draw_cursor
mov edi,tl_p_scrol ;рисуем дочерний скроллинг
cmp edi,0 ;для того что-бы его не пришлось рисовать в пользовательской программе
je .end_draw ;если нет скроллинга выходим
stdcall scroll_bar_vertical.draw, edi
.end_draw:
popad
ret
endp
;переход на следущий видимый узел (пропуская закрытые)
;input:
; ecx = pointer to 1 node struct
; edx = pointer to some node struct
; edi = pointer to 'TreeList' struct
;output:
; edx = pointer to next node struct
align 4
tl_iterat_next:
push bx
mov bl,0x7f
cmp byte[edx+3],1
jne @f
mov bl,byte[edx+2]
@@:
cmp tl_tim_undo,0
je .else
push eax
.beg0:
call tl_move_next
cmp edx,ecx
jle @f
call tl_node_not_vis ;пропуск удаленных и отмененных
cmp al,1
je .beg0
cmp bl,byte[edx+2] ;пропуск закрытых
jl .beg0
@@:
pop eax
pop bx
ret
.else:
call tl_move_next
cmp edx,ecx
jle .endif
cmp dword[edx+16],0 ;td = 'time delete' -> пропуск удаленных
jne .else
cmp bl,byte[edx+2] ;пропуск закрытых
jl .else
.endif:
pop bx
ret
;переход на следущий видимый узел (и на закрытые тоже)
;input:
; ecx = pointer to 1 node struct
; edx = pointer to some node struct
; edi = pointer to 'TreeList' struct
;output:
; edx = pointer to next visible node struct
align 4
tl_iterat_next_all:
cmp tl_tim_undo,0
je .else
push eax
@@:
call tl_move_next
cmp edx,ecx
jle @f
call tl_node_not_vis
cmp al,1
je @b
@@:
pop eax
ret
.else:
call tl_move_next
cmp edx,ecx
jle .endif
cmp dword[edx+16],0 ;td -> time delete
jne .else
.endif:
ret
;переход на предыдущий видимый узел (пропуская закрытые)
;input:
; ecx = pointer to 1 node struct
; edx = pointer to some node struct
; edi = pointer to 'TreeList' struct
align 4
tl_iterat_perv:
push eax
cmp tl_tim_undo,0
je .beg1
.beg0:
call tl_move_perv
cmp edx,ecx
jle @f
call tl_node_not_vis ;пропуск удаленных и отмененных
cmp al,1
je .beg0
.beg1:
call tl_move_perv
cmp edx,ecx
jle @f
cmp dword[edx+16],0 ;td = 'time delete' -> пропуск удаленных
jne .beg1
@@:
call tl_move_max_clo_par
pop eax
ret
;находит родительский закрытый узел максимального уровня
;input:
; edx = pointer to some node struct
; edi = pointer to 'TreeList' struct
;output:
; edx = pointer closed parent node with maximum level
align 4
proc tl_move_max_clo_par uses eax ebx
mov eax,edx
xor ebx,ebx
.beg:
call tl_move_par
cmp byte[edx+3],1 ;родительский узел закрыт ?
jne @f
mov eax,edx
@@:
cmp ebx,edx
je .end_f
mov ebx,edx
jmp .beg
.end_f:
mov edx,eax
ret
endp
;input:
; edx = pointer to some node struct
; edi = pointer to 'TreeList' struct
;output:
; edx = pointer to next node struct
align 4
tl_move_next:
mov edx,dword[edx+8]
imul edx,sizeof.TreeList
add edx,tl_data_nodes
ret
;input:
; edx = pointer to some node struct
; edi = pointer to 'TreeList' struct
;output:
; edx = pointer to perv node struct
align 4
tl_move_perv:
mov edx,dword[edx+4]
imul edx,sizeof.TreeList
add edx,tl_data_nodes
ret
;передвигаемся на родительский узел, если такого нет, то оставляем старое значение указателя
;input:
; ecx =
; edx = pointer to some node struct
; edi = pointer to 'TreeList' struct
;output:
; edx = pointer to parent node struct
align 4
tl_move_par:
cmp byte[edx+2],0
je .end_f ;узел 0-го уровня не может быть дочерним
push eax ebx esi
mov esi,edx ;copy node pointer (edx)
mov bl,byte[edx+2]
@@:
call tl_move_perv
cmp edx,ecx
jle @f ;все выше стоящие узлы не родительские
call tl_node_not_vis ;пропуск удаленных и отмененных
cmp al,1
je @b
cmp byte[edx+2],bl
jl .end_0 ;удачно нашли родительский узел
jmp @b
@@:
mov esi,ebx ;restore node pointer
.end_0:
pop esi ebx eax
.end_f:
ret
;проверяет видимый ли указанный узел с учетом: добавлений, удалений, отмен действий
;input:
; edx = pointer to symbol struct
; edi = pointer to 'TreeList' struct
;output:
; al = 1 if sumbol not visible
; (node[i].td+tim_Undo<=ch_tim && node[i].td) || (node[i].tc>ch_tim-tim_Undo)
align 4
tl_node_not_vis:
cmp dword[edx+16],0
je @f
mov eax,dword[edx+16] ;eax=node[i].td
add eax,tl_tim_undo
cmp eax,tl_ch_tim
jg @f
mov al,1
ret
@@:
mov eax,tl_ch_tim
sub eax,tl_tim_undo
cmp dword[edx+12],eax ;tc -> time create
jle @f
mov al,1
ret
@@:
xor al,al
ret
;рисуем курсор на экране
;input:
; edi = pointer to TreeInfo struct
; esi = coord bottom border
align 4
proc tl_draw_cursor uses eax ebx ecx edx esi
call tl_get_display_cur_pos ;eax = cursor pos in screen
cmp eax,0
jl .end_f ;курсор находится выше окна, в области прокрученной скроллингом
cmp tl_data_img_sys,0 ;смотрим есть ли указатель на картинку системных иконок
jne @f
mov ebx,tl_box_left
shl ebx,16
mov bx,tl_img_cx
xor ecx,ecx
mov cx,tl_img_cy
imul ecx,eax
add ecx,tl_box_top
add cx,tl_capt_cy
;crop image if on the border
cmp esi,ecx ;если курсор внизу и его вообще не видно
jl .end_f
sub esi,ecx
shl ecx,16
mov cx,tl_img_cy
cmp si,tl_img_cy
jge .crop0
mov cx,si ;если курсор виден частично (попал на нижнюю границу)
.crop0:
mov edx,tl_col_txt
mcall 13 ;рисуем простой прямоугольник, т.к. нет системных иконок
jmp .end_f
@@:
mov ebx,tl_data_img_sys
imul ax,tl_img_cy
mov edx,tl_box_left
shl edx,16
mov dx,ax
add edx,tl_box_top
add dx,tl_capt_cy
mov ecx,tl_el_focus ;проверяем в фокусе элемент или нет
cmp dword[ecx],edi
je .focus
;если не в фокусе сдвигаем координаты на иконку не активного курсора
xor eax,eax
xor ecx,ecx
mov cx,tl_img_cx
mov ax,tl_img_cy
imul eax,ecx
imul eax,4*3 ;4=icon index 3=rgb
add ebx,eax
.focus:
mov cx,tl_img_cx
shl ecx,16
mov cx,tl_img_cy
;crop image if on the border
cmp si,dx ;если курсор внизу и его вообще не видно
jl .end_f
sub si,dx
cmp si,tl_img_cy
jge .crop1
mov cx,si ;если курсор виден частично (попал на нижнюю границу)
.crop1:
mcall 7 ;рисуем иконку курсора
.end_f:
ret
endp
;стираем курсор на экране
;input:
; edi = pointer to TreeInfo struct
; esi = coord bottom border
align 4
proc tl_draw_null_cursor uses eax ebx ecx edx esi
call tl_get_display_cur_pos ;eax = cursor pos in screen
cmp eax,0
jl .end_f ;курсор находится выше окна, в области прокрученной скроллингом
mov ebx,tl_box_left
shl ebx,16
mov bx,tl_img_cx
xor ecx,ecx
mov cx,tl_img_cy
imul ecx,eax
add ecx,tl_box_top
add cx,tl_capt_cy
;crop image if on the border
cmp esi,ecx ;если курсор внизу и его вообще не видно
jl .end_f
sub esi,ecx
shl ecx,16
mov cx,tl_img_cy
cmp si,tl_img_cy
jge @f
mov cx,si ;если курсор виден частично (попал на нижнюю границу)
@@:
mov edx,tl_col_bkg
mcall 13 ;рисуем простой прямоугольник с фоновым цветом
.end_f:
ret
endp
;берет позицию курсора, относительно экрана
;input:
; edi = pointer to TreeInfo struct
;output:
; eax = index
align 4
tl_get_display_cur_pos:
mov eax,tl_cur_pos
cmp tl_p_scrol,0
je @f
push ebx
mov ebx,tl_p_scrol
mov ebx,dword[ebx+sb_offs_position]
sub eax,ebx ;отнимаем позицию скроллинга
pop ebx
@@:
ret
;рисует узел с: картинкой, подписью, иконкой открытия/закрытия и линиями к родит. узлу
;input:
; eax = node position
; edx = pointer to some node struct
; edi = pointer to 'TreeList' struct
; esi = coord of bottom border
align 4
proc tl_draw_node uses eax ebx ecx edx esi
mov ebx,1 ;1 - место под курсор
bt tl_style,2 ;tl_list_box_mode
jc @f
inc ebx ;+1 - место под знак +,-
add bl,byte[edx+2] ;добавляем уровень элемента для его учета в левом отступе иконки
@@:
imul bx,tl_img_cx
add ebx,tl_box_left
shl ebx,16
mov bx,tl_img_cx
xor ecx,ecx
mov cx,tl_img_cy
imul ecx,eax
add ecx,tl_box_top
add cx,tl_capt_cy
;crop image if on the border
cmp esi,ecx ;если узел внизу и его вообще не видно
jl .end_draw
sub esi,ecx
shl ecx,16
mov cx,tl_img_cy
cmp si,tl_img_cy
jge @f
mov cx,si ;если узел виден частично (попал на нижнюю границу)
jmp .crop ;пропускаем рисование надписи, которая скорее всего тоже вылезет за нижнюю границу
@@:
call tl_draw_node_caption
.crop:
mov esi,ecx ;save ecx
cmp tl_data_img,0
jne .draw_img_n
push edx
mov edx,tl_col_txt
mcall 13 ;draw node rect
pop edx
jmp @f
.draw_img_n:
push ebx edx esi
xor esi,esi
mov si,word[edx] ;get icon type
mov edx,ebx
ror ecx,16
mov dx,cx
mov cx,bx
ror ecx,16
mov ebx,3 ;rgb = 3 bytes
imul bx,tl_img_cx
imul bx,tl_img_cy
imul ebx,esi ;esi = icon index
add ebx,tl_data_img
mcall 7 ;draw node icon '-'
pop esi edx ebx
@@:
mov al,byte[edx+2] ;draw minus '-'
mov ecx,tl_data_nodes
add ecx,sizeof.TreeList
mov ah,10 ;get icon index '+' or '-' ?
cmp byte[edx+3],1
jne .close
dec ah
.close:
call tl_draw_node_icon_opn_clo ;рисование иконки открытого или закрытого узла
bt tl_style,1
jae .end_draw
call tl_draw_node_icon_par_lin ;рисование линии к родительскому элементу
call tl_draw_node_icon_par_lin_up ;рисование вертикальной линии к родительскому элементу
.end_draw:
ret
endp
;рисует иконки открытого или закрытого узла (обычно + или -)
;input:
; al = уровень элемента
; ecx = pointer to 1 node struct
; edx = pointer to some node struct
;...
align 4
proc tl_draw_node_icon_opn_clo uses eax ebx ecx edx esi
inc al
call tl_iterat_next_all ;get next visible item
cmp edx,ecx
jle @f
mov ecx,esi ;load ecx
cmp al,byte[edx+2]
jne @f
ror ebx,16
sub bx,tl_img_cx
ror ebx,16
cmp tl_data_img_sys,0
jne .draw_img_s
mov edx,tl_col_txt
mcall 13 ;draw minus rect, if not system icons
jmp @f
.draw_img_s:
mov ecx,esi ;load ecx
mov edx,ebx
ror ecx,16
mov dx,cx
mov cx,bx
ror ecx,16
mov ebx,3 ;rgb = 3 bytes
imul bx,tl_img_cx
imul bx,tl_img_cy
shr eax,8
and eax,0xff
imul ebx,eax ;eax = icon index
add ebx,tl_data_img_sys
mcall 7 ;draw minus icon '-'
@@:
ret
endp
;рисование линии к родительскому элементу
;input:
; al = уровень элемента
; ecx = pointer to 1 node struct
; edx = pointer to some node struct
;...
align 4
tl_draw_node_icon_par_lin:
cmp byte[edx+3],1
je .close
push eax ebx ecx edx esi
cmp al,0
je @f
; dec al
; call tl_iterat_perv ;get perv visible item
call tl_iterat_next_all ;get next visible item
cmp edx,ecx
jle .line3 ;if end of list
cmp al,byte[edx+2]
jne .line3 ;jg ???
mov eax,3 ;line in middle element
jmp .line2
.line3:
mov eax,6 ;line in end element
.line2:
mov ecx,esi ;load ecx
ror ebx,16
sub bx,tl_img_cx
ror ebx,16
cmp tl_data_img_sys,0
jne .draw_img_s
mov edx,tl_col_txt
mcall 13 ;draw minus rect, if not system icons
jmp @f
.draw_img_s:
; mov ecx,esi ;load ecx
mov edx,ebx
ror ecx,16
mov dx,cx
mov cx,bx
ror ecx,16
mov ebx,3 ;rgb = 3 bytes
imul bx,tl_img_cx
imul bx,tl_img_cy
; shr eax,8
; and eax,0xff
imul ebx,eax ;eax = icon index
add ebx,tl_data_img_sys
mcall 7 ;draw line icon
@@:
pop esi edx ecx ebx eax
.close:
ret
;input:
; al = уровень элемента
; ecx = pointer to 1 node struct
; edx = pointer to some node struct
; edi = pointer to 'TreeList' struct
align 4
tl_draw_node_icon_par_lin_up:
push eax ebx ecx edx
push esi
cmp tl_data_img_sys,0 ;if not image
je @f
cmp al,0
je @f
xor esi,esi ;в si будем насчитывать кол-во иконок, нужных для прорисовки линии
;--- цикл для вычисления колличества вертикальных линий ---
.cycle0:
call tl_iterat_perv ;get perv visible item
cmp edx,ecx
jle .cycle1 ;if begin of list
cmp byte[edx+2],al
jle .cycle0end ;уровень верхнего элемента не требует прорисовки
inc si
jmp .cycle0
.cycle0end:
cmp si,0 ;si = кол-во иконок линии которые нужно нарисовать сверху
je @f
shl esi,16
pop ecx ;esi->ecx
push ecx ;save esi
ror ebx,16
sub bx,tl_img_cx
ror ebx,16
mov edx,ebx
ror ecx,16
mov dx,cx
mov cx,bx
ror ecx,16
mov cx,tl_img_cy ;restore size y (if crop)
mov ebx,3 ;rgb = 3 bytes
imul bx,tl_img_cx
imul bx,tl_img_cy
add ebx,tl_data_img_sys
add esi,tl_box_top
add si,tl_capt_cy ;si = верхняя граница окна
mov eax,7
;--- цикл для рисования вертикальной линии ---
.cycle1:
sub dx,tl_img_cy ;поднимаем координату y вверх
cmp dx,si
jl @f
cmp esi,0x10000
jl @f
int 0x40 ;draw line icon
sub esi,0x10000 ;уменьшаем счетчик иконок
jmp .cycle1
@@:
pop esi
pop edx ecx ebx eax
ret
;input:
; edi = pointer to TreeInfo struct
;output:
; eax = rows
align 4
tl_get_rows_count:
push ecx edx
mov eax,tl_box_height
sub ax,tl_capt_cy
xor ecx,ecx
mov cx,tl_img_cy
xor edx,edx
div ecx
pop edx ecx
ret
;input:
; eax = node position
; ebx = [координата по оси x]*65536 + [img_cx]
; ecx = [координата по оси y]*65536 + [img_cy]
; edx = pointer to some node struct
; edi = pointer to TreeInfo struct
align 4
tl_draw_node_caption:
push ebx ecx edx esi
xor esi,esi
mov si,tl_info_size
cmp si,tl_info_capt_offs
jle @f ;if caption size <= 0
push eax
call tl_get_node_index ;eax = node index
imul esi,eax
pop eax
add si,tl_info_capt_offs
add esi,tl_data_info
mov edx,esi
shr ebx,16
add bx,tl_img_cx ;сдвигаем надпись по горизонтали --->
add bx,3 ;отступ
;bx = coord. x
call tl_strlen ;eax = strlen
call tl_get_draw_text_len
mov cx,bx
ror ecx,16
mov ebx,ecx
add bx,tl_img_cy ;выравнивиние по нижней границе иконки
sub bx,9 ;отнимаем высоту текста
mov ecx,tl_col_txt
and ecx,0xffffff
; or ecx,0x80000000 ;text is ASCIIZ
mcall 4
@@:
pop esi edx ecx ebx
ret
;input:
; eax = strlen
; ebx = text coord x
;output:
; esi = text len
align 4
tl_get_draw_text_len:
push eax ecx edx
mov esi,eax ;берем длинну строки
mov eax,tl_box_left
add eax,tl_box_width
cmp eax,ebx
jle .text_null ;если подпись полностью вся за экраном
sub eax,ebx
xor edx,edx
mov ecx,6 ;ширина системного шрифта
div ecx ;смотрим сколько символов может поместиться на экране
cmp esi,eax
jl @f
mov esi,eax ;если длинна текста меньше, чем все место под строку
jmp @f
.text_null:
xor esi,esi
@@:
pop edx ecx eax
ret
;input:
; esi = pointer to string
;output:
; eax = strlen
align 4
tl_strlen:
mov eax,esi
@@:
cmp byte[eax],0
je @f
inc eax
jmp @b
@@:
sub eax,esi
ret
;добавить узел
;input:
; tlist - указатель на структуру листа
; n_opt - опции добавления
; n_info - указатель на добавляемые данные
align 4
proc tl_node_add uses eax ebx ecx edx edi, n_info:dword, n_opt:dword, tlist:dword
mov edi,dword[tlist]
call tl_info_set_undo
mov ebx,sizeof.TreeList
imul ebx,tl_info_max_count
add ebx,tl_data_nodes
;--
call tl_get_cur_node_index ;eax=po_t
imul eax,sizeof.TreeList
add eax,tl_data_nodes
mov edx,eax
call tl_move_perv
call tl_get_node_index ;eax = index of pointer [edx]
;--
mov edx,sizeof.TreeList
shl edx,1
add edx,tl_data_nodes
@@: ;for(i=2;i<nodeMax;i++)
cmp dword [edx+12],0
jne .u0
cmp dword [edx+16],0
jne .u0
inc tl_ch_tim
mov ecx,dword[n_opt]
ror ecx,16 ;cx = type
mov word[edx],cx
;;;mov cl,byte[ebp+13]
rol ecx,8 ;cl = close|open
mov byte[edx+3],cl ;node[i].clo
mov byte[edx+2], 0 ;node[i].lev=0
bt tl_style,2 ;tl_list_box_mode
jc .l_box_m
mov cl,byte[n_opt]
mov byte[edx+2],cl ;node[i].lev
.l_box_m:
push tl_ch_tim ;node[i].tc=ch_tim;
pop dword[edx+12]
mov dword[edx+4], eax ;node[i].perv=po_t;
;*** copy node data ***
push esi
xor ecx,ecx
mov cx,tl_info_size
mov esi,ecx
push eax
call tl_get_node_index ;eax = node index
imul esi,eax
pop eax
add esi,tl_data_info
mov edi,dword[n_info] ;pointer to node data
xchg edi,esi
rep movsb
mov esi,edi
mov edi,dword[tlist] ;restore edi
mov cx,tl_info_capt_offs
cmp cx,tl_info_size
jge .no_text_data
cmp tl_info_capt_len,0 ;проверяем есть ли ограничение на длинну строки
je .no_len_ogran
add cx,tl_info_capt_len
and ecx,0xffff
add esi,ecx
mov cx,tl_info_size
sub esi,ecx
.no_len_ogran:
dec esi
mov byte[esi],0
.no_text_data:
pop esi ;restore esi
mov ecx,eax
imul ecx,sizeof.TreeList
add ecx,tl_data_nodes ; *** ecx = node[po_t] ***
add ecx,8 ; *** ecx = node[po_t].next ***
push dword [ecx] ;node[i].next=node[po_t].next;
pop dword [edx+8]
call tl_get_node_index ;*** eax = i ***
cmp eax,tl_info_max_count
jge .u0
mov [ecx],eax ;node[po_t].next=i; // ссылки перенаправляем
mov ecx,[edx+8] ; *** ecx = node[i].next ***
imul ecx,sizeof.TreeList
add ecx,tl_data_nodes ; *** ecx = node[node[i].next] ***
mov [ecx+4],eax ;node[node[i].next].perv=i;
call tb_scrol_resize ;обработка скроллинга
jmp @f
.u0:
add edx,sizeof.TreeList
cmp edx,ebx ;enf of node memory ?
jle @b
@@:
ret
endp
;input:
; edi = pointer to TreeInfo struct
align 4
proc tb_scrol_resize uses eax ecx edx
cmp tl_p_scrol,0 ;обработка скроллинга
je @f
call tl_get_node_count ;eax = node count
mov ecx,eax
call tl_get_rows_count
cmp ecx,eax
jg .ye_sb
xor ecx,ecx
.ye_sb:
mov edx,tl_p_scrol
mov dword[edx+sb_offs_cur_area],eax
mov dword[edx+sb_offs_max_area],ecx
stdcall scroll_bar_vertical.draw,edx
@@:
ret
endp
;input:
;n_info - pointer to node info
align 4
proc tl_node_set_data uses eax ecx edx edi esi, n_info:dword, tlist:dword
mov edi,dword[tlist]
call tl_get_cur_node_index ;eax=po_t
cmp eax,2
jl @f
xor ecx,ecx
mov cx,tl_info_size
imul eax,ecx
add eax,tl_data_info
mov edi,eax
mov esi,dword[n_info] ;pointer to node data
rep movsb
mov esi,edi
mov edi,dword[tlist] ;restore edi
mov cx,tl_info_capt_offs
cmp cx,tl_info_size
jge .no_text_data
mov ax,tl_info_capt_len ;проверяем есть ли ограничение на длинну текста
cmp ax,0
je .no_limit
add cx,ax ;cx = tl_info_capt_offs + tl_info_capt_len
and ecx,0xffff
xor eax,eax
mov ax,tl_info_size
cmp eax,ecx
jl .no_limit ;пользователь задал слишком большую длинну текста
add esi,ecx
sub esi,eax
.no_limit:
dec esi
mov byte[esi],0 ;обнуляем последний символ подписи, что-бы не глючило если пользователь задал неправильную структуру
.no_text_data:
@@:
ret
endp
;input:
;dword[ebp+ 8] - pointer to 'TreeList' struct
align 4
tl_node_get_data: ;взять указатель на данные узла под курсором
push ebp
mov ebp,esp
push eax ecx edi
mov edi,dword[ebp+8]
call tl_get_cur_node_index ;eax=po_t
mov dword[ebp+8],0 ;if return 0 pointer
cmp eax,2
jl @f
xor ecx,ecx
mov cx,tl_info_size
imul eax,ecx
add eax,tl_data_info
mov dword[ebp+8],eax ;return node data pointer
@@:
pop edi ecx eax
pop ebp
ret
;input:
;dword[ebp+ 8] - node index
;dword[ebp+12] - pointer to 'TreeList' struct
align 4
tl_node_poi_get_info: ;взять указатель на структуру узла в указанной позиции
push ebp
mov ebp,esp
push eax ecx edx edi
mov edi,dword[ebp+12]
mov eax,dword[ebp+8]
;cycle to nodes
mov edx,tl_data_nodes
mov ecx,edx
add ecx,sizeof.TreeList
@@:
call tl_iterat_next_all
cmp edx,ecx
jle @f
dec eax
cmp eax,0
jg @b
jmp .find
@@:
xor edx,edx
.find:
mov dword[ebp+12],edx
pop edi edx ecx eax
pop ebp
ret 4
;input:
;dword[ebp+ 8] - node param struct
;dword[ebp+12] - pointer to 'TreeList' struct
align 4
tl_node_poi_get_next_info: ;взять указатель на следущую структуру узла
push ebp
mov ebp,esp
push ecx edx edi
mov edi,dword[ebp+12]
mov edx,dword[ebp+8]
mov ecx,tl_data_nodes
add ecx,sizeof.TreeList
call tl_iterat_next_all
cmp edx,ecx
jg @f
xor edx,edx
@@:
mov dword[ebp+12],edx
pop edi edx ecx
pop ebp
ret 4
;input:
;dword[ebp+ 8] - node param struct
;dword[ebp+12] - pointer to 'TreeList' struct
align 4
tl_node_poi_get_data: ;взять указатель на данные узла
push ebp
mov ebp,esp
push eax ecx edx edi
mov edi,dword[ebp+12]
mov edx,dword[ebp+8]
mov dword[ebp+12],0
call tl_get_node_index ;eax = node index
cmp eax,2
jl @f
xor ecx,ecx
mov cx,tl_info_size
imul eax,ecx
add eax,dword[edi]
mov dword[ebp+12],eax ;return node data pointer
@@:
pop edi edx ecx eax
pop ebp
ret 4
;берет позицию под курсором
;input:
; edi = pointer 'tl' struct
;output:
; eax = index of current node
align 4
proc tl_get_cur_node_index uses ecx edx
;cycle to nodes
xor eax,eax
mov edx,tl_data_nodes
mov ecx,edx
add ecx,sizeof.TreeList
@@:
call tl_iterat_next
cmp edx,ecx
jle @f
cmp eax,tl_cur_pos
je @f
inc eax
jmp @b
@@:
mov eax,edx
sub eax,tl_data_nodes
xor edx,edx
mov ecx,sizeof.TreeList
div ecx
ret
endp
;берет позицию указанного символа
;input:
; edx = pointer node memory
; edi = pointer 'tl' struct
;output:
; eax = struct index of current node
align 4
tl_get_node_index:
push ecx edx
mov eax,edx
sub eax,tl_data_nodes
xor edx,edx
mov ecx,sizeof.TreeList
div ecx
pop edx ecx
ret
;удалить узел
align 4
proc tl_node_delete uses eax edx edi, tlist:dword
mov edi,dword[tlist]
call tl_get_cur_node_index ;eax=po_t
cmp eax,2
jl @f
imul eax,sizeof.TreeList
add eax,tl_data_nodes
mov edx,eax
inc tl_ch_tim
mov eax,tl_ch_tim
mov dword[edx+16],eax
call tb_scrol_resize ;обработка скроллинга
@@:
ret
endp
;поставить курсор на первый узел
align 4
proc tl_cur_beg uses edi, tlist:dword
mov edi,dword[tlist]
mov tl_cur_pos,0
cmp tl_p_scrol,0
je @f
mov edi,tl_p_scrol
mov dword[edi+sb_offs_position],0
stdcall scroll_bar_vertical.draw, edi
@@:
ret
endp
;перенести курсор на 1 позицию ниже
align 4
proc tl_cur_next uses eax ebx edi esi, tlist:dword
mov edi,dword[tlist]
call tl_get_node_count ;eax = node count
;inc eax
cmp tl_cur_pos,eax
jge .no_redraw
mov esi,tl_box_top
add esi,tl_box_height ;esi = coord bottom border
call tl_draw_null_cursor ;стираем курсор
inc tl_cur_pos
cmp tl_p_scrol,0 ;if not scrol struct
je @f
call tl_get_rows_count ;eax = rows count
mov ebx,tl_p_scrol
add eax,dword[ebx+sb_offs_position]
cmp tl_cur_pos,eax
jl @f
inc dword[ebx+sb_offs_position]
stdcall scroll_bar_vertical.draw,ebx
stdcall tl_draw,dword[tlist] ;полная перерисовка окна
jmp .no_redraw
@@:
mov edi,dword[tlist] ;restore edi
call tl_draw_cursor ;перерисовка курсора
call tl_draw_caption_cur_pos
.no_redraw:
ret
endp
;берет число всех видимых узлов (не считая закрытых дочерних)
;input:
; edi = pointer 'tl' struct
;output:
; eax = struct index of current node
align 4
tl_get_node_count:
push ecx edx
;cycle to nodes
xor eax,eax
mov edx,tl_data_nodes
mov ecx,edx
add ecx,sizeof.TreeList
@@:
call tl_iterat_next
cmp edx,ecx
jle @f
inc eax
jmp @b
@@:
pop edx ecx
ret
;берет число всех видимых узлов (считая закрытые дочерние)
;input:
; edi = pointer 'tl' struct
;output:
; eax = struct index of current node
align 4
tl_get_node_count_all:
push ecx edx
;cycle to nodes
xor eax,eax
mov edx,tl_data_nodes
mov ecx,edx
add ecx,sizeof.TreeList
@@:
call tl_iterat_next_all
cmp edx,ecx
jle @f
inc eax
jmp @b
@@:
pop edx ecx
ret
;перенести курсор на 1 позицию выше
align 4
proc tl_cur_perv uses eax edi esi, tlist:dword
mov edi,dword[tlist]
cmp tl_cur_pos,0
je .no_redraw
mov esi,tl_box_top
add esi,tl_box_height ;esi = coord bottom border
call tl_draw_null_cursor ;стираем курсор
dec tl_cur_pos ;двигаем курсор вверх
cmp tl_p_scrol,0 ;если есть указатель на скроллинг
je @f
mov eax,tl_p_scrol
cmp dword[eax+sb_offs_position],0 ;если скроллинг на верху, выходим
je @f
mov edi,tl_cur_pos
cmp edi,dword[eax+sb_offs_position] ;если курсор ушел выше скроллинга, тогда опускаем скроллинг
jge @f
dec dword[eax+sb_offs_position]
stdcall scroll_bar_vertical.draw, eax
stdcall tl_draw, dword[tlist] ;полная перерисовка окна
jmp .no_redraw
@@:
mov edi,dword[tlist] ;restore edi
;mov esi,tl_box_top
;add esi,tl_box_height ;esi = coord bottom border
call tl_draw_cursor ;перерисовка курсора
call tl_draw_caption_cur_pos
.no_redraw:
ret
endp
;перенести курсор на 1 страницу выше
align 4
proc tl_cur_page_up uses eax edi esi, tlist:dword
mov edi,dword[tlist]
cmp tl_p_scrol,0 ;если есть указатель на скроллинг
je .no_redraw
mov esi,tl_p_scrol
call tl_get_rows_count ;eax = rows count
cmp tl_cur_pos,0
jne @f
cmp dword[esi+sb_offs_position],0 ;если скроллинг на верху, выходим
jne @f
jmp .no_redraw
@@:
cmp tl_cur_pos,eax ;проверяем позицию курсора и кол-во сток на странице
jl @f ;если меньше, то приравниваем к 0, что-бы не отнять больше чем надо
sub tl_cur_pos,eax
jmp .cursor
@@:
mov tl_cur_pos,0
.cursor:
cmp dword[esi+sb_offs_position],eax
jl @f
sub dword[esi+sb_offs_position],eax
jmp .scroll
@@:
mov dword[esi+sb_offs_position],0
.scroll:
;перерисовки окна и скроллинга
stdcall tl_draw, edi ;draw window
stdcall scroll_bar_vertical.draw, esi
.no_redraw:
ret
endp
;перенести курсор на 1 страницу ниже
align 4
proc tl_cur_page_down uses eax ebx ecx edi esi, tlist:dword
;eax - кол-во строк на странице
;ebx - макс. позиция курсора
;ecx - макс. позиция скроллинга
mov edi,dword[tlist]
cmp tl_p_scrol,0 ;если есть указатель на скроллинг
je .no_redraw
mov esi,tl_p_scrol
call tl_get_node_count ;eax = node count
mov ebx,eax
call tl_get_rows_count ;eax = rows count
mov ecx,ebx
inc ecx ;если нижний узел виден на половину
cmp ecx,eax ;if (ecx>eax) { ecx=ecx-eax } else { ecx=0 }
jl @f
sub ecx,eax ;уменьшаем максимальную позицию скроллинга, так что-бы были видны последние узлы
jmp .control
@@:
xor ecx,ecx ;ecx=0 - все узлы влазят в экран, скроллинг не нужен
.control:
cmp tl_cur_pos,ebx ;курсор внизу ?
jl @f
cmp dword[esi+sb_offs_position],ecx ;скроллинг внизу ?
jl @f
jmp .no_redraw
@@:
add tl_cur_pos,eax ;перемещаем курсор
cmp tl_cur_pos,ebx
jl @f
mov tl_cur_pos,ebx
@@:
add dword[esi+sb_offs_position],eax ;перемещаем скроллинг
cmp dword[esi+sb_offs_position],ecx
jl @f
mov dword[esi+sb_offs_position],ecx
@@:
;перерисовки окна и скроллинга
stdcall tl_draw, edi ;draw window
stdcall scroll_bar_vertical.draw, esi
.no_redraw:
ret
endp
;открыть/закрыть узел (работает с узлами которые имеют дочерние узлы)
align 4
proc tl_node_close_open uses eax edx edi, tlist:dword
mov edi,dword[tlist]
call tl_get_cur_node_index ;eax = позиция узла на котором стоит курсор
cmp eax,2 ;курсор стоит на узле ?
jl @f
imul eax,sizeof.TreeList
add eax,tl_data_nodes
;eax = указатель на структуру узла выбранного курсором
push dword edi
push dword eax
call tl_node_poi_get_next_info
pop dword edx ;edx = указатель на структуру узла который идет после узла eax
cmp edx,0 ;есть ли узлы ниже выбранного нами ?
je @f
mov dl,byte[edx+2] ;берем уровень нижнего узла
cmp byte[eax+2],dl ;+2 = .lev
jge @f ;если нижние узлы меньшего уровня, значит они не дочерние, конец функции
xor byte[eax+3],1 ;+3 = .clo *** открытие/закрытие узла ***
call tb_scrol_resize ;обработка скроллинга
stdcall tl_draw, edi ;обновление окна
@@:
ret
endp
;увеличить уровень
align 4
proc tl_node_lev_inc uses eax ecx edx edi, tlist:dword
mov edi,dword[tlist]
bt tl_style,2 ;tl_list_box_mode
jc @f
call tl_get_cur_node_index ;eax=po_t
cmp eax,2
jl @f
mov ecx,tl_data_nodes
imul eax,sizeof.TreeList
add eax,ecx ;eax = pointer to some node struct
add ecx,sizeof.TreeList ;ecx = pointer to 1 node struct
mov edx,eax
call tl_iterat_perv ;проверяем есть ли верхний узел
cmp edx,ecx
jle @f ;если верхнего узла нет то текущий узел не двигаем
mov cl,byte[edx+2] ;берем уровень родительского узла
inc cl ;добавляем 1 и получаем максимальное значение
cmp byte[eax+2],cl
jge @f
inc byte[eax+2] ;увеличиваем значение узла
@@:
ret
endp
;уменьшить уровень
align 4
proc tl_node_lev_dec uses eax edi, tlist:dword
mov edi,dword[tlist]
call tl_get_cur_node_index ;eax=po_t
cmp eax,2
jl @f
imul eax,sizeof.TreeList
add eax,tl_data_nodes
cmp byte[eax+2],0
je @f
dec byte[eax+2]
@@:
ret
endp
;перемещаем узел вверх
align 4
proc tl_node_move_up uses eax ebx ecx edx edi esi, tlist:dword
mov edi,dword[tlist]
call tl_get_cur_node_index ;eax=po_t
cmp eax,2
jl @f
mov ebx,eax ;copy index of node struct
mov edx,tl_data_nodes
mov ecx,edx
add ecx,sizeof.TreeList
imul eax,sizeof.TreeList
add eax,edx ;eax = pointer to 2 node struct
mov edx,eax ;edx = pointer to 2 node struct
mov esi,eax ;esi = pointer to 2 node struct
call tl_iterat_perv ;edx = pointer to 1 node struct
call tl_get_node_index ;eax = index of 1 node struct
cmp edx,ecx
jle @f
cmp dword[edx+8],ebx ;+8 next
jne .po8
call tl_node_move_po6 ;узлы идут подряд меняем 6 ссылок
jmp .cur_mov
.po8:
call tl_node_move_po8 ;узлы идут не подряд меняем 8 ссылок
.cur_mov:
push dword edi
call tl_cur_perv
push dword edi
call tl_draw
@@:
ret
endp
;перемещаем узел вниз
align 4
proc tl_node_move_down uses eax ebx ecx edx edi esi, tlist:dword
mov edi,dword[tlist]
call tl_get_cur_node_index ;eax=po_t
cmp eax,2
jl @f
mov ebx,eax ;copy index of node struct
mov edx,tl_data_nodes
mov ecx,edx
add ecx,sizeof.TreeList
imul eax,sizeof.TreeList
add eax,edx ;eax = pointer to 1 node struct
mov edx,eax ;edx = pointer to 1 node struct
mov esi,eax ;esi = pointer to 1 node struct
call tl_iterat_next ;edx = pointer to 2 node struct
call tl_get_node_index ;eax = index of 2 node struct
cmp edx,ecx
jle @f
cmp dword[esi+8],eax ;+8 next
jne .po8
xchg eax,ebx ;меняе порядок следования заменяемых узлов
xchg edx,esi
call tl_node_move_po6 ;узлы идут подряд меняем 6 ссылок
jmp .cur_mov
.po8: ;а тут порядок следования узлов не меняем
call tl_node_move_po8 ;узлы идут не подряд меняем 8 ссылок
.cur_mov:
stdcall tl_cur_next, edi
stdcall tl_draw, edi
@@:
ret
endp
align 4
tl_node_move_po6:
mov ecx,edx ;save node pointer
call tl_move_perv
mov dword[edx+8],ebx
mov edx,esi
call tl_move_next
mov dword[edx+4],eax
mov edx,ecx ;restore node pointer
;+4 perv
mov ecx,dword[edx+4]
mov dword[esi+4],ecx
;+8 next
mov ecx,dword[esi+8]
mov dword[edx+8],ecx
mov dword[edx+4],ebx
mov dword[esi+8],eax
ret
;input
;eax = index 1 node struct
;ebx = index 2 node struct
;edx = pointer 1 node struct
;esi = pointer 2 node struct
;edi = pointer to 'TreeList' struct
;output:
;eax = ?
;ebx = ?
;ecx = ?
align 4
tl_node_move_po8:
; push ecx
mov ecx,edx ;save node pointer
call tl_move_perv
mov dword[edx+8],ebx
mov edx,ecx
call tl_move_next
mov dword[edx+4],ebx
mov edx,esi
call tl_move_perv
mov dword[edx+8],eax
mov edx,esi
call tl_move_next
mov dword[edx+4],eax
mov edx,ecx ;restore node pointer
; pop ecx
;+4 perv
mov eax,dword[edx+4]
mov ebx,dword[esi+4]
xchg eax,ebx
mov dword[edx+4],eax
mov dword[esi+4],ebx
;+8 next
mov eax,dword[edx+8]
mov ebx,dword[esi+8]
xchg eax,ebx
mov dword[edx+8],eax
mov dword[esi+8],ebx
ret
;input:
; edi = pointer to 'TreeList' struct
align 4
tl_draw_caption_cur_pos:
cmp tl_capt_cy,9 ;9 - minimum caption height
jl @f
push eax ebx ecx edx edi esi
mov ebx,edi ;calculate cursor position
mov eax,tl_cur_pos
inc eax
lea edi,[txt_capt_cur]
add edi,7
call tl_convert_to_str
mov edi,ebx
mov eax,4 ;draw text captions
mov ebx,tl_box_left
shl ebx,16
add ebx,5*65536+3
add ebx,tl_box_top
mov ecx,tl_col_txt
or ecx,0xc0000000 ;0x40000000 закрашивать фон цветом edi
lea edx,[txt_capt_cur]
mov edi,tl_col_zag
int 0x40
pop esi edi edx ecx ebx eax
@@:
ret
;input:
;dword[ebp+ 8] - memory size
;dword[ebp+12] - pointer to memory
;dword[ebp+16] - options: 0 - first element, 1 - add next element
;dword[ebp+20] - pointer to 'TreeList' struct
;output:
;dword[ebp+ 8] - error code
align 4
tl_save_mem:
push ebp
mov ebp,esp
push eax ebx ecx edx edi esi
mov esi,dword[ebp+12]
mov edi,dword[ebp+20]
cmp dword[ebp+16],0 ;add mode
je @f
push dword edi
push dword esi
call tl_get_mem_size ;берем размер ранее сохранённых данных
pop ebx
add esi,ebx
@@:
xor ebx,ebx
mov bx,tl_info_size
call tl_get_node_count_all ;eax = all node count
mov ecx,eax ;вычисляем сколько памяти должно быть заполнено
imul ecx,ebx ;умножаем на размер структуры узла
add ecx,tl_save_load_heder_size+1 ;element header +1 end element sumbol
add ecx,esi ;добавляем указатель на начало памяти (с учетом ранее записанных структур)
sub ecx,dword[ebp+12] ;отнимаем указатель на начало памяти (без ранее записанных структур)
cmp ecx,dword[ebp+8] ;ecx = element memory size
jg .err_mem_size
;save tree params (in header)
mov dword[esi],'tree'
mov word[esi+4],bx
mov dword[esi+6],eax ;element count
mov eax,tl_style
mov dword[esi+10],eax
mov eax,tl_cur_pos
mov dword[esi+14],eax
mov ax,tl_info_capt_offs
mov word[esi+18],ax
mov ax,tl_info_capt_len
mov word[esi+20],ax
;copy scroll position
mov edx,tl_p_scrol
mov eax,dword[edx+sb_offs_position]
mov dword[esi+22],eax
add esi,tl_save_load_heder_size ;add header size
;cycle to nodes
mov edx,tl_data_nodes
mov ecx,edx
add ecx,sizeof.TreeList
@@:
call tl_iterat_next_all
cmp edx,ecx
jle @f
;save node params
call tl_get_node_index ;eax = index of pointer [edx]
mov dword[esi],eax
add esi,4
mov eax,dword[edx] ;eax = (type; lev; clo)
mov dword[esi],eax
add esi,4
stdcall tl_node_poi_get_data, edx,edi
pop dword eax
;call tl_node_copy_data
push ecx edi
mov edi,eax
mov ecx,ebx
xchg esi,edi
rep movsb
mov esi,edi
pop edi ecx
;add esi,ebx
jmp @b
@@:
mov byte[esi],0 ;end of 'treelist'
mov dword[ebp+20],0 ;return error code
jmp @f
.err_mem_size:
or dword[ebp+20],tl_err_save_memory_size
@@:
pop esi edi edx ecx ebx eax
pop ebp
ret 12
;input:
;dword[ebp+ 8] - memory size
;dword[ebp+12] - pointer to memory
;word[ebp+16] - options: element index
;word[ebp+18] - options: 2*(add mode)+(init mode)
;dword[ebp+20] - pointer to 'TreeList' struct
;output:
;dword[ebp+ 8] - error code
align 4
tl_load_mem:
push ebp
mov ebp,esp
push eax ebx ecx edx edi esi
mov esi,dword[ebp+12]
mov edi,dword[ebp+20]
mov dword[ebp+20],0 ;return error code
xor ecx,ecx
mov cx,word[ebp+16]
cmp cx,0 ;load in array mode
je @f
; push dword edi
; push dword esi
; call tl_get_mem_size ;берем размер ранее сохранённых данных
; pop ebx
; add esi,ebx
.beg_cycle:
cmp dword[esi],'tree'
jne .no_tree
xor ebx,ebx
mov bx,word[esi+4]
add bx,8
imul ebx,dword[esi+6]
add ebx,tl_save_load_heder_size
add esi,ebx
loop .beg_cycle
@@:
cmp dword[esi],'tree'
jne .no_tree
bt word[ebp+18],1 ;load in add mode
jc @f
stdcall tl_info_clear, dword edi
@@:
xor ebx,ebx
mov bx,word[esi+4] ;info_size
cmp bx,tl_info_size
je @f
or dword[ebp+20],tl_err_load_info_size
@@:
mov ecx,dword[esi+6] ;count nodes
cmp ecx,1
jl .end_f
mov edx,esi ;save header pointer
add esi,tl_save_load_heder_size
cld
@@: ;load node params
mov eax,dword[esi+4]
ror eax,16 ;eax - options (type; lev; clo)
add esi,8
stdcall tl_node_add, esi,eax,edi
stdcall tl_cur_next, edi
;...
add esi,ebx
loop @b
bt word[ebp+18],1 ;load in add mode
jc .no_tree
mov eax,dword[edx+14] ;set cursor pos
mov tl_cur_pos,eax
mov eax,dword[edx+22] ;set scroll pos
mov ebx,tl_p_scrol
cmp ebx,0
je .end_f
mov dword[ebx+sb_offs_position],eax
stdcall scroll_bar_vertical.draw, ebx
jmp .end_f
.no_tree:
mov dword[ebp+20],tl_err_load_caption
.end_f:
pop esi edi edx ecx ebx eax
pop ebp
ret 12
;input:
;dword[ebp+ 8] - pointer to memory
;dword[ebp+12] - pointer to 'TreeList' struct
;output:
;dword[ebp+ 8] - error code
align 4
tl_get_mem_size: ;берет размер памяти занятой функцией tl_save_mem при сохранении элементов
push ebp
mov ebp,esp
push ebx edi esi
mov esi,dword[ebp+ 8]
mov edi,dword[ebp+12]
@@:
cmp dword[esi],'tree'
jne @f
xor ebx,ebx
mov bx,word[esi+4]
add bx,8 ;размер дополнительной информации об узле (индекс записи; индекс иконки, уровень, ...)
imul ebx,dword[esi+6]
add ebx,tl_save_load_heder_size
add esi,ebx
jmp @b
@@:
sub esi,dword[ebp+ 8]
mov dword[ebp+12],esi ;возвращаем размер блока памяти
pop esi edi edx
pop ebp
ret 4
;ascii scan key
; 13 28 Enter
; 32 57 Space
; 178 72 Up
; 177 80 Down
; 176 75 Left
; 179 77 Right
; 182 83 Delete
; 184 73 Pg Up
; 183 81 Pg Dn
tl_key_ascii db 13,32,178,177,176,179,182,184,183
tl_key_scan db 28,57, 72, 80, 75, 77, 83, 73, 81
txt_capt_cur db '‘ва®Є  ',0
txt_capt_otm db 'Ћв¬Ґ­л ',0
;этот код не мой, он преобразует число в строку
;input:
; eax = value
; edi = string buffer
align 4
tl_convert_to_str:
pushad
mov dword[edi+1],0x20202020
call .str
popad
ret
align 4
.str:
mov ecx,0x0a ;задается система счисления изменяются регистры ebx,eax,ecx,edx входные параметры eax - число
;преревод числа в ASCII строку взодные данные ecx=система счисленя edi адрес куда записывать, будем строку, причем конец переменной
cmp eax,ecx ;сравнить если в eax меньше чем в ecx то перейти на @@-1 т.е. на pop eax
jb @f
xor edx,edx ;очистить edx
div ecx ;разделить - остаток в edx
push edx ;положить в стек
;dec edi ;смещение необходимое для записи с конца строки
call .str;перейти на саму себя т.е. вызвать саму себя и так до того момента пока в eax не станет меньше чем в ecx
pop eax
@@: ;cmp al,10 ;проверить не меньше ли значение в al чем 10 (для системы счисленя 10 данная команда - лишная))
;sbb al,$69 ;- честно данная инструкция меня заставляет задуматься т.е. я не знаю как это работает
;das ;после данной команды как бы происходит уменьшение al на 66h (в книге написано другое)
or al,0x30 ;данная команда короче чем две выше
stosb ;записать элемент из регистра al в ячеку памяти es:edi
ret ;вернуться очень интересный ход т.к. пока в стеке храниться кол-во вызовов то столько раз мы и будем вызываться
}