format MS COFF
public EXPORTS
section '.flat' code readable align 16

include '../../../macros.inc'
include 'strlen.inc'

MB_FIRST_BUT_ID equ 3 ;¨¤¥­â¨ä¨ª â®à 1-© ª­®¯ª¨ ­  á®®¡é¥­¨¨
MB_MAX_BUT equ 8 ;¬ ªá¨¬ «ì­®¥ ç¨á«® ª­®¯®ª ¢ á®®¡é¥­¨¨
MB_BUT_HEIGHT equ 20 ;¢ëá®â  ª­®¯ª¨ ­  á®®¡é¥­¨¨
CHAR_WIDTH equ 6 ;è¨à¨­  1-© ¡ãª¢ë ⥪áâ 
MB_BUT_OTY_1 equ  5 ;¢ëà⨪ «ì­ë©(¥) ®âáâã¯(ë) ¬¥¦¤ã: § £®«®¢ª®¬ ®ª­  ¨ ⥪á⮬, ⥪á⮬ ª­®¯ª ¬¨
;--- ®âáâã¯ë ­  ª­®¯ª å, 㪠§ ­­ë¥ ¢®¯à®á ¬¨: <-?->, ¡¥§ ãç¥â  ⥪áâ  ---
MB_BUT_OTX_1 equ  5 ;[<-?->Caption.....]
MB_BUT_OTX_2 equ 10 ;[<-?->Caption<-?->]
MB_BUT_OTX_3 equ 15 ;[<-?->Caption<-?->]<-?->
MB_TEXT_OFFSET equ 2 ;ᬥ饭¨¥, ¯® ª®â®à®¬ã ­ ç¨­ ¥âìáï ⥪áâ § £®«®¢ª  ®ª­ 

align 4
start:
  mov eax,48
  mov ebx,3
  mov ecx,sc
  mov edx,sizeof.system_colors
  mcall
  mov eax,40
  mov ebx,0x27
  mcall

  ;-- clear id pressed button ---
  mov ebx,[mb_text]
  mov al,byte[ebx]
  add al,MB_FIRST_BUT_ID
  dec al
  mov byte[mb_key_foc],al

  push [mb_text]
  call MsgBoxReInit

align 4
red_win:
  mov eax,12
  mov ebx,1
  mcall

  xor eax,eax
  mov bx,word[mb_left]
  shl ebx,16
  mov bx,word[mb_width]
  mov cx,word[mb_top]
  shl ecx,16
  mov cx,word[mb_height]
  mov edx,[sc.work]
  or  edx,0x33000000
  mov edi,[mb_text]
  add edi,MB_TEXT_OFFSET ;Caption
  mcall

  mcall 9,mb_procinfo,-1
  mov eax,dword[mb_procinfo.client_box.width]

  sub eax,[but_width]
  shr eax,1
  add eax,MB_BUT_OTX_1
  mov [ot_left],eax

  mov eax,4 ;à¨á®¢ ­¨¥ ⥪áâ 
  mov bx,MB_BUT_OTX_1
  shl ebx,16
  mov bx,MB_BUT_OTY_1
  mov ecx,[sc.work_text]
  mov edx,[txtMsg]

  @@:
    mov esi,edx
    call strlen
    call linlen

    cmp eax,0
    je @f

    mov esi,eax
    push eax
      mov eax,4
      int 0x40
    pop eax

    add edx,eax
    cmp byte[edx],0
    je @f
    inc edx

    add ebx,10 ; move <--y-->
    jmp @b
  @@:

  call MsgBoxDrawAllBut
  mcall 12,2

align 4
still:
  mov eax,10
  mcall

  cmp al,1 ;¨§¬. ¯®«®¦¥­¨¥ ®ª­ 
  jz red_win
  cmp al,2
  jz key
  cmp al,3
  jz button

  jmp still

align 4
key:
  mcall 2
  cmp ah,13
  jne @f
    mov ah,[mb_key_foc]
    jmp close
  @@:

  cmp ah,176 ;Left
  jne .no_left
  cmp [mb_key_foc],MB_FIRST_BUT_ID
  jg @f
    mov al,[mb_key_max]
    add [mb_key_foc],al
  @@:
    dec [mb_key_foc]
    call MsgBoxDrawAllBut
  .no_left:

  cmp ah,9 ;Tab
  je @f
  cmp ah,179 ;Right
  je @f
	jmp .no_right
  @@:
  mov al,[mb_key_max]
  add al,MB_FIRST_BUT_ID
  cmp [mb_key_foc],al
  je .no_right
    inc [mb_key_foc]
    cmp [mb_key_foc],al
    jl @f
      mov [mb_key_foc],MB_FIRST_BUT_ID
    @@:
    call MsgBoxDrawAllBut
  .no_right:

  jmp still

align 4
button:
  mcall 17 ;¯®«ãç¨âì ª®¤ ­ ¦ â®© ª­®¯ª¨
  cmp ah,MB_FIRST_BUT_ID
  jge close
  cmp ah,1
  jne still

;.exit:
  mov ah,MB_FIRST_BUT_ID
  dec ah
close:
  sub ah,MB_FIRST_BUT_ID
  inc ah
  mov ebx,[mb_text]
  mov byte[ebx],ah

  ;*** call msgbox functions ***
  cmp ah,0
  je @f
  cmp dword[mb_funct],0
  je @f
    xor ebx,ebx
    mov bl,ah
    dec bl
    shl bx,2 ;bx=bx*4
    add ebx,dword[mb_funct]
    cmp dword[ebx],0
    je @f
      call dword[ebx]
  @@:
  mcall -1 ;¢ë室 ¨§ ¯à®£à ¬¬ë

align 4
MsgBoxDrawAllBut:
  mov ebx,[ot_left]
  shl ebx,16
  mov bx,word[ot_top]
  add bx,MB_BUT_OTY_1

  ; Buttons ...
  push edi
  mov edi,txtBut
  mov edx,[edi]

  mov ecx,MB_FIRST_BUT_ID
  @@:
    ;eax = len button caption text
    mov esi,edx
    call strlen

    cmp eax,0
    je @f

    call MsgBoxDrawButton
    inc ecx

    add edi,4
    cmp edi,endBut
    jge @f
    mov edx,[edi]

    push bx
    ror ebx,16
      imul esi,CHAR_WIDTH
      add esi,MB_BUT_OTX_3
      add ebx,esi ; ...
    ror ebx,16
    pop bx

    jmp @b
  @@:
  pop edi
  ret

;input:
; ecx = button id
align 4
MsgBoxDrawButton:
  push ecx

  ;button
  push eax ebx edx
    mov edx,ecx
    imul eax,CHAR_WIDTH
    add eax,MB_BUT_OTX_2

    mov esi,[sc.work_button]
    cmp cl,[mb_key_foc]
    jne @f
      mov esi,[sc.work_button_text]
    @@:

    mov cx,bx
    sub cx,MB_BUT_OTY_1
    shl ecx,16
    mov cx,MB_BUT_HEIGHT
    ror ebx,16
    sub bx,MB_BUT_OTX_1
    ror ebx,16
    mov bx,ax

    mov eax,8
    int 0x40
  pop edx ebx eax

  ;caption
  mov ecx,[sc.work_button_text]
  cmp esi,ecx
  jne @f
    mov ecx,[sc.work_button]
  @@:
  mov esi,eax
  mov eax,4
  int 0x40

  pop ecx
  ret

align 4
MsgBoxReInit:
  push ebp
  mov ebp,esp
    m2m dword[mb_text],dword[ebp+8]
  push eax ebx ecx edi esi

  mov esi,[mb_text]
  add esi,MB_TEXT_OFFSET
  call strlen
  inc esi ;add terminated zero
  add esi,eax ;add len of caption
  mov [txtMsg],esi

  ;--- go to first button text --- buttons 1...MB_MAX_BUT
  mov ebx,txtBut
  mov cx,MB_MAX_BUT
  @@:
    call strlen
    add esi,eax ;add len of caption
    inc esi ;add terminated zero

    mov dword[ebx],esi
    cmp byte[esi],0
    je @f
    add ebx,4
  loop @b
  @@:

  ;--- calc button top ---
  mov eax,1
  mov ebx,[txtMsg]
  @@:
    inc ebx
    cmp byte[ebx],0
    je @f
    cmp byte[ebx],13
    jne @b
    inc eax
    jmp @b
  @@:
  imul eax,10
  add eax,2*MB_BUT_OTY_1
  mov [ot_top],eax

  ;--- calc window height ---
  add eax,MB_BUT_OTY_1
  add eax,MB_BUT_HEIGHT
  add ax,5 ;height of border
  mov [mb_height],ax
  mcall 48,4 ;skin height
  add [mb_height],ax

  ;--- calc window top ---
  mov eax,14
  int 0x40
  mov word[mb_top],ax
  mov ax,word[mb_height]
  sub word[mb_top],ax
  shr word[mb_top],1
  ;---
  shr eax,16
  mov word[mb_left],ax
  mov ax,word[mb_width]
  sub word[mb_left],ax
  shr word[mb_left],1

  ;--- calc button width ---
  xor ebx,ebx
  xor ecx,ecx
  mov esi,[txtBut]
  mov byte[mb_key_max],0
  @@:
    cmp byte[esi],0
    je @f
    inc ecx
    call strlen
    add esi,eax
    inc esi
    inc byte[mb_key_max]
    add ebx,eax
    jmp @b
  @@:

  imul ebx,CHAR_WIDTH
  imul ecx,MB_BUT_OTX_3
  add ebx,ecx
  add ebx,MB_BUT_OTX_2
  sub ebx,MB_BUT_OTX_3
  mov [but_width],ebx

  pop esi edi ecx ebx eax
  pop ebp
  ret 4

;input:
; [esp+8] = pointer to msgbox text
align 4
MsgBoxCreate:
  push ebp
  mov ebp,esp
    m2m dword[mb_text],dword[ebp+8]
    push eax ebx ecx edx

    mov eax,51
    mov ebx,1
    mov ecx,start
    mov edx,dword[ebp+12];thread
    int 0x40

    mov dword[mb_funct],0
    pop edx ecx ebx eax
  pop ebp
  ret 8

;input:
; [esp+8] = pointer to msgbox functions pointers
align 4
MsgBoxSetFunctions:
  push ebp
  mov ebp,esp
    m2m dword[mb_funct],dword[ebp+8]
  pop ebp
  ret 4

;--- data ---
  txtMsg dd 0 ;㪠§ â¥«ì ­  ­ ç «® ⥪áâ  á®®¡é¥­¨ï
  txtBut rd MB_MAX_BUT ;㪠§ â¥«ì ­  ­ ç «® ⥪áâ  ¯®¤¯¨á¥© ª­®¯®ª
  endBut:
  ot_left dd 0 ;®âáâ㯠᫥¢  (¤«ï à¨á®¢ ­¨ï ª­®¯®ª)
  ot_top dd 0 ;®âáâ㯠ᢥàåã (¤«ï à¨á®¢ ­¨ï ª­®¯®ª)
  but_width dd 0 ;è¨à¨­  ¢á¥å ª­®¯®ª + § §®àë ¬¥¦¤ã ­¨¬¨
  ;--- à §¬¥àë ­  íªà ­¥ ®ª­  á®®¡é¥­¨ï ---
  mb_left dw 0
  mb_width dw 300
  mb_top dw 0
  mb_height dw 50
  mb_key_foc db MB_FIRST_BUT_ID ;ª­®¯ª  ¢ 䮪ãᥠ(á ãç¥â®¬ MB_FIRST_BUT_ID)
  mb_key_max db 1 ;ç¨á«® ¢á¥å ª­®¯®ª á®®¡é¥­¨ï
;--------------------------------------------------
  sc system_colors
  mb_procinfo process_information ;㪠§ â¥«ì ­  áâàãªâãàã process_information த¨â¥«ì᪮£® ®ª­ 
  mb_text dd 0 ;msgbox_1 ;㪠§ â¥«ì ¤ ­­ë¥ ¤«ï á®®¡é¥­¨ï (ª®â®àë ¯¥à¥¤ îâìáï ®ª­ã)
  mb_funct dd 0 ;pointer to functions
;--------------------------------------------------
align 16
EXPORTS:
  dd sz_mb_create, MsgBoxCreate
  dd sz_mb_reinit, MsgBoxReInit
  dd sz_mb_setfunctions, MsgBoxSetFunctions
  dd 0,0
  sz_mb_create db 'mb_create',0
  sz_mb_reinit db 'mb_reinit',0
  sz_mb_setfunctions db 'mb_setfunctions',0