;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Basic macros for use editbox                             ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ed_width        equ [edi]               ;ширина компонента
ed_left         equ [edi+4]             ;положение по оси х
ed_top          equ [edi+8]             ;положение по оси у
ed_color        equ [edi+12]            ;цвет фона компонента
shift_color     equ [edi+16]            ;=0x6a9480 для примера возьем желеный цвет бокса
ed_focus_border_color   equ [edi+20]    ;цвет рамки компонента
ed_blur_border_color    equ [edi+24]    ;цвет не активного компонента
ed_text_color   equ [edi+28]            ;цвет текста
ed_max          equ [edi+32]                    ;кол-во символов которые можно максимально ввести
ed_text         equ [edi+36]                    ;указатель на буфер
ed_mouse_variable 	equ [edi+40]	; указатель на переменную для бокса/группы 
ed_flags        equ [edi+44]            ;флаги
bp_flags	equ [ebp+44]		;в некоторых процедурах edi используется, взамен указатель храниться в ebp
ed_size equ [edi+48]                    ;кол-во символов
bp_size equ [ebp+48]			;кол-во симвполов, для адресации испльзуется ebpб edi занят
ed_pos  equ [edi+52]                    ;позиция курсора
ed_offset       equ [edi+56]            ;смещение
cl_curs_x       equ [edi+60]            ;предыдущее координата курсора по х
cl_curs_y       equ [edi+64]            ;предыдущее координата курсора по у
ed_shift_pos    equ [edi+68]            ;положение курсора
ed_shift_pos_old equ [edi+72]           ;старое положение курсора

ed_figure_only= 1000000000000000b   ;одни символы
ed_always_focus= 100000000000000b
ed_focus=                     10b   ;фокус приложения
ed_shift_on=                1000b   ;если не установлен -значит впервые нажат shift,если был установлен, значит мы уже что - то делали удерживая shift
ed_shift_on_off=1111111111110111b
ed_shift=                    100b   ;включается при нажатии на shift т.е. если нажимаю
ed_shift_off=   1111111111111011b
ed_shift_bac=              10000b   ;бит для очистки выделеного shift т.е. при установке говорит что есть выделение
ed_shift_bac_cl=1111111111101111b   ;очистка при удалении выделения
ed_shift_cl=    1111111111100011b
ed_shift_mcl=   1111111111111011b
ed_left_fl=               100000b
ed_right_fl=    1111111111011111b
ed_offset_fl=            1000000b
ed_offset_cl=   1111111110111111b
ed_insert=              10000000b
ed_insert_cl=   1111111101111111b
ed_mouse_on =          100000000b
ed_mous_adn_b=         100011000b
ed_mouse_on_off=1111111011111111b
ed_height=14 ; высота



macro init_editbox
{
pushad
	mcall

popad
}


macro use_editbox_draw
{
edit_box:
.draw:
        pushad
;--- рисуем рамку ---
        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

;Проверка нажат shift ?
        call    edit_box_key.check_shift
;----------------------------------------------------------
;--- проверяем, что нажато --------------------------------
;----------------------------------------------------------
use_key_process  backspase,delete,left,right,home,end,insert
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Заглушка на обработку клавиш вверх и вниз т.е. при обнаружении этих кодов происходит выход из обработчика
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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.backspase,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
        mcall
ret
;----------------------------------------------------------
;--- процедура прорисовки фона ----------------------------
;входные данные
;eax
;edx - color
;----------------------------------------------------------
;вход только цвет edx
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
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:
	cmp     ecx,0
        je      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
}

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.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 don't 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:
pusha   ;сохраним все регистры
        mcall   66,3
        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      edit_box_key.backspace
end if
if delete eq 
else
        cmp     ah,0xb6
        jz      edit_box_key.delete
end if
if left eq 
else
        cmp     ah,176
        jz      edit_box_key.left
end if
if right eq 
else
        cmp     ah,179
        jz      edit_box_key.right
end if
if home eq 
else
        cmp     ah,180
        jz      edit_box_key.home
end if
if home eq 
else
        cmp     ah,181
        jz      edit_box_key.end
end if
if insert eq 
else
        cmp     ah,185  ;insert
        jz      edit_box_key.insert
end if
}

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     eax,dword ed_shift_pos
        mov     ebx,ed_size
        sub     ebx,eax
        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 enable  т.к. 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:
        ; проверяем, курсор у левого края ?
        mov     ecx,ed_pos
        test    ecx,ecx
        jnz     edit_box_key.del_bac
        test    word ed_flags,ed_shift_on
        jne     edit_box_key.bac_del
        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
}

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
struc  edit_box width,left,top,color,shift_color,focus_border_color,\
       blur_border_color,text_color,max,text,mouse_variable,flags,size,pos
{
.width dd width
.left dd left
.top dd top
.color dd color
.shift_color dd shift_color
.focus_border_color dd focus_border_color
.blur_border_color dd blur_border_color
.text_color dd text_color
.max dd max
.text dd text
.mouse_variable dd mouse_variable
.flags dd flags+0
.size dd size+0
.pos dd pos+0
.offset dd 0
.cl_curs_x dd 0
.cl_curs_y dd 0
.shift   dd 0
.shift_old   dd 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Bit mask from editbox 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ed_figure_only= 1000000000000000b   ;одни символы 
ed_always_focus= 100000000000000b
ed_focus=                     10b   ;фокус приложения
ed_shift_on=                1000b   ;если не установлен -значит впервые нажат shift,если был установлен, значит мы уже что - то делали удерживая shift
ed_shift_on_off=1111111111110111b
ed_shift=                    100b   ;включается при нажатии на shift т.е. если нажимаю
ed_shift_off=   1111111111111011b
ed_shift_bac=              10000b   ;бит для очистки выделеного shift т.е. при установке говорит что есть выделение
ed_shift_bac_cl=1111111111101111b   ;очистка при удалении выделения
ed_shift_cl=    1111111111100011b
ed_shift_mcl=   1111111111111011b
ed_left_fl=               100000b
ed_right_fl=    1111111111011111b
ed_offset_fl=            1000000b
ed_offset_cl=   1111111110111111b
ed_insert=              10000000b
ed_insert_cl=   1111111101111111b
ed_mouse_on =          100000000b
ed_mous_adn_b=         100011000b
ed_mouse_on_off=1111111011111111b
ed_height=14 ; высота

}
