kolibrios/programs/develop/libraries/box_lib/trunk/tree_list.mac
IgorA c2cbea2674 changed the function of the opening of Tile when specifying non-existent path
git-svn-id: svn://kolibrios.org@1441 a494cfbc-eb01-0410-851d-a64ba20cac60
2010-03-26 17:16:07 +00:00

2470 lines
58 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
; файл последний раз изменялся 26.03.2010 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
tl_info_size equ word[edi +4] ;размер данных выделяемых для каждого узла (пользовательськие данные + текст для подписи)
tl_info_max_count equ dword[edi+6] ;максимальное количество узлов, которые можно добавить в элемент
tl_style equ dword[edi+10] ;стили элемента
tl_data_nodes equ dword[edi+14] ;указатель на структуры узлов
tl_data_img equ dword[edi+18] ;указатель на изображения с иконками узлов
tl_img_cx equ word[edi+22] ;ширина иконок
tl_img_cy equ word[edi+24] ;высота иконок
tl_data_img_sys equ dword[edi+26] ;указатель на системные изображения (стрелки, плюсики)
tl_ch_tim equ dword[edi+30] ;количество изменений в файле
tl_tim_undo equ dword[edi+38] ;количество отмененных действий
tl_cur_pos equ dword[edi+42] ;позиция курсора
tl_col_bkg equ dword[edi+46] ;цвет фона
tl_col_zag equ dword[edi+50] ;цвет заголовка
tl_col_txt equ dword[edi+54] ;цвет текста
tl_box_left equ dword[edi+58]
tl_box_top equ dword[edi+62]
tl_box_width equ dword[edi+66]
tl_box_height equ dword[edi+70]
tl_capt_cy equ word[edi+74] ;высота подписи
tl_info_capt_offs equ word[edi+76] ;сдвиг для начала текста (подписи узла)
tl_info_capt_len equ word[edi+78] ;длинна текста подписи узла (если = 0 то до конца структуры)
tl_el_focus equ dword[edi+80] ;указатель на структуру элемента в фокусе
tl_p_scrol equ dword[edi+84] ;указатель на структуру скроллинга
tl_on_press equ dword[edi+96] ;указатель на функцию, которая вызывается при нажатии Enter
;константы стиля
tl_key_no_edit equ 1b ;элемент нельзя редактировать на клавиатуре (изменять уровни, удалять)
tl_draw_par_line equ 10b ;рисовать линии к родительскому узлу
tl_list_box_mode equ 100b ;стиль не отображает уровни (как в ListBox все одного уровня)
;константы для функций
tl_err_save_memory_size equ 10b ;не хватает памяти для сохранения элемента
tl_err_load_caption equ 1b ;в памяти нет заголовка 'tree'
tl_err_load_info_size equ 100b ;не совпадает размер информационной структуры при открытии
tl_load_mode_add equ 0x20000 ;опция считывания в режиме добавления информации
tl_save_load_heder_size equ 26 ;размер заголовка для записи/чтения элементов
;data_info dd ? ;+ 0 указатель на основные даные
;ls_tim dd ? ;+34 время последнего сохранения
;on_activate dd ? ;+92 указатель на функцию при активировании узла
macro use_tree_list
{
;-----------------------------------------------------------------------------
;функция для выделения памяти
;input:
; ecx = size data
;otput:
; eax = pointer to memory
align 4
mem_Alloc:
push ebx
mov eax,68
mov ebx,12
int 0x40
pop ebx
ret
;-----------------------------------------------------------------------------
;функция для освобождения памяти
;input:
; ecx = pointer to memory
align 4
mem_Free:
push eax ebx
cmp ecx,0
jz @f
mov eax,68
mov ebx,13
int 0x40
@@:
pop ebx eax
ret
align 4
tl_data_init: ;выделние памяти для структур списка и основной информации (конструктор)
push ebp
mov ebp,esp
push eax ecx edi
mov edi,dword[ebp+8]
xor ecx,ecx
mov cx,tl_info_size
imul ecx,tl_info_max_count
call mem_Alloc
mov dword[edi],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
call mem_Alloc
mov tl_data_nodes,eax ;копируем указатель на полученую память в структуру
push dword edi
call tl_info_clear
;настройки дочернего скроллинга
cmp tl_p_scrol,0
je @f
mov eax,tl_p_scrol
;*** цветовые настройки ***
mov ecx,tl_col_bkg
mov dword[eax+28],ecx ;+28 .bckg_col
mov ecx,tl_col_zag
mov dword[eax+32],ecx ;+32 .frnt_col
mov ecx,tl_col_txt
mov dword[eax+36],ecx ;+32 .line_col
;*** настройки размеров ***
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
@@:
pop edi ecx eax
pop ebp
ret 4
align 4
tl_data_clear: ;очистка памяти элемента (деструктор)
push ebp
mov ebp,esp
push ecx edi
mov edi,dword[ebp+8]
cmp tl_data_img,0
je @f
mov ecx,tl_data_img
call mem_Free ;чистка системных иконок
@@:
cmp tl_data_img_sys,0
je @f
mov ecx,tl_data_img_sys
call mem_Free ;чистка системных иконок
@@:
mov ecx,dword[edi]
call mem_Free
mov ecx,tl_data_nodes
call mem_Free
pop edi ecx
pop ebp
ret 4
align 4
tl_info_clear: ;очистка списка (информации)
push ebp
mov ebp,esp
push eax ecx edi
mov edi,dword[ebp+8]
mov tl_ch_tim,0
mov dword[edi+34],0 ;ls_tim
mov tl_tim_undo,0
mov tl_cur_pos,0
;xor ecx,ecx
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+24],0 ;+24 .position
call tb_scrol_resize
@@:
pop edi ecx eax
pop ebp
ret 4
align 4
tl_key: ;реакция на клавиатуру
push ebp
mov ebp,esp
push ebx ecx edi
mov edi,dword[ebp+8]
mov ebx,tl_el_focus
cmp dword[ebx],edi
jne .no_focus ;элемент не в фокусе
push eax
mov eax,66
mov ebx,2
int 0x40 ;получить режим ввода с клавиатуры
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
push dword edi
call tl_node_close_open
@@:
cmp ah,byte[ecx+2] ;Up
jne @f
push dword edi
call tl_cur_perv
@@:
cmp ah,byte[ecx+3] ;Down
jne @f
push dword edi
call tl_cur_next
@@:
cmp ah,byte[ecx+7] ;Page Up
jne @f
push dword edi
call tl_cur_page_up
@@:
cmp ah,byte[ecx+8] ;Page Down
jne @f
push dword edi
call tl_cur_page_down
@@:
bt tl_style,0 ;tl_key_no_edit
jc .no_edit
cmp ah,byte[ecx+4] ;Left
jne @f
push dword edi
call tl_node_lev_dec
mov bx,1
@@:
cmp ah,byte[ecx+5] ;Right
jne @f
push dword edi
call tl_node_lev_inc
mov bx,1
@@:
cmp ah,byte[ecx+6] ;Delete
jne @f
push dword edi
call tl_node_delete
mov bx,1
@@:
.no_edit:
cmp bx,1
jne .no_focus
push dword edi
call tl_draw
.no_focus:
pop edi ecx ebx
pop ebp
ret 4
align 4
tl_mouse: ;реакция на мышь
push ebp
mov ebp,esp
pushad
mov edi,dword[ebp+8]
mov eax,37
mov ebx,1
int 0x40
mov ebx,tl_box_left
shl ebx,16
cmp eax,ebx ;левая граница окна
jl .no_in_wnd ;.test_scroll
mov ebx,tl_box_left
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
mov eax,37
mov ebx,2
int 0x40
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+24] ;добавляем скроллинг на верху
@@:
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
push dword edi
call tl_node_close_open
.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+16] ;+16 .max_area
cmp eax,dword[edx+20] ;+20 .cur_area
jbe .no_in_wnd ;все узлы попадают в окно скроллинга
push dword edx
call scroll_bar_vertical.mouse ;scrollbar_ver_mouse
cmp dword[edx+40],0 ;+40 .redraw
je @f
mov dword[edx+40],0 ;+40 .redraw
push dword edi
call tl_draw ;произошли изменения скроллинга
@@:
cmp dword[edx+46],0 ;+46 .delta2
jne .no_draw ;попали на скроллинг - не снимаем фокус с TreeList
;-------------------------------------------------------------------------------
.no_in_wnd: ;не попали в окно - потеря фокуса (при условии что фокус был на данном эелементе)
mov eax,37 ;проверяем нажатость любых кнопок
mov ebx,2
int 0x40
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
pop ebp
ret 4
align 4
tl_info_undo: ;отмена действия
push ebp
mov ebp,esp
push eax edi
mov edi,dword[ebp+8]
mov eax,tl_tim_undo
cmp tl_ch_tim,eax
jbe @f
inc tl_tim_undo
call tb_scrol_resize ;обработка скроллинга
@@:
pop edi eax
pop ebp
ret 4
align 4
tl_info_redo: ;повтор действия
push ebp
mov ebp,esp
push edi
mov edi,dword[ebp+8]
cmp tl_tim_undo,1
jl @f
dec tl_tim_undo
call tb_scrol_resize ;обработка скроллинга
@@:
pop edi
pop ebp
ret 4
align 4
tl_info_set_undo: ;удаление отмененных действий
; push ebp
; mov ebp,esp
; push edi
; mov edi,dword[ebp+8]
; mov [dragk],0 ;заканчиваем выделение от клавиатуры
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:
; pop edi
; pop ebp
; ret 4
ret
align 4
tl_draw: ;вывод списка на экран
push ebp
mov ebp,esp
pushad
;draw dir_list main rect
mov edi,dword[ebp+8]
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
mov eax,13
int 0x40 ;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+24],0 ;если скроллинг на верху, выходим
je .end_c1
@@:
call tl_iterat_next
cmp edx,ecx
jle .end_draw
inc eax
cmp eax,dword[esi+24]
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 ;если нет скроллинга выходим
push dword edi
call scroll_bar_vertical.draw
.end_draw:
popad
pop ebp
ret 4
;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
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
tl_move_max_clo_par: ;находит родительский закрытый узел максимального уровня
push 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
pop ebx eax
ret
;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
tl_draw_cursor: ;рисуем курсор на экране
push 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
mov eax,13
int 0x40 ;рисуем простой прямоугольник, т.к. нет системных иконок
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:
mov eax,7
int 0x40 ;рисуем иконку курсора
.end_f:
pop esi edx ecx ebx eax
ret
;input:
; edi = pointer to TreeInfo struct
; esi = coord bottom border
align 4
tl_draw_null_cursor: ;стираем курсор на экране
push 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
mov eax,13
int 0x40 ;рисуем простой прямоугольник с фоновым цветом
.end_f:
pop esi edx ecx ebx eax
ret
;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+24]
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
tl_draw_node: ;рисует узел с: картинкой, подписью, иконкой открытия/закрытия и линиями к родит. узлу
push 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];get level
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
mov eax,13
int 0x40 ;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
mov eax,7
int 0x40 ;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:
pop esi edx ecx ebx eax
ret
;input:
; ecx = pointer to 1 node struct
; edx = pointer to some node struct
;...
align 4
tl_draw_node_icon_opn_clo: ;рисует иконки открытого или закрытого узла (обычно + или -)
push 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
mov eax,13
int 0x40 ;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
mov eax,7
int 0x40 ;draw minus icon '-'
@@:
pop esi edx ecx ebx eax
ret
;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
mov eax,13
int 0x40 ;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
mov eax,7
int 0x40 ;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,dword[edi]
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
mov eax,4
int 0x40
@@:
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
loop @b
@@:
sub eax,esi
ret
;input:
;dword[ebp+ 8] - pointer to node info
;dword[ebp+12] - options
;dword[ebp+16] - pointer to 'TreeList' struct
align 4
tl_node_add: ;добавить узел
push ebp
mov ebp,esp
push eax ebx ecx edx edi
mov edi,dword[ebp+16]
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 cx,word[ebp+14] ;get type
mov word[edx],cx
mov cl,byte[ebp+13]
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[ebp+12]
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,dword[edi]
mov edi,dword[ebp+8] ;pointer to node data
xchg edi,esi
rep movsb
mov esi,edi
mov edi,dword[ebp+16] ;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
@@:
pop edi edx ecx ebx eax
pop ebp
ret 12
;input:
; edi = pointer to TreeInfo struct
align 4
tb_scrol_resize:
push 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+20],eax ;+20 .cur_area
mov dword[edx+16],ecx ;+16 .max_area
push dword edx ;pointer to scroll struct
call scroll_bar_vertical.draw
@@:
pop edx ecx eax
ret
;input:
;dword[ebp+ 8] - pointer to node info
;dword[ebp+12] - pointer to 'TreeList' struct
align 4
tl_node_set_data:
push ebp
mov ebp,esp
push eax ecx edx edi esi
mov edi,dword[ebp+12]
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,dword[edi]
mov edi,eax
mov esi,dword[ebp+8] ;pointer to node data
rep movsb
mov esi,edi
mov edi,dword[ebp+12] ;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:
@@:
pop esi edi edx ecx eax
pop ebp
ret 8
;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,dword[edi]
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 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 ecx eax
pop ebp
ret 4
;input:
; edi = pointer 'tl' struct
;output:
; eax = index of current node
align 4
tl_get_cur_node_index: ;берет позицию под курсором
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
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
pop edx ecx
ret
;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
tl_node_delete: ;удалить узел
push ebp
mov ebp,esp
push eax edx edi
mov edi,dword[ebp+8]
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 ;обработка скроллинга
@@:
pop edi edx eax
pop ebp
ret 4
align 4
tl_cur_beg: ;поставить курсор на первый узел
push ebp
mov ebp,esp
push edi
mov edi,dword[ebp+8]
mov tl_cur_pos,0
cmp tl_p_scrol,0
je @f
mov edi,tl_p_scrol
mov dword[edi+24],0
push dword edi
mov edi,dword[ebp+8]
call scroll_bar_vertical.draw
@@:
pop edi
pop ebp
ret 4
align 4
tl_cur_next: ;перенести курсор на 1 позицию ниже
push ebp
mov ebp,esp
push eax ebx edi esi
mov edi,dword[ebp+8]
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+24] ;.position +24
cmp tl_cur_pos,eax
jl @f
inc dword[ebx+24] ;.position +24
push dword ebx
call scroll_bar_vertical.draw
mov edi,dword[ebp+8] ;restore edi
push dword edi
call tl_draw ;полная перерисовка окна
jmp .no_redraw
@@:
mov edi,dword[ebp+8] ;restore edi
call tl_draw_cursor ;перерисовка курсора
call tl_draw_caption_cur_pos
.no_redraw:
pop esi edi ebx eax
pop ebp
ret 4
;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
align 4
tl_cur_perv: ;перенести курсор на 1 позицию выше
push ebp
mov ebp,esp
push eax edi esi
mov edi,dword[ebp+8]
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+24],0 ;если скроллинг на верху, выходим
je @f
mov edi,tl_cur_pos
cmp edi,dword[eax+24] ;если курсор ушел выше скроллинга, тогда опускаем скроллинг
jge @f
dec dword[eax+24]
push dword eax
mov edi,dword[ebp+8]
call scroll_bar_vertical.draw
mov edi,dword[ebp+8] ;restore edi
push dword edi
call tl_draw ;полная перерисовка окна
jmp .no_redraw
@@:
mov edi,dword[ebp+8] ;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:
pop esi edi eax
pop ebp
ret 4
align 4
tl_cur_page_up: ;перенести курсор на 1 страницу выше
push ebp
mov ebp,esp
push eax edi esi
mov edi,dword[ebp+8]
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+24],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+24],eax
jl @f
sub dword[esi+24],eax
jmp .scroll
@@:
mov dword[esi+24],0
.scroll:
;перерисовки окна и скроллинга
push dword edi
call tl_draw ;draw window
push dword esi
call scroll_bar_vertical.draw
.no_redraw:
pop esi edi eax
pop ebp
ret 4
align 4
tl_cur_page_down: ;перенести курсор на 1 страницу ниже
push ebp
mov ebp,esp
push eax ebx ecx edi esi
;eax - кол-во строк на странице
;ebx - макс. позиция курсора
;ecx - макс. позиция скроллинга
mov edi,dword[ebp+8]
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+24],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+24],eax ;перемещаем скроллинг
cmp dword[esi+24],ecx
jl @f
mov dword[esi+24],ecx
@@:
;перерисовки окна и скроллинга
push dword edi
call tl_draw ;draw window
push dword esi
call scroll_bar_vertical.draw
.no_redraw:
pop esi edi ecx ebx eax
pop ebp
ret 4
align 4
tl_node_close_open: ;открыть/закрыть узел (работает с узлами которые имеют дочерние узлы)
push ebp
mov ebp,esp
push eax edx edi
mov edi,dword[ebp+8]
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 ;обработка скроллинга
push dword edi
call tl_draw ;обновление окна
@@:
pop edi edx eax
pop ebp
ret 4
align 4
tl_node_lev_inc: ;увеличить уровень
push ebp
mov ebp,esp
push eax ecx edx edi
mov edi,dword[ebp+8]
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] ;увеличиваем значение узла
@@:
pop edi edx ecx eax
pop ebp
ret 4
align 4
tl_node_lev_dec: ;уменьшить уровень
push ebp
mov ebp,esp
push eax edi
mov edi,dword[ebp+8]
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]
@@:
pop edi eax
pop ebp
ret 4
align 4
tl_node_move_up: ;перемещаем узел вверх
push ebp
mov ebp,esp
push eax ebx ecx edx edi esi
mov edi,dword[ebp+8]
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
@@:
pop esi edi edx ecx ebx eax
pop ebp
ret 4
align 4
tl_node_move_down: ;перемещаем узел вниз
push ebp
mov ebp,esp
push eax ebx ecx edx edi esi
mov edi,dword[ebp+8]
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:
push dword edi
call tl_cur_next
push dword edi
call tl_draw
@@:
pop esi edi edx ecx ebx eax
pop ebp
ret 4
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+24] ;+24 .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
push dword edi
push dword edx
call tl_node_poi_get_data
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
push dword edi
call tl_info_clear
@@:
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
@@:
;load node params
push dword edi
mov eax,dword[esi+4]
ror eax,16
push dword eax ;options (type; lev; clo)
add esi,8
push dword esi
call tl_node_add
push dword edi
call tl_cur_next
;...
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+24],eax ;+24 .position
push dword ebx ;pointer to scroll struct
call scroll_bar_vertical.draw
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 ;вернуться чень интересный ход т.к. пока в стеке храниться кол-во вызовов то столько раз мы и будем вызываться
}