Files
kolibrios/programs/develop/libraries/box_lib/trunk/editbox.mac
T
Marat Zakiyanov (Mario79) 2fa4df3549 Box_Lib - Editbox support for Clipboard (Ctrl + C|V)
git-svn-id: svn://kolibrios.org@4601 a494cfbc-eb01-0410-851d-a64ba20cac60
2014-03-01 19:33:34 +00:00

1442 lines
42 KiB
Plaintext

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Basic macros for use editbox ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
macro use_editbox_draw
{
edit_box:
.draw:
pushad
.draw_1:
;--- рисуем рамку ---
mov edi,dword [esp+36]
call .draw_border ; Функция стабильна
.draw_bg_cursor_text:
;--- изменяем смещение, если надо ---
call .check_offset ;вычисление позиции курсора стабильна
;--- рисуем внутреннюю область ---
call .draw_bg ;нарисовать прямоугольник рабочей области
;---- рисуем выделение, по shift если есть
call .draw_shift
.draw_cursor_text:
;--- рисуем курсор ---
;--- может его не надо рисовать ----
test word ed_flags,ed_focus
jz @f
call .draw_cursor
@@:
call .draw_text
; ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Общий выход из editbox для всех функций и пост обработчиков;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.editbox_exit:
popad
ret 4
}
macro use_editbox_key
{
;==========================================================
;=== обработка клавиатуры =================================
;==========================================================
edit_box_key:
pushad
mov edi,dword [esp+36]
test word ed_flags,ed_focus ; если не в фокусе, выходим
je edit_box.editbox_exit
test word ed_flags,ed_mouse_on
jne edit_box.editbox_exit
;--------------------------------------
; this code for Win-keys, works with
; kernel SVN r.3356 or later
push eax
push ebx
mcall 66,3
test ax,0x200 ; LWin
jnz .win_key_pressed
test ax,0x400 ; RWin
jz @f
.win_key_pressed:
pop ebx
pop eax
jmp edit_box.editbox_exit
@@:
pop ebx
pop eax
;--------------------------------------
;Проверка нажат shift ?
call edit_box_key.check_shift_ctrl_alt
;----------------------------------------------------------
;--- проверяем, что нажато --------------------------------
;----------------------------------------------------------
cmp ah,8
jz edit_box_key.backspace
cmp ah,0xb6
jz edit_box_key.delete
cmp ah,176
jz edit_box_key.left
cmp ah,179
jz edit_box_key.right
cmp ah,180
jz edit_box_key.home
cmp ah,181
jz edit_box_key.end
cmp ah,185 ;insert
jz edit_box_key.insert
; комбинации Ctrl + клавиша
test word ed_flags,ed_ctrl_on
jz @f
; проверка сканкода
ror eax,8
cmp ah,46 ; Ctrl + C
je edit_box_key.ctrl_c
cmp ah,47 ; Ctrl + V
je edit_box_key.ctrl_v
rol eax,8
@@:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Заглушка на обработку клавиш вверх и вниз т.е. при обнаружении этих кодов происходит выход из обработчика
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_key_no_process up,down,esc,enter,tab,numl,capsl,scrolll
;--- нажата другая клавиша ---
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Проверка установлен ли флаг при котором нужно выводить только цифры в нужном боксе, если такой необходимости нет, нужно закоментировать макрос
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_key_figures_only
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;проверка на shift, был ли нажат
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
are_key_shift_press
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; проверяем, находится ли курсор в конце + дальнейшая обработка
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
are_key_cur_end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Обработка клавиш insert,delete.backspace,home,end,left,right
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_work_key
}
macro use_editbox_mouse
{
;==========================================================
;=== обработка мыши =======================================
;==========================================================
;save for stdcall ebx,esi,edi,ebp
edit_box_mouse:
pushad
mov edi,dword [esp+36]
;debug
;----------------------------------------------------------
;--- получаем состояние кнопок мыши -----------------------
;----------------------------------------------------------
mcall 37,2
;----------------------------------------------------------
;--- проверяем состояние ----------------------------------
;----------------------------------------------------------
test eax,1
jnz edit_box_mouse.mouse_left_button
and word ed_flags,ed_mouse_on_off
mov ebx,dword ed_mouse_variable
push 0
pop dword [ebx]
; mov dword [ebx],ebx
jmp edit_box.editbox_exit
.mouse_left_button:
;----------------------------------------------------------
;--- блокировка от фокусировки в других боксах при попадании на них курсора
;----------------------------------------------------------
mov eax,dword ed_mouse_variable
push dword [eax]
pop eax
test eax,eax
jz @f
cmp eax,edi
je @f
jmp edit_box_mouse._blur
;----------------------------------------------------------
;--- получаем координаты мыши относительно 0 т.е всей области экрана
;----------------------------------------------------------
@@: mcall 37,1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Функция обработки мышки получение координат и проверка их + выделения
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_work_mouse
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Общие функции обработки
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_general_func
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Функции для работы с key
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_key_func
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Функции для работы с mouse
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_mouse_func
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Bit mask from editbox
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
}
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;ниже расположены функции которыми реализуется весь алгоритм
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Макрос для вывода основных функций которые используются боксом
macro use_general_func
{
;debug_func
;----------------------------------------------------------
;--- процедура прорисовки выделенной части -----------------
;----------------------------------------------------------
edit_box.draw_shift:
test word ed_flags,ed_shift_bac ;установка флага, выделенной области
jz @f
mov ebp,shift_color
mov ebx,dword ed_shift_pos
call edit_box_key.sh_cl_
@@: ret
;----------------------------------------------------------
;--- процедура прорисовки текста --------------------------
;----------------------------------------------------------
edit_box.draw_text:
;--- вычисляем, сколько помещается символов ---
;--- чтобы мусор не рисовать ---
call edit_box.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
add ebx,ed_top
mov ecx,ed_text_color
add ebx,4
add edx,ed_text
test word ed_flags,ed_pass
jz @f
call edit_box.draw_password
jmp .end_f
@@:
mcall
.end_f:
ret
txt_pass db '*',0
proc edit_box.draw_password
locals
s_len dw ? ;длина выводимого текста
endl
cmp esi,1
jl .end_f ;если строка пустая
mov [s_len],si
xor esi,esi
inc esi
lea edx,[txt_pass]
@@:
mcall
add ebx,6 shl 16 ;добавляем стандартную ширину символа
dec word[s_len]
cmp word[s_len],0
jg @b
.end_f:
ret
endp
;----------------------------------------------------------
;--- процедура прорисовки фона ----------------------------
;входные данные
;eax
;edx - color
;----------------------------------------------------------
edit_box.draw_bg:
mov ebx,ed_left
add ebx,1
mov edx,ed_color
shl ebx,16
add ebx,ed_width
sub ebx,1
;вход только цвет edx
edit_box.draw_bg_eax:
mov ecx,ed_top
mov eax,13
add ecx,1
shl ecx,16
add ecx,ed_height
dec ecx
mcall
ret
;----------------------------------------------------------
;--- процедура получения количества символов в текущей ширине компонента
;----------------------------------------------------------
edit_box.get_n:
mov eax,ed_width ;получем ширину компонента
xor edx,edx ;результат располагается в паре edx:eax в eax - остаток
sub eax,4 ;вычтем 4
mov ebx,6 ;загрузим делитель
div ebx ;разделим на 6
ret
;----------------------------------------------------------
;--- процедура рисования курсора --------------------------
;----------------------------------------------------------
;входные ebp- цвет
edit_box.clear_cursor:
mov edx,ebp
mov ebx,cl_curs_x
mov ecx,cl_curs_y
jmp edit_box.draw_curs
edit_box.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 ebx,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 ecx,ed_height-4
mov cl_curs_x,ebx
mov cl_curs_y,ecx
edit_box.draw_curs:
mcall 38
ret
;----------------------------------------------------------
;--- процедура рисования рамки ----------------------------
;----------------------------------------------------------
edit_box.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 ebx,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 ebx,ed_width
mcall
;--- справа ---
mov ebx,ebp
shl ebx,16
mov bx,bp
mcall
ret
;----------------------------------------------------------
;--- проверка, зашел ли курсор за границы и, если надо, ---
;--- изменяем смещение ------------------------------------
;--- если смещение было, установка флага ed_offset_cl, иначе,
; если ничего не изменилось, то выставление ed_offset_fl
; в общей битовой матрице состояния компонентов word ed_flags
;----------------------------------------------------------
edit_box.check_offset:
pushad
mov ecx,ed_pos
mov ebx,ed_offset
cmp ebx,ecx
ja edit_box.sub_8
push ebx
call edit_box.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 edit_box.add_end
sub edx,ecx
cmp edx,8
jbe edit_box.add_8
add ebx,8
jmp edit_box.chk_d
edit_box.sub_8:
test ecx,ecx
jz edit_box.sub_min
cmp ebx,8
jbe edit_box.sub_min
sub ebx,8 ;ebx=ed_offset
jmp edit_box.chk_d
edit_box.sub_min:
xor ebx,ebx
jmp edit_box.chk_d
edit_box.add_end:sub edx,eax
mov ebx,edx
jmp edit_box.chk_d
edit_box.add_8: add ebx,edx
edit_box.chk_d: mov ed_offset,ebx
call edit_box.draw_bg
and word ed_flags,ed_offset_cl
edit_ex
@@:
or word ed_flags,ed_offset_fl
edit_ex
align 4
proc edit_box_set_text, edit:dword, text:dword
pushad
mov edi,dword[edit]
mov ecx,ed_max
inc ecx ;учитываем будущее обрезание строки для ascii 0
mov edi,dword[text]
xor al,al
cld
repne scasb ;поиск в строке edi символа al
mov ecx,edi ;ecx = text + мин. значение из: 1) ed_max или 2) длины строки text
mov edi,dword[edit]
mov esi,dword[text]
sub ecx,esi ;ecx = длина строки text (но не больше чем ed_max)
dec ecx
mov ed_size,ecx ;ставим новый размер строки
mov ed_pos,ecx ;ставим курсор в конец новой строки
and word ed_flags,ed_shift_cl ;снимаем выделение если оно было
mov edi,ed_text
repne movsb ;копирование текстовой строки text в edit_box
mov byte[edi],0 ;ставим ascii 0 в конце строки
popad
ret
endp
}
macro use_key_func
{
;Обработка Shift для снятия выделения неизвестной области
edit_box_key.shift: ;;;;;;;SHIFT
test word ed_flags,ed_shift
je edit_box_key.f_exit
@@: mov ebp,shift_color
or word ed_flags,ed_shift_bac ;установка флага, выделенной области
mov ebx,dword ed_shift_pos
call edit_box_key.sh_cl_
jmp edit_box.draw_cursor_text
;;;;;;;;;;;;;;;;;;;;;
edit_box_key.f_exit:
call edit_box.check_offset
and word ed_flags,ed_shift_cl
call edit_box_key.enable_null
jmp edit_box.draw_cursor_text
edit_box_key.sh_cl_:
;;;;;;SHIFT end
;обработка очистки, при левом - правом движении выделения
;для обработки снятия выделения
;входные параметры ebp=color ebx=ed_shift_pos
mov eax,dword ed_pos
cmp eax,ebx
jae edit_box_key.sh_n
push eax ;меньшее в eax
push ebx ;большее
jmp edit_box_key.sh_n1
;если иначе
edit_box_key.sh_n:
push ebx
push eax
edit_box_key.sh_n1:
call edit_box.check_offset
call edit_box.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 edit_box_key.f_f ;если больше
xor eax,eax
cmp edx,ebx ;cравним размер w_off с большим
jb @f
sub ebx,ecx
jmp edit_box_key.nxt_f
@@: mov ebx,edx
sub ebx,ecx
jmp edit_box_key.nxt_f
edit_box_key.f_f:
sub eax,ecx
cmp edx,ebx ;cравним размер w_off с большим
jle @f
sub ebx,ecx
sub ebx,eax
jmp edit_box_key.nxt_f
@@:
mov ebx,edx
sub ebx,ecx
sub ebx,eax
edit_box_key.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 edit_box.draw_bg_eax
@@: call edit_box_key.enable_null
ret
;;;;;;;;;;;;;;;;;;;;;
;Установка- снятие выделения в один символ
;;;;;;;;;;;;;;;;;;;;;
edit_box_key.drw_sim:
mov eax,dword ed_pos
call edit_box_key.draw_rectangle ;нарисовать прямоугольник с заданным цветом
jmp @b
;;;;;;;;;;;;;;;;;;;;;
;Функция установки выделения при движении влево и вправо и нажатии shift
;Логика:
;;;;;;;;;;
edit_box_key.draw_wigwag:
;функция установки переменных
mov ebp,shift_color
call edit_box.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 edit_box_key.low
jmp @f
;;;;;;;;;;
;Функция удаления выделения при движении влево и вправо и нажатии shift
;Логика:
;;;;;;;;;;
edit_box_key.draw_wigwag_cl:
;функция установки переменных
mov ebp,ed_color
call edit_box.clear_cursor
mov ebp,ed_color
mov eax,dword ed_pos
test word ed_flags,ed_left_fl
jz edit_box_key.low
@@: call edit_box_key.draw_rectangle ;нарисовать прямоугольник закрашиваемой области
ret
edit_box_key.low: dec eax
jmp @b
;входной параметр ebx - ed_pos
edit_box_key.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
;иначе вообще выходит
edit_box_key.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 edit_box_key.sh_cl_ ;очистка выделеного фрагмента
and word ed_flags,ed_shift_cl ; очистка от того, что убрали выделение
jmp edit_box.draw_cursor_text
@@:
and word ed_flags,ed_shift_off
popad
ret 4
;проверка состояния shift, был ли он нажат раньше?
edit_box_key.sh_enable:
test word ed_flags,ed_shift
jne edit_box_key.sh_ext_en ;нарисовать закрашенный прямоугольник
test word ed_flags,ed_shift_bac
je @f
call edit_box.check_offset
mov ebp,ed_color
mov ebx,dword ed_shift_pos
call edit_box_key.sh_cl_ ;очистка выделенного фрагмента
call edit_box_key.draw_wigwag_cl
and word ed_flags,ed_shift_cl ; 1вар не нужно
ret
@@: mov ebp,ed_color
call edit_box.clear_cursor
call edit_box.check_offset
ret
edit_box_key.sh_ext_en:
call edit_box.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 edit_box_key.1_shem
jb edit_box_key.smaller
cmp ecx,ebx
ja edit_box_key.1_shem
call edit_box_key.draw_wigwag_cl ;clear
jmp edit_box_key.sh_e_end
edit_box_key.smaller:
cmp ecx,ebx
jb edit_box_key.1_shem
call edit_box_key.draw_wigwag_cl ;clear
jmp edit_box_key.sh_e_end
;alike =
edit_box_key.1_shem: call edit_box_key.draw_wigwag
edit_box_key.sh_e_end: and word ed_flags,ed_shift_off
ret
@@: mov ebp,shift_color
mov ebx,dword ed_shift_pos
call edit_box_key.sh_cl_
jmp edit_box_key.sh_e_end
;функция для обработки shift при нажатии home and end
edit_box_key.sh_home_end:
mov ebp,ed_color
call edit_box.clear_cursor
test word ed_flags,ed_shift_bac
je @f
mov ebp,ed_color
mov ebx,dword ed_shift_pos_old
call edit_box_key.sh_cl_
@@: test word ed_flags,ed_shift
je edit_box_key.sh_exit_ ;выйти
mov ebp,shift_color
mov ebx,dword ed_shift_pos
call edit_box_key.sh_cl_
or word ed_flags,ed_shift_bac ;установка флага, выделенной области
jmp edit_box_key.sh_e_end
edit_box_key.sh_exit_:
call edit_box.draw_bg
call edit_box.check_offset
ret
;функция внесения 0 по адресу ed_size+1
edit_box_key.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
edit_box_key.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 edit_box_key.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 edit_box_key.del_ch_sh
;если иначе
edit_box_key.dh_n:
mov ebp,eax
sub ebp,ecx
add ebx,ecx
sub edx,eax
add esi,eax
mov dword ed_shift_pos,ebp
jmp edit_box_key.del_ch_sh
@@: add esi,ecx ;указатель + смещение к реальному буферу
mov ebx,esi
inc esi
cld
sub edx,ecx
edit_box_key.del_ch_sh:
push edi
mov edi,ebx
@@:
lodsb
stosb
dec edx
jns @b
pop edi
ret
;вычислить закрашиваемую область
;соглашение в ebp - передается ed_size
edit_box_key.clear_bg:
call edit_box.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 edit_box_key.nxt
@@: mov ebx,ed_pos
push ebx
sub eax,ebx
mov ebx,eax ;It is not optimal
pop eax ;ed_pos
mov ecx,ed_offset
sub eax,ecx
edit_box_key.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 edit_box.draw_bg_eax
ret
;;;;;;;;;;;;;;;;;;;
;;; Обработка примитивов
;;;;;;;;;;;;;;;;;;;;
;Нарисовать прямоугольник, цвет передается в ebp
;входные параметры:
;eax=dword ed_pos
;ebp=-цвет ed_color or shift_color
edit_box_key.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
add ebx,6
mov edx,ebp
call edit_box.draw_bg_eax
ret
;;;;;;;;;;;;;;;;;;
;;Проверка нажат ли shift
;;;;;;;;;;;;;;;;;;
edit_box_key.check_shift_ctrl_alt:
pusha ;сохраним все регистры
mcall 66,3
test al,11b
je @f
or word ed_flags,ed_shift ;установим флаг Shift
@@:
and word ed_flags,ed_ctrl_off ; очистим флаг Ctrl
test al,1100b
je @f
or word ed_flags,ed_ctrl_on ;установим флаг Ctrl
@@:
and word ed_flags,ed_alt_off ; очистим флаг Alt
test al,110000b
je @f
or word ed_flags,ed_alt_on ;установим флаг Alt
@@:edit_ex
}
macro use_key_no_process up,down,esc,enter,tab,numl,capsl,scrolll
{
if up eq
else
cmp ah,177
jz edit_box.editbox_exit
end if
if down eq
else
cmp ah,178
jz edit_box.editbox_exit
end if
if esc eq
else
cmp ah,27 ;ESC - клавиша ))
jz edit_box.editbox_exit
end if
if enter eq
else
cmp ah,13 ;ENTER - клавиша ))
jz edit_box.editbox_exit
end if
if tab eq
else
cmp ah,9 ;TAB - клавиша ))
jz edit_box.editbox_exit
end if
if numl eq
else
cmp ah,4 ;Num Lock - клавиша ))
jz edit_box.editbox_exit
end if
if capsl eq
else
cmp ah,2 ;Caps Lock - клавиша ))
jz edit_box.editbox_exit
end if
if scrolll eq
else
cmp ah,1 ;Scroll Lock - клавиша ))
jz edit_box.editbox_exit
end if
}
macro use_key_figures_only
{
test word ed_flags,ed_figure_only ; только цифры?
jz @f
cmp ah,'0'
jb edit_box.editbox_exit
cmp ah,'9'
ja edit_box.editbox_exit
@@:
}
macro are_key_shift_press
{
test word ed_flags,ed_shift_on
je @f
;Входные данные edx=ed_size;ecx=ed_pos
push eax
mov edx,ed_size
mov ecx, ed_pos
pusha
;;;;;;;;;;;;;;;;;;;;;
;clear input arrea
mov ebp,ed_color
mov ebx,dword ed_shift_pos
call edit_box_key.sh_cl_
mov ebp,ed_size
call edit_box_key.clear_bg
;;;;;;;;;;;;;;;;;;;;;
popa
call edit_box_key.del_char
;;;;
mov ebx,ed_size
sub ebx,dword ed_shift_pos
mov ed_size,ebx
pop eax
@@:
}
macro are_key_cur_end
{
mov ecx,ed_size
mov edx, ed_max
test word ed_flags,ed_insert
jne @f
cmp ecx,edx
jae edit_box.editbox_exit
@@: mov ebx, ed_pos
cmp ebx,edx
jl @f ; если меньше или равно
jmp edit_box.editbox_exit
@@: ; сдвигаем символы после курсора вправо
mov ecx,ed_size
push edi eax
mov ebp,edi
mov esi,ed_text ; Указатель на буфер
;Будем работать со строкой
add esi,ecx ;add ed_size добавим max size
mov edi,esi
cmp ecx,ebx ;Если у нас позиция курсора = текущему размеру напечатанных символов т.е. курсор стоит в конце
je edit_box_key.In_k
test dword bp_flags,ed_insert ;IF insert is enabled т.к. edi изменен, адресуем через ebp
jne edit_box_key.ins_v
;clear
pusha
mov edi,ebp
mov ebp,ed_size
call edit_box_key.clear_bg
popa
sub ecx,ebx ;Найдем кол-во символов для передвижения.
inc edi ;Сместим наши символы вправо
std
inc ecx
@@:
;--------
lodsb
stosb
;--------
loop @b
edit_box_key.In_k:
cld
pop eax
mov al,ah
stosb
pop edi
; вставляем код клавиши туда, где курсор
; увеличиваем значение размера и позиции
inc dword ed_size
inc dword ed_pos
call edit_box_key.draw_all2
jmp edit_box_key.shift
}
macro use_work_key
{
edit_box_key.insert: test word ed_flags,ed_insert ;not word ed_insert
je @f
and word ed_flags,ed_insert_cl
jmp edit_box.editbox_exit
@@:
or word ed_flags,ed_insert
jmp edit_box.editbox_exit
edit_box_key.ins_v:
; dec dword [ebp+48];ed_size ;processing is insert
dec dword bp_size
sub esi,ecx
add esi,ebx
mov edi,esi
;clear
pusha
mov edi,ebp
mov ebp,ed_pos
call edit_box_key.clear_bg
popa
jmp edit_box_key.In_k
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
edit_box_key.delete:
mov edx,ed_size
mov ecx,ed_pos
cmp edx,ecx
jg edit_box_key.bac_del
test word ed_flags,ed_shift_on
jne edit_box_key.del_bac
popad
ret 4
edit_box_key.bac_del:
call edit_box_key.del_char
jmp edit_box_key.draw_all
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;--- нажата клавиша backspace ---
edit_box_key.backspace:
test word ed_flags,ed_shift_on
jne edit_box_key.delete
; проверяем, курсор у левого края?
mov ecx,ed_pos
test ecx,ecx
jnz edit_box_key.del_bac
popad
ret 4
edit_box_key.del_bac:
mov edx,ed_size
cmp edx,ecx ;if ed_pos=ed_size
je @f
dec ecx
call edit_box_key.del_char
@@: test word ed_flags,ed_shift_on
jne edit_box_key.bac_del
dec dword ed_pos
edit_box_key.draw_all:
push edit_box_key.shift;.draw_cursor_text;eax
test word ed_flags,ed_shift_on
je @f
mov eax,dword ed_shift_pos
mov ebx,ed_size
sub ebx,eax
mov ed_size,ebx
mov ebp,ed_color
call edit_box.clear_cursor
call edit_box.check_offset
call edit_box.draw_bg
ret
@@: dec dword ed_size
edit_box_key.draw_all2:
and word ed_flags,ed_shift_cl
mov ebp,ed_color
call edit_box.clear_cursor
call edit_box.check_offset
mov ebp,ed_size
call edit_box_key.clear_bg
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;--- нажата клавиша left ---
edit_box_key.left:
mov ebx,ed_pos
test ebx,ebx
jz edit_box_key.sh_st_of
or word ed_flags,ed_left_fl
call edit_box_key.sh_first_sh
dec dword ed_pos
call edit_box_key.sh_enable
jmp edit_box.draw_cursor_text
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;--- нажата клавиша right ---
edit_box_key.right:
mov ebx,ed_pos
cmp ebx,ed_size
je edit_box_key.sh_st_of
and word ed_flags,ed_right_fl
call edit_box_key.sh_first_sh
inc dword ed_pos
call edit_box_key.sh_enable
jmp edit_box.draw_cursor_text
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
edit_box_key.home:
mov ebx,ed_pos
test ebx,ebx
jz edit_box_key.sh_st_of
call edit_box_key.sh_first_sh
xor eax,eax
mov ed_pos,eax
call edit_box_key.sh_home_end
jmp edit_box.draw_cursor_text
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
edit_box_key.end:
mov ebx,ed_pos
cmp ebx,dword ed_size
je edit_box_key.sh_st_of
call edit_box_key.sh_first_sh
mov eax,ed_size
mov ed_pos,eax
call edit_box_key.sh_home_end
jmp edit_box.draw_cursor_text
;-----------------------------------------------------------------------------
edit_box_key.ctrl_c:
; add memory area
mov ecx,ed_size
add ecx,3*4
mcall 68,12
; building the clipboard slot header
xor ecx,ecx
mov [eax+4],ecx ; type 'text'
inc ecx
mov [eax+8],ecx ; cp866 text encoding
mov ecx,ed_size
add ecx,3*4
mov [eax],ecx
sub ecx,3*4
; copy data
mov esi,ed_text
push edi
mov edi,eax
add edi,3*4
cld
rep movsb
pop edi
; put slot to the kernel clipboard
mov edx,eax
mov ecx,[edx]
push eax
mcall 54,2
pop ecx
; remove unnecessary memory area
mcall 68,13
;--------------------------------------
.exit:
jmp edit_box.editbox_exit
;-----------------------------------------------------------------------------
edit_box_key.ctrl_v:
mcall 54,0
; no slots of clipboard ?
test eax,eax
jz .exit
; main list area not found ?
inc eax
test eax,eax
jz .exit
sub eax,2
mov ecx,eax
mcall 54,1
; main list area not found ?
inc eax
test eax,eax
jz .exit
; error ?
sub eax,2
test eax,eax
jz .exit
inc eax
; check contents of container
mov ebx,[eax+4]
; check for text
test ebx,ebx
jnz .no_valid_text
mov ebx,[eax+8]
; check for cp866
cmp bl,1
jnz .no_valid_text
mov ecx,[eax]
sub ecx,3*4
cmp ecx,ed_max
jb @f
mov ecx,ed_max
@@:
mov esi,eax
add esi,3*4
mov ed_size,ecx
mov ed_pos,ecx
push eax edi
mov edi,ed_text
cld
@@:
lodsb
cmp al,0x0d ; EOS (end of string)
je .replace
cmp al,0x0a ; EOS (end of string)
jne .continue
.replace:
mov al,0x20 ; space
.continue:
stosb
dec ecx
jnz @b
; rep movsb
pop edi eax
;--------------------------------------
.no_valid_text:
; remove unnecessary memory area
mov ecx,eax
mcall 68,13
;--------------------------------------
.exit:
jmp edit_box.draw_1
}
macro use_mouse_func
{
;----------------------------------------------------------
;--- Обработка .mouse_wigwag
;----------------------------------------------------------
edit_box_mouse.mouse_wigwag:
shr eax,16
or word ed_flags,ed_shift_bac+ed_shift_on+ed_shift
;;;;;;;;;;;;;;;;;;
;;процедура обработки положения выделенного текста, когда происходит выход за пределы editbox
;;;;;;;;;;;;;;;;;;
test ax,0x8000
jnz edit_box_mouse.mleft
mov ebx,ed_left
cmp eax,ebx
jb edit_box_mouse.mleft
add ebx,ed_width
cmp eax,ebx
ja edit_box_mouse.mright
sub ebx,ed_width
xor edx,edx
sub eax,ebx ; вычтем из координат мышки по оси х координаты до editbox по оси х
mov ebx,6
div ebx
;;;;;;;;;;;;;;;;;;
;;процедура обработки положения выделенного текста, в пределах области editbox
;;;;;;;;;;;;;;;;;;
;Получили координаты в eax мышки, т.е. куда она переместилась
;Рисование закрашенных прямоугольников и их очистка
add eax,ed_offset ;добавим смещение
cmp eax,dword ed_size ;если вышли за пределы, то ничего не делать
ja edit_box_mouse.mwigvag
edit_box_mouse.mdraw:
mov dword ed_pos,eax ;сохраним новое значение
;Рисование закрашенных прямоугольников и их очистка
mov ecx,dword ed_shift_pos
mov ebx,dword ed_shift_pos_old
mov dword ed_shift_pos_old,eax ;внесем новое значение старой позиции курсора
;проверка и рисование закрашенных областей
cmp ecx,ebx ;выясняем куда было движение на один шаг назад
je edit_box_mouse.m1_shem ;движения не было ранее
jb edit_box_mouse.msmaller ;движение было ->
cmp ebx,eax ;движение было до этого <- и тут мы проверяем сейчас куда движение происходит
ja edit_box_mouse.m1_shem ;если было движение <- то нужно закрасить область
je edit_box_mouse.mwigvag ;если изменения не было, то ничего не делать
mov ebp,ed_color ;тут нужно очистить область c ed_pos ed_shift_pos_old
;входные параметры ebp=color ebx=ed_shift_pos
call edit_box_key.sh_cl_
jmp edit_box_mouse.mwigvag
edit_box_mouse.msmaller:
cmp ebx,eax
jb edit_box_mouse.m1_shem
mov ebp,ed_color
;входные параметры ebp=color ebx=ed_shift_pos
call edit_box_key.sh_cl_
jmp edit_box_mouse.mwigvag
;alike =
edit_box_mouse.m1_shem:
mov ebp,shift_color
;входные параметры ebp=color ebx=ed_shift_pos
mov ebx,ecx
call edit_box_key.sh_cl_
jmp edit_box_mouse.mwigvag
edit_box_mouse.mwigvag:
and word ed_flags,ed_shift_mcl
jmp edit_box.draw_cursor_text
; popa
; ret
edit_box_mouse.mleft:
mov eax,ed_pos
cmp eax,0
jbe edit_box_mouse.mwigvag
dec eax
call edit_box.check_offset
push eax
mov ebx,ed_shift_pos
mov ebp,shift_color
call edit_box_key.sh_cl_
pop eax
jmp edit_box_mouse.mdraw
edit_box_mouse.mright:
mov eax,ed_pos
mov ebx,ed_size
cmp eax,ebx
jae edit_box_mouse.mwigvag
inc eax
call edit_box.check_offset
mov ebx,ed_shift_pos
mov ebp,shift_color
push eax
call edit_box_key.sh_cl_
pop eax
jmp edit_box_mouse.mdraw
}
macro use_work_mouse
;----------------------------------------------------------
;--- А не удерживаем ли мы клавишу мышки, перемещая курсор, во все разные стороны?
;----------------------------------------------------------
{
test word ed_flags,ed_mouse_on
jne edit_box_mouse.mouse_wigwag
;----------------------------------------------------------
;--- проверяем, попадает ли курсор в edit box -------------
;----------------------------------------------------------
mov ebx,ed_top
cmp ax,bx
jl edit_box_mouse._blur;.mouse_end_no_focus
add ebx,ed_height
cmp ax,bx
jg edit_box_mouse._blur;.mouse_end_no_focus
shr eax,16
mov ebx,ed_left
cmp ax,bx
jl edit_box_mouse._blur;.mouse_end_no_focus
add ebx,ed_width
cmp ax,bx
jg edit_box_mouse._blur;.mouse_end_no_focus
;--- изменяем позицию курсора ---
push eax
mov ebp,ed_color
call edit_box.clear_cursor
pop eax
edit_box_mouse._mvpos:
xor edx,edx
sub eax,ed_left
mov ebx,6
div bx
add eax,ed_offset
cmp eax,ed_size
jna edit_box_mouse._mshift
mov eax,ed_size
edit_box_mouse._mshift:
;;;;;;;
;;Секция обработки shift и выделения по shift
;;;;;;;
test word ed_flags,ed_shift_bac
je @f
mov ebp,dword ed_color
mov ebx,dword ed_shift_pos
push eax
call edit_box_key.sh_cl_
and word ed_flags,ed_shift_bac_cl
pop eax
@@:
test word ed_flags,ed_mouse_on
jne @f
mov dword ed_shift_pos,eax
or word ed_flags,ed_mouse_on
mov dword ed_pos,eax
; mov dword [mouse_flag],edi ;установим идентификатор
mov ebx,dword ed_mouse_variable
push edi
pop dword [ebx]
bts word ed_flags,1 ;установка фокуса
jmp edit_box_mouse.m_sh
@@:
cmp eax,dword ed_shift_pos ;если позиции не изменились
je edit_box.editbox_exit
mov ed_pos,eax
mov ebp,dword shift_color
mov ebx,dword ed_shift_pos
call edit_box_key.sh_cl_
or word ed_flags,ed_mous_adn_b ;установим бит, что мы выделили +shift_on +
edit_box_mouse.m_sh:
call edit_box.draw_text
call edit_box.draw_cursor
;----------------------------------------------------------
;--- процедура установки фокуса ---------------------------
;----------------------------------------------------------
jmp edit_box_mouse.drc
edit_box_mouse._blur:
test word ed_flags,ed_always_focus
jne edit_box.editbox_exit
btr word ed_flags,1 ; если не в фокусе, выходим
jnc edit_box.editbox_exit
mov ebp,ed_color
call edit_box.clear_cursor
edit_box_mouse.drc: call edit_box.draw_border
jmp edit_box.editbox_exit
}
; Макрос выхода
macro edit_ex
{
popad
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 ;вернуться очень интересный ход, т.к. пока в стеке хранится кол-во вызовов, то столько раз мы и будем вызываться
}
ed_struc_size=76