Files
kolibrios/programs/develop/examples/editbox/trunk/editbox.mac
T
Alexey Teplov ( b192d9260a modify macros and optimization
git-svn-id: svn://kolibrios.org@483 a494cfbc-eb01-0410-851d-a64ba20cac60
2007-05-10 04:03:05 +00:00

677 lines
19 KiB
Plaintext

;Макрос для вывода основных функций которые испльзуются боксом
macro use_general_func
{
;debug_func
;----------------------------------------------------------
;--- процедура прорисовки выделеной части -----------------
;----------------------------------------------------------
.draw_shift:
test word ed_flags,ed_shift_bac ;установка флага, выделенной области
jz @f
mov ebp,shift_color
mov ebx,dword ed_shift_pos
call .sh_cl_
@@: ret
;----------------------------------------------------------
;--- процедура прорисовки текста --------------------------
;----------------------------------------------------------
.draw_text:
;--- вычисляем, сколько помещается символов ---
;--- чтобы мусор не рисовать ---
call .get_n
mov esi,ed_size
mov ebx,ed_offset
sub esi,ebx
cmp eax,esi
jae @F
mov esi,eax ;чтобы не выходить за пределы экрана
;--- рисуем текст ---
@@: mov eax,4
mov ebx,ed_left
mov edx,ed_offset
add ebx,2
shl ebx,16
mov bx,ed_top
add ebx,4
mov ecx,ed_text_color
add edx,ed_text
mcall
ret
;----------------------------------------------------------
;--- процедура прорисовки фона ----------------------------
;входные данные
;eax
;edx - color
;----------------------------------------------------------
;вход только цвет edx
.draw_bg:
mov ebx,ed_left
add ebx,1
shl ebx,16
mov bx,ed_width
sub ebx,1
mov edx,ed_color
.draw_bg_eax:
mov ecx,ed_top
mov eax,13
add ecx,1
shl ecx,16
mov cx,ed_height
dec ecx
mcall
ret
;----------------------------------------------------------
;--- процедура получения количества символов в текущей щирине компонента
;----------------------------------------------------------
.get_n:
mov eax,ed_width ;получем ширину компонента
xor edx,edx ;результат распологается в паре edx:eax в eax - остаток
sub eax,4 ;вычтим 4
mov ebx,6 ;загрузми делитель
div ebx ;размделим на 6
ret
;----------------------------------------------------------
;--- процедура рисования курсора --------------------------
;----------------------------------------------------------
;входные ebp- цвет
.clear_cursor:
mov edx,ebp
mov ebx,cl_curs_x
mov ecx,cl_curs_y
jmp .draw_curs
.draw_cursor:
mov edx,ed_text_color
mov ebx,ed_pos
mov ecx,ed_offset
sub ebx,ecx
lea ebx,[ebx*2+ebx]
shl ebx,1
;imul ebx,6
add bx,ed_left
mov ecx,ed_top
inc ebx
add ecx,2
mov ebp,ebx
shl ebx,16
mov bx,bp
mov ebp,ecx
shl ecx,16
mov cx,bp
add cx,ed_height-4
mov cl_curs_x,ebx
mov cl_curs_y,ecx
.draw_curs:
mcall 38
ret
;----------------------------------------------------------
;--- процедура рисования рамки ----------------------------
;----------------------------------------------------------
.draw_border:
;--- цвет рамки ---
test word ed_flags,ed_focus
mov edx,ed_focus_border_color
jne @f
mov edx,ed_blur_border_color
@@:
;--- сверху ---
mov eax,38
mov ebx,ed_left
mov ecx,ebx
shl ebx,16
mov bx,cx
add bx,ed_width
mov ecx, ed_top
mov esi,ecx
shl ecx,16
mov cx,si
mcall
;--- снизу ---
mov esi,ecx
add ecx,ed_height
mov ebp,ecx
shl ecx,16
mov cx,bp
mcall
;--- слева ---
mov cx,si
mov ebp,ebx
sub bx,ed_width
mcall
;--- справа ---
mov ebx,ebp
shl ebx,16
mov bx,bp
mcall
ret
;----------------------------------------------------------
;--- проверка, зашел ли курсор за границы и, если надо, ---
;--- изменяем смещение ------------------------------------
;--- если смещение было установка флага ed_offset_cl иначе
; если ничего не изменилось то выставление ed_offset_fl
; в общей битовой маррице состояния компонентов word ed_flags
;----------------------------------------------------------
.check_offset:
pusha
mov ecx,ed_pos
mov ebx,ed_offset
cmp ebx,ecx
ja .sub_8
push ebx
call .get_n ;получим кол-во символов в паре регистров edx:eax
pop ebx
mov edx,ebx
add edx,eax ;ed_offset+width editbox
inc edx ;необходимо для номального положения курсора в крайней левой позиции
cmp edx,ecx
ja @f
mov edx,ed_size
cmp edx,ecx
je .add_end
sub edx,ecx
cmp edx,8
jbe .add_8
add ebx,8
jmp .chk_d
.sub_8: cmp ecx,0
je .sub_min
cmp ebx,8
jbe .sub_min
sub ebx,8 ;ebx=ed_offset
jmp .chk_d
.sub_min:
xor ebx,ebx
jmp .chk_d
.add_end:sub edx,eax
mov ebx,edx
jmp .chk_d
.add_8: add ebx,edx
.chk_d: mov ed_offset,ebx
call .draw_bg
and word ed_flags,ed_offset_cl
edit_ex
@@:
or word ed_flags,ed_offset_fl
edit_ex
}
macro use_key_func
{
;Обработка Shift для снятия выделения неизвестной области
.shift: ;;;;;;;SHIFT
test word ed_flags,ed_shift
je .f_exit
@@: mov ebp,shift_color
or word ed_flags,ed_shift_bac ;установка флага, выделенной области
mov ebx,dword ed_shift_pos
call .sh_cl_
jmp .draw_cursor_text
;;;;;;;;;;;;;;;;;;;;;
.f_exit:call .check_offset
and word ed_flags,ed_shift_cl
call .enable_null
jmp .draw_cursor_text
.sh_cl_:
;;;;;;SHIFT end
;обработка очистки, при левом - правом движении выделения
;для обработки снятия выделения
;входные параметры ebp=color ebx=ed_shift_pos
mov eax,dword ed_pos
cmp eax,ebx
jae .sh_n
push eax ;меньшее в eax
push ebx ;большее
jmp .sh_n1
;если иначе
.sh_n: push ebx
push eax
.sh_n1:
call .check_offset
call .get_n
mov edx,eax ;size of ed_box
mov ecx,ed_offset
add eax,ecx ;eax = w_off= ed_offset+width
mov edx,eax ;save
pop ebx ;большее
pop eax ;меньшее
cmp eax,ecx ;сравнение с меньшего с offset.
jae .f_f ;если больше
xor eax,eax
cmp edx,ebx ;cравним размер w_off с большим
jb @f
sub ebx,ecx
jmp .nxt_f
@@: mov ebx,edx
sub ebx,ecx
jmp .nxt_f
.f_f:
sub eax,ecx
cmp edx,ebx ;cравним размер w_off с большим
jle @f
sub ebx,ecx
sub ebx,eax
jmp .nxt_f
@@:
mov ebx,edx
sub ebx,ecx
sub ebx,eax
.nxt_f:
mov edx,ebx
lea ebx,[eax*2+eax]
shl ebx,1
add ebx,ed_left
inc ebx
shl ebx,16
lea ecx,[edx*2+edx]
shl ecx,1
mov bx,cx
inc ebx
mov edx,ebp;shift_color
call .draw_bg_eax
@@: call .enable_null
ret
;;;;;;;;;;;;;;;;;;;;;
;Установка- снятие выделения в один символ
;;;;;;;;;;;;;;;;;;;;;
.drw_sim:
mov eax,dword ed_pos
call .draw_rectangle ;нарисовать прямоугольник с заданным цветом
jmp @b
;;;;;;;;;;;;;;;;;;;;;
;Фукция установки выделения при движения влево и вправо и нажатии shift
;Логика:
;;;;;;;;;;
.draw_wigwag:
;функция установки переменных
mov ebp,shift_color
call .clear_cursor
or word ed_flags,ed_shift_bac ;установка флага, выделенной области
mov ebp,shift_color
mov eax,dword ed_pos
test word ed_flags,ed_left_fl
jz .low
jmp @f
;;;;;;;;;;
;Фукция удаления выделения при движения влево и вправо и нажатии shift
;Логика:
;;;;;;;;;;
.draw_wigwag_cl:
;функция установки переменных
mov ebp,ed_color
call .clear_cursor
mov ebp,ed_color
mov eax,dword ed_pos
test word ed_flags,ed_left_fl
jz .low
@@: call .draw_rectangle ;нарисовать прямоугольник закрашиваемой области
ret
.low: dec eax
jmp @b
;входной параметр ebx - ed_pos
.sh_first_sh:
test word ed_flags,ed_shift
je @f
mov dword ed_shift_pos_old,ebx
test word ed_flags,ed_shift_on
jne @f
mov dword ed_shift_pos,ebx
or word ed_flags,ed_shift_on
@@: ret
;Обработка крайних положений в editbox при нажатом shift
;производит снятие выделение, если нет shift
;иначе вообще выходит
.sh_st_of:
test word ed_flags,ed_shift
jne @f
test word ed_flags,ed_shift_bac
je @f
mov ebp,ed_color
mov ebx,dword ed_shift_pos
call .sh_cl_ ;очистка выделеного фрагмента
and word ed_flags,ed_shift_cl ; очистка от того что убрали выделение
jmp .draw_cursor_text
@@:
and word ed_flags,ed_shift_off
edit_ex
;проверка состояния shift был ли он нажат раньше?
.sh_enable:
test word ed_flags,ed_shift
jne .sh_ext_en ;нарисовать закрашеный прямоугольник
test word ed_flags,ed_shift_bac
je @f
call .check_offset
mov ebp,ed_color
mov ebx,dword ed_shift_pos
call .sh_cl_ ;очистка выделеного фрагмента
call .draw_wigwag_cl
and word ed_flags,ed_shift_cl ; 1вар не нужно
ret
@@: mov ebp,ed_color
call .clear_cursor
call .check_offset
ret
.sh_ext_en:
call .check_offset
test word ed_flags,ed_offset_fl
je @f
;Рисование закрашеных прямоугольников и очистка их
mov eax,dword ed_shift_pos
mov ebx,dword ed_pos
mov ecx,dword ed_shift_pos_old
;проверка и рисование закрашеных областей
cmp eax,ecx
je .1_shem
jb .smaller
cmp ecx,ebx
ja .1_shem
call .draw_wigwag_cl ;clear
jmp .sh_e_end
.smaller:
cmp ecx,ebx
jb .1_shem
call .draw_wigwag_cl ;clear
jmp .sh_e_end
;alike =
.1_shem: call .draw_wigwag
.sh_e_end: and word ed_flags,ed_shift_off
ret
@@: mov ebp,shift_color
mov ebx,dword ed_shift_pos
call .sh_cl_
jmp .sh_e_end
;функция для обработки shift при нажатии home and end
.sh_home_end:
mov ebp,ed_color
call .clear_cursor
test word ed_flags,ed_shift_bac
je @f
mov ebp,ed_color
mov ebx,dword ed_shift_pos_old
call .sh_cl_
@@: test word ed_flags,ed_shift
je .sh_exit_ ;выйти
mov ebp,shift_color
mov ebx,dword ed_shift_pos
call .sh_cl_
or word ed_flags,ed_shift_bac ;установка флага, выделенной области
jmp .sh_e_end
.sh_exit_: call .check_offset
ret
;функция внесения 0 по адресу ed_size+1
.enable_null:
pusha
mov eax,ed_size
mov ebx,ed_text
test eax,eax
add eax,ebx
jne @f
inc eax
@@: xor ebx,ebx
mov [eax],bl
edit_ex
;- удаление символа
;Входные данные edx=ed_size;ecx=ed_pos
.del_char:
mov esi,ed_text
test word ed_flags,ed_shift_on
je @f
mov eax,dword ed_shift_pos
mov ebx,esi
cmp eax,ecx
jae .dh_n
mov ed_pos,eax ;что бы не было убегания курсора
mov ebp,ecx
sub ebp,eax
add ebx,eax ;eax меньше
sub edx,ecx
add esi,ecx
mov dword ed_shift_pos,ebp
jmp .del_ch_sh
;если иначе
.dh_n:
mov ebp,eax
sub ebp,ecx
add ebx,ecx
sub edx,eax
add esi,eax
mov dword ed_shift_pos,ebp
jmp .del_ch_sh
@@: add esi,ecx ;указатель + смещение к реальному буфферу
mov ebx,esi
inc esi
cld
sub edx,ecx
.del_ch_sh:
push edi
mov edi,ebx
@@:
lodsb
stosb
dec edx
jns @b
pop edi
ret
;вычислить закрашиваемую область
;соглашение в ebp - передается ed_size
.clear_bg:
call .get_n ;получить размер в символах ширины компонента
push eax
mov ebx,ed_offset
add eax,ebx ;eax = w_off= ed_offset+width
mov ebx,ebp ;ed_size
cmp eax,ebx
jb @f
mov eax,ed_pos
sub ebx,eax
mov ecx,ed_offset
sub eax,ecx
jmp .nxt
@@: mov ebx,ed_pos
push ebx
sub eax,ebx
mov ebx,eax ;It is don't optimal
pop eax ;ed_pos
mov ecx,ed_offset
sub eax,ecx
.nxt:
mov ebp,eax ;проверка на выход закрашиваемой области за пределы длины
add ebp,ebx
pop edx
cmp ebp,edx
je @f
inc ebx
@@: mov edx,ebx
lea ebx,[eax*2+eax]
shl ebx,1
add ebx,ed_left
inc ebx
shl ebx,16
lea ecx,[edx*2+edx]
shl ecx,1
mov bx,cx
mov edx,ed_color
call .draw_bg_eax
ret
;;;;;;;;;;;;;;;;;;;
;;; Обработка примитивов
;;;;;;;;;;;;;;;;;;;;
;Нарисовать прямоугольник, цвет передается в ebp
;входные параметры:
;eax=dword ed_pos
;ebp=-цвет ed_color or shift_color
.draw_rectangle:
mov ecx,dword ed_offset
sub eax,ecx
lea ebx,[eax*2+eax]
shl ebx,1
inc ebx
add ebx,ed_left
shl ebx,16
mov bx,6
mov edx,ebp
call .draw_bg_eax
ret
;;;;;;;;;;;;;;;;;;
;;Проверка нажат ли shift
;;;;;;;;;;;;;;;;;;
.check_shift:
pusha ;сохраним все регистры
mcall 66,3,1
test al,0x03
je @f
or word ed_flags,ed_shift ;установим флаг
@@:edit_ex
}
;макрос клавиш на которые происходит реакция
macro use_key_process backspase,delete,left,right,home,end,insert
{
if backspase eq
else
cmp ah,8
jz .backspace
end if
if delete eq
else
cmp ah,0xb6
jz .delete
end if
if left eq
else
cmp ah,176
jz .left
end if
if right eq
else
cmp ah,179
jz .right
end if
if home eq
else
cmp ah,180
jz .home
end if
if home eq
else
cmp ah,181
jz .end
end if
if insert eq
else
cmp ah,185 ;insert
jz .insert
end if
}
macro use_key_no_process up,down,esc
{
if up eq
else
cmp ah,177
jz .no_figure
end if
if down eq
else
cmp ah,178
jz .no_figure
end if
if esc eq
else
cmp ah,27 ;ESC - клавиша ))
jz .no_figure
end if
}
macro use_key_figures_only
{
test word ed_flags,ed_figure_only ; только цифры ?
jz @f
cmp ah,'0'
jb .no_figure
cmp ah,'9'
ja .no_figure
}
; Макрос выхода
macro edit_ex
{
popa
ret
}
macro debug
{
;----------- отладка
pushad
; mov dword [ed_buffer.2],0
; mov eax,edi
mov eax,dword [ed_buffer.2]
mov edi,ed_buffer.3
call .str
;рисование фона
mov eax,13
mov ebx,178*65536+70
mov ecx,28*65536+10
xor edx,edx
int 0x40
;вывод значения на экран
mov eax,4
mov ebx,180*65536+30
mov ecx,0x10DDBBCC
mov edx,ed_buffer.3
mov esi,8
int 0x40
popad
;----------- отладка
}
macro debug_func
{
.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 ;вернуться чень интересный ход т.к. пока в стеке храниться кол-во вызовов то столько раз мы и будем вызываться
}