%LNG% equ 'ENU'
%GUIVER% equ ';micro3d 2023.1112                               ',13,10,\
             ';                                                ',13,10,\
             ';cmdL: file|"f i l e" [--line=1..] [--colors=1..]',13,10,\
             ';                                                ',13,10,\
             ';mail: kiselpro@ukr.net                          ',13,10,\
             ';mail: board.flatassembler.net, idle             ',13,10,\
             ';                                                ',13,10,\
             ';todo: 3d                                        ',13,10,0
;/tst/include once (fasm patch autogen).txt








format pe gui 4.0
include once 'win32a.inc'








section '.idata' import readable

  library comdlg32,'comdlg32.dll',\
          gdi32,'gdi32.dll',\
          kernel32,'kernel32.dll',\
          msvcrt,'msvcrt.dll',\
          shell32,'shell32.dll',\
          user32,'user32.dll'

  include 'api\comdlg32.inc'
  include 'api\gdi32.inc'
  include 'api\kernel32.inc'

  import msvcrt,\ ;microsoft visual c run time ...
         printf,'_vsnprintf' ;cinvoke (buffer,szBuffer,format,argptr)

  include 'api\shell32.inc'
  include 'api\user32.inc'








section 'const' data readable

;localizable string equates, add yours

  match ='ENU',%LNG%{
    %LNG%._ask_upon_replace    equ 'ask upon replace'
    %LNG%._cannot_open_file    equ 'cannot open file'
    %LNG%._cannot_save_file    equ 'cannot save file'
    %LNG%._case_sensitive      equ 'case sensitive'
    %LNG%._copy                equ 'copy'
    %LNG%._cut                 equ 'cut'
    %LNG%._cycle_editor_colors equ 'cycle editor colors'
    %LNG%._delete              equ 'delete'
    %LNG%._error               equ 'error'
    %LNG%._file                equ 'file'
    %LNG%._find                equ 'find'
    %LNG%._find_next           equ 'find next ...'
    %LNG%._find_replace        equ 'find/replace'
    %LNG%._in_whole_text       equ 'in whole text'
    %LNG%._increase            equ 'increase'
    %LNG%._kill                equ 'KILL!'
    %LNG%._line                equ 'line'
    %LNG%._names               equ 'names'
    %LNG%._open_file           equ 'open file'
    %LNG%._paste               equ 'paste'
    %LNG%._pause               equ 'pause'
    %LNG%._redo                equ 'redo'
    %LNG%._replace             equ 'replace'
    %LNG%._run_script          equ 'run script'
    %LNG%._save_changed        equ 'save changed'
    %LNG%._save_file           equ 'save file'
    %LNG%._search_complete     equ 'search complete'
    %LNG%._select_all          equ 'select all'
    %LNG%._switch_windows      equ 'switch windows'
    %LNG%._under_sync          equ 'under sync, waiting for respective data ...'
    %LNG%._undo                equ 'undo'
    %LNG%._vertical_selection  equ 'vertical selection'
  }
  match ='RUS',%LNG%{ include once 'encoding\win1251.inc'
    %LNG%._ask_upon_replace    equ '  '
    %LNG%._cannot_open_file    equ '  '
    %LNG%._cannot_save_file    equ '  '
    %LNG%._case_sensitive      equ ''
    %LNG%._copy                equ ''
    %LNG%._cut                 equ ''
    %LNG%._cycle_editor_colors equ ' '
    %LNG%._delete              equ ''
    %LNG%._error               equ ''
    %LNG%._file                equ ''
    %LNG%._find                equ ''
    %LNG%._find_next           equ '  ...'
    %LNG%._find_replace        equ '/'
    %LNG%._in_whole_text       equ '  '
    %LNG%._increase            equ ''
    %LNG%._kill                equ '!'
    %LNG%._line                equ ''
    %LNG%._names               equ ''
    %LNG%._open_file           equ ' '
    %LNG%._paste               equ ''
    %LNG%._pause               equ ''
    %LNG%._redo                equ ' '
    %LNG%._replace             equ ''
    %LNG%._run_script          equ ''
    %LNG%._save_changed        equ ' '
    %LNG%._save_file           equ ' '
    %LNG%._search_complete     equ ' '
    %LNG%._select_all          equ ' '
    %LNG%._switch_windows      equ ' '
    %LNG%._under_sync          equ '    ...'
    %LNG%._undo                equ ''
    %LNG%._vertical_selection  equ ' '
  }
  match ='UKR',%LNG%{ include once 'encoding\win1251.inc'
    %LNG%._ask_upon_replace    equ '  '
    %LNG%._cannot_open_file    equ '  '
    %LNG%._cannot_save_file    equ '  '
    %LNG%._case_sensitive      equ ''
    %LNG%._copy                equ ''
    %LNG%._cut                 equ ''
    %LNG%._cycle_editor_colors equ ' '
    %LNG%._delete              equ ''
    %LNG%._error               equ ''
    %LNG%._file                equ ''
    %LNG%._find                equ ''
    %LNG%._find_next           equ '  ...'
    %LNG%._find_replace        equ '/'
    %LNG%._in_whole_text       equ '  '
    %LNG%._increase            equ ''
    %LNG%._kill                equ '!'
    %LNG%._line                equ ''
    %LNG%._names               equ ''
    %LNG%._open_file           equ ' '
    %LNG%._paste               equ ''
    %LNG%._pause               equ ''
    %LNG%._redo                equ ' '
    %LNG%._replace             equ ''
    %LNG%._run_script          equ ''
    %LNG%._save_changed        equ ' '
    %LNG%._save_file           equ ' '
    %LNG%._search_complete     equ ' '
    %LNG%._select_all          equ ' '
    %LNG%._switch_windows      equ ' '
    %LNG%._under_sync          equ '    ...'
    %LNG%._undo                equ ''
    %LNG%._vertical_selection  equ ' '
  }

;control equates

  include once '../use/fedit/FEDIT.ASH'

  editor_colors:
    .01 dd $00000000,$00ffffff, $00ffffff,$00c56a31, $00f03030,$00009000,$000000b0,$00808080
    .02 dd $00969696,$00303030, $002c2c2c,$006a9cb7, $00ffffff,$0054fe54,$004080ff,$00007575
    .03 dd $00707070,$00000000, $00000000,$003a95ce, $0080ffff,$0000aa00,$004080ff,$00303030
    ;...
    .:

  ;dimensions

  WINDOW:
    .LEFT    = CW_USEDEFAULT
    .TOP     = CW_USEDEFAULT
    .WIDTH   = 825
    .HEIGHT  = 503
  INTERFACE:
    .LEFT    = 003
    .TOP     = 009
    .WIDTH   = 645
    .HEIGHT  = 450
  GROUP1:
    .LEFT    = 660
    .TOP     = 009
    .WIDTH   = 150
    .HEIGHT  = 191

  ;IDs

  GROUPICO0             = 01
    ICO0                = 02
  AXEL           label at 03
    .SW                 = 04
    .SAVE_FILE          = 05
    .OPEN_FILE          = 06
    .RUN_SCRIPT         = 07
    .PAUSE              = 08
    .KILL               = 09
    .NAMES              = 10
  TEXT:
    .MENU               = 11
    .MENU.UNDO          = 12
    .MENU.REDO          = 13
    .MENU.CUT           = 14
    .MENU.COPY          = 15
    .MENU.PASTE         = 16
    .MENU.DELETE        = 17
    .MENU.SELECTALL     = 18
    .MENU.VERTICAL      = 19
    .MENU.COLORS        = 20
    .MENU.FINDNEXT      = 21
    .MENU.FINDR         = 22
    .MENU.FINDR.TEXT    = 23
    .MENU.FINDR.NEW     = 24
    .MENU.FINDR.CASE    = 25
    .MENU.FINDR.WHOLE   = 26
    .MENU.FINDR.ASK     = 27
    .MENU.FINDR.LEFT    = 28
    .MENU.FINDR.FIND    = 29
    .MENU.FINDR.RIGHT   = 30
    .MENU.FINDR.FINDR   = 31

;flags and messages

  flagAXEL_CONCEDED            = 0 ;e.g. an axel. matched but not the window under focus, used to localize axels within a control
  flagTEXT_CHANGED             = 1
  flagSYNC.BMP32.SCREEN.ENABLE = 2
  flagSYNC.NAMES.ENABLE        = 3

  ;sync messages via SendMessage:
  ;  - SendMessage switches to destination thread window code with the message
  ;  - waits until it performs its exclusive access
  ;  - resumes to calling thread

  SYNC.BMP32.SCREEN.DISABLE = WM_USER+0 ;the script waits until gui sets0 flagSYNC.BMP32.SCREEN.ENABLE that is [last_bmp32] not reliable
  SYNC.BMP32.SCREEN.ENABLE  = WM_USER+1 ;the script waits until gui sets1 flagSYNC.BMP32.SCREEN.ENABLE that is [last_bmp32] valid
  SYNC.LOCK_CONTROLS        = WM_USER+2
  SYNC.UNLOCK_CONTROLS      = WM_USER+3
  SYNC.NAMES.DISABLE        = WM_USER+4
  SYNC.NAMES.ENABLE         = WM_USER+5
  SYNC.NAMES.LIST           = WM_USER+6

  ;TG
  FEM_HIGHLIGHTLINE         = WM_USER+7

;script basics

  MB               = 1024*1024
  printf.szBuffer  = 4096
  sz_script        = MB   ;human readable text
  szDataseg        = MB*8 ;dataseg / RAM :)
  szExprseg        = MB   ;expressions cache
  szTokenseg       = MB*8 ;analyzed text

;strings

  ___line_               db '--line=',0
  ___colors_             db '--colors=',0
  _button                db 'button',0
  _camera                db 'camera',0
  _camera_under_sync     db 'camera ',%LNG%._under_sync,0
  _combobox              db 'combobox',0
  _common_font_name      db 'ms sans serif',0
  _fedit                 db 'fedit',0
  _fedit_font_name       db 'courier new',0
  _fedit.dll0            db '../use/fedit/fedit.dll',0
  _fedit.dll1            db 'fedit.dll',0
  _find_replace          db %LNG%._find_replace,0
  _guiver                db %GUIVER%,0
  _kill                  db '^K ',%LNG%._kill,0
  _micro3d               db 'micro3d',0
  _names                 db '^N ',%LNG%._names,':',0
  _names_under_sync      db 'names ',%LNG%._under_sync,0
  _open_file             db '^O ',%LNG%._open_file,0
  _pause                 db '^P ',%LNG%._pause,0
  _printf.format_errExe  db '"%s" --line=%u --colors=%u',0
  _printf.format_errMsg  db %LNG%._error,9,'= %s',10,%LNG%._file,9,'= %s',10,%LNG%._line,9,'= %u',0
  _printf.format_lbl     db 'LBL %s, %u',0
  _printf.format_var     db 'VAR %s, %f',0
  _replace?              db %LNG%._replace,'?',0
  _run_script            db '^R ',%LNG%._run_script,0
  _save_changed?         db %LNG%._save_changed,'?',0
  _save_file             db '^S ',%LNG%._save_file,0
  _search_complete       db %LNG%._search_complete,0
  _switch_windows        db '^W ',%LNG%._switch_windows,0








section '.rsrc' resource readable

  directory RT_ACCELERATOR,accelerators,\
            RT_DIALOG,dialogs,\
            RT_GROUP_ICON,group_icons,\
            RT_ICON,icons,\
            RT_MENU,menus

  resource accelerators,\
           AXEL,0,axel

  resource dialogs,\
           Interface.InputBoxA.DLG,0,interface.inputboxa.dlg,\
           TEXT.MENU.FINDR,0,text.menu.findr

  resource group_icons,\
           GROUPICO0,0,groupico0;,\
           ;GROUPICO1,0,groupico1,\
           ;GROUPICO2,0,groupico2,\

  resource icons,\
           ICO0,0,ico0;,\
           ;ICO1,0,ico1,\
           ;ICO2,0,ico2,\

  resource menus,\
           TEXT.MENU,0,text.menu

  accelerator axel,\
           \;these are global axels
           FNOINVERT+FCONTROL+FVIRTKEY,'W',AXEL.SW,\
           FNOINVERT+FCONTROL+FVIRTKEY,'S',AXEL.SAVE_FILE,\
           FNOINVERT+FCONTROL+FVIRTKEY,'O',AXEL.OPEN_FILE,\
           FNOINVERT+FCONTROL+FVIRTKEY,'R',AXEL.RUN_SCRIPT,\
           FNOINVERT+FCONTROL+FVIRTKEY,'P',AXEL.PAUSE,\
           FNOINVERT+FCONTROL+FVIRTKEY,'K',AXEL.KILL,\
           FNOINVERT+FCONTROL+FVIRTKEY,'N',AXEL.NAMES,\
           \;local axel keys which are not supported by fedit natively
           FNOINVERT+FCONTROL+FVIRTKEY,'Z',TEXT.MENU.UNDO,\
           FNOINVERT+FCONTROL+FSHIFT+FVIRTKEY,'Z',TEXT.MENU.REDO,\
           FNOINVERT+FCONTROL+FVIRTKEY,'X',TEXT.MENU.CUT,\
           FNOINVERT+FCONTROL+FVIRTKEY,'C',TEXT.MENU.COPY,\
           FNOINVERT+FCONTROL+FVIRTKEY,'V',TEXT.MENU.PASTE,\
           FNOINVERT+FCONTROL+FVIRTKEY,'A',TEXT.MENU.SELECTALL,\
           \;let it be global
           FNOINVERT+FALT    +FVIRTKEY,'C',TEXT.MENU.COLORS,\
           FNOINVERT         +FVIRTKEY,VK_F3,TEXT.MENU.FINDNEXT,\
           FNOINVERT+FCONTROL+FVIRTKEY,'F',TEXT.MENU.FINDR

  dialog interface.inputboxa.dlg,'',40,40,273,144,WS_CAPTION+WS_SYSMENU,,,'courier new',8
    dialogitem 'edit','',Interface.InputBoxA.TXT,3,6,267,114                            ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE+WS_VSCROLL+(ES_MULTILINE+ES_NOHIDESEL+ES_WANTRETURN),WS_EX_CLIENTEDGE
    dialogitem 'button','OK',Interface.InputBoxA.YES,108,126,51,15                      ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE                                                     ,WS_EX_CLIENTEDGE
  enddialog

  dialog text.menu.findr,%LNG%._find_replace,40,40,342,54,WS_CAPTION+WS_SYSMENU
    dialogitem 'static'   ,%LNG%._find             ,-1                    ,3,6,45,9     ,            WS_CHILD           +WS_VISIBLE+(SS_RIGHT)
    dialogitem 'static'   ,%LNG%._replace          ,-1                    ,3,27,45,9    ,            WS_CHILD           +WS_VISIBLE+(SS_RIGHT)

    dialogitem 'combobox' ,''                      ,TEXT.MENU.FINDR.TEXT  ,54,3,186,64  ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE+WS_VSCROLL+(CBS_AUTOHSCROLL+CBS_DROPDOWN)
    dialogitem 'combobox' ,''                      ,TEXT.MENU.FINDR.NEW   ,54,21,186,64 ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE+WS_VSCROLL+(CBS_AUTOHSCROLL+CBS_DROPDOWN)

    dialogitem 'button'   ,%LNG%._case_sensitive   ,TEXT.MENU.FINDR.CASE  ,54,42,90,9   ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE+(BS_AUTOCHECKBOX)
    dialogitem 'button'   ,%LNG%._in_whole_text    ,TEXT.MENU.FINDR.WHOLE ,150,42,90,9  ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE+(BS_AUTOCHECKBOX)
    dialogitem 'button'   ,%LNG%._ask_upon_replace ,TEXT.MENU.FINDR.ASK   ,246,42,90,9  ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE+(BS_AUTOCHECKBOX)

    dialogitem 'button'   ,'<'                     ,TEXT.MENU.FINDR.LEFT  ,246,3,18,15  ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE
    dialogitem 'button'   ,%LNG%._find             ,TEXT.MENU.FINDR.FIND  ,264,3,57,15  ,WS_DISABLED+WS_CHILD+WS_TABSTOP+WS_VISIBLE
    dialogitem 'button'   ,'>'                     ,TEXT.MENU.FINDR.RIGHT ,321,3,18,15  ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE
    dialogitem 'button'   ,%LNG%._replace          ,TEXT.MENU.FINDR.FINDR ,246,24,93,15 ,            WS_CHILD+WS_TABSTOP+WS_VISIBLE
  enddialog

  icon groupico0,ico0,'../ico/TnxGhisler4The.ico';,\
                 ;ico1,'path',\
                 ;ico2,'path',\

  menu text.menu
       menuitem 'Edit',0,MFR_POPUP+MFR_END
                menuitem <%LNG%._undo               ,9,'Ctrl+Z'      >, TEXT.MENU.UNDO
                menuitem <%LNG%._redo               ,9,'Ctrl+Shift+Z'>, TEXT.MENU.REDO
                menuseparator
                menuitem <%LNG%._cut                ,9,'Ctrl+X'      >, TEXT.MENU.CUT
                menuitem <%LNG%._copy               ,9,'Ctrl+C'      >, TEXT.MENU.COPY
                menuitem <%LNG%._paste              ,9,'Ctrl+V'      >, TEXT.MENU.PASTE
                menuitem <%LNG%._delete                              >, TEXT.MENU.DELETE
                menuseparator
                menuitem <%LNG%._select_all         ,9,'Ctrl+A'      >, TEXT.MENU.SELECTALL
                menuitem <%LNG%._vertical_selection ,9,'Alt+Ins'     >, TEXT.MENU.VERTICAL
                menuseparator
                menuitem <%LNG%._cycle_editor_colors,9,'Alt+C'       >, TEXT.MENU.COLORS
                menuseparator
                menuitem <%LNG%._find_next          ,9,'F3'          >, TEXT.MENU.FINDNEXT
                menuitem <%LNG%._find_replace       ,9,'Ctrl+F'      >, TEXT.MENU.FINDR,MFR_END








section 'vars' data readable writable

  _script                      rb sz_script
  candidate_file_name          rb tokens.szFullNameBuf
  common_font                  dd ?
  dataseg                      rb szDataseg
  exePath                      rb tokens.szFullNameBuf
  exePathName                  rb tokens.szFullNameBuf
  exprseg                      rb szExprseg
  fedit_font                   dd ?
  fepos                        FEPOS

  findr:
    .search_settings           rd 1
    ._search_string            rb 1000h
  .sz_search_string             = $-._search_string
    ._replace_string           rb 1000h
  .sz_replace_string            = $-._replace_string

  flags                        dd ?
  hAxel                        dd ?
  hCam                         dd ?
  hGrp1                        dd ?
  hKill                        dd ?
  hNames                       dd ?
  hOpen                        dd ?
  hPause                       dd ?
  hRun                         dd ?
  hSave                        dd ?
  hScript                      dd ?
  hSearchHistory               dd ?
  hSW                          dd ?
  hTxt                         dd ?
  hTxt.editor_colors.?         dd ?
  hTxt.menu                    dd ?
  hWnd                         dd ?

  ;to be used directly by script
  Interface.flags              dd ?
  Interface.height             dd ?
  Interface.InputBoxA.buffer   dd ?
  Interface.InputBoxA.szBuffer dd ?
  Interface.last_token         dd ?
  Interface.width              dd ?

  ioResult                     dd ?,?
  last_bmp32                   dd ?
  msg                          MSG
  names                        dd ?
  ofn                          OPENFILENAME
  printf.buffer                rb printf.szBuffer
  ps                           PAINTSTRUCT
  rect                         RECT
  tokenseg                     rb szTokenseg
  wc                           WNDCLASSEX








section 'code' code data executable readable

entry $

;cpuid

       sub      ebx,ebx

       call     cpuid'.sse1
       shl      eax,tokens.flagSSE1
       or       ebx,eax

       call     cpuid'.sse2
       shl      eax,tokens.flagSSE2
       or       ebx,eax

       mov      [Interface.flags],ebx








;paths

        invoke  GetCurrentDirectoryA,tokens.szFullNameBuf,exePath
        invoke  GetModuleFileNameA,0,exePathName,tokens.szFullNameBuf








;create controls, mostly

        ;fonts
        invoke  CreateFontA,-8,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,_common_font_name
        mov     [common_font],eax
        invoke  CreateFontA,-15,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,_fedit_font_name
        mov     [fedit_font],eax

        ;main class & window,groupbox template
        mov     [wc.cbSize],sizeof.WNDCLASSEX
        mov     [wc.style],CS_DBLCLKS
        mov     [wc.lpfnWndProc],WindowProc
        invoke  GetModuleHandleA,0
        mov     [wc.hInstance],eax
        invoke  LoadIconA,[wc.hInstance],GROUPICO0
        mov     [wc.hIcon],eax
        invoke  LoadCursorA,0,IDC_ARROW
        mov     [wc.hCursor],eax
        mov     [wc.hbrBackground],COLOR_BTNFACE+1
        mov     [wc.lpszClassName],_micro3d
        invoke  RegisterClassExA,wc
        invoke  CreateWindowExA,0,_micro3d,0,WS_CAPTION+WS_CLIPCHILDREN+WS_MAXIMIZEBOX+WS_MINIMIZEBOX+WS_SIZEBOX+WS_SYSMENU+WS_VISIBLE,WINDOW.LEFT,WINDOW.TOP,WINDOW.WIDTH,WINDOW.HEIGHT,0,0,[wc.hInstance],0
        mov     [hWnd],eax
        invoke  DragAcceptFiles,[hWnd],1

        ;window to draw in
        mov     [Interface.width],INTERFACE.WIDTH
        mov     [Interface.height],INTERFACE.HEIGHT
        invoke  CreateWindowExA,0,_micro3d,_camera,WS_CAPTION+WS_CHILD+WS_TABSTOP+0*WS_VISIBLE,INTERFACE.LEFT,INTERFACE.TOP,INTERFACE.WIDTH,INTERFACE.HEIGHT,[hWnd],0,[wc.hInstance],0
        mov     [hCam],eax
        invoke  SendMessageA,eax,WM_SETFONT,[common_font],0

        ;fedit control
        invoke  LoadLibraryA,_fedit.dll0
        invoke  LoadLibraryA,_fedit.dll1
        invoke  CreateWindowExA,0,_fedit,0,ES_MULTILINE+ES_NOHIDESEL+ES_WANTRETURN+WS_BORDER+WS_CHILD+WS_HSCROLL+WS_TABSTOP+1*WS_VISIBLE+WS_VSCROLL,INTERFACE.LEFT,INTERFACE.TOP,INTERFACE.WIDTH,INTERFACE.HEIGHT,[hWnd],0,[wc.hInstance],0
        mov     [hTxt],eax
        invoke  SendMessageA,eax,WM_SETFONT,[fedit_font],0
        invoke  SendMessageA,[hTxt],WM_SETTEXT,0,_guiver
        btr     [flags],flagTEXT_CHANGED
        ;fedit style
        invoke  GetWindowLongA,[hTxt],GWL_STYLE
        or      eax,FES_AUTOINDENT+FES_CONSOLECARET+FES_SMARTTABS
        invoke  SetWindowLongA,[hTxt],GWL_STYLE,eax
        ;fedit colors
        mov     [hTxt.editor_colors.?],editor_colors.01 - sizeof.EDITOR_COLORS
        call    cycle_editor_colors
        ;fedit menu
        invoke  LoadMenuA,[wc.hInstance],TEXT.MENU
        invoke  GetSubMenu,eax,0
        mov     [hTxt.menu],eax
        invoke  SendMessageA,[hTxt],FEM_SETRIGHTCLICKMENU,eax,[hWnd]

        ;group1
        invoke  CreateWindowExA,0,_micro3d,0,WS_CHILD+WS_CLIPCHILDREN+WS_VISIBLE,GROUP1.LEFT,GROUP1.TOP,GROUP1.WIDTH,GROUP1.HEIGHT,[hWnd],0,[wc.hInstance],0
        mov     [hGrp1],eax
        invoke  SendMessageA,eax,WM_SETFONT,[common_font],0

        invoke  CreateWindowExA,WS_EX_STATICEDGE,_button,_switch_windows,BS_PUSHBUTTON+WS_CHILD+WS_TABSTOP+WS_VISIBLE,6,12,137,25,[hGrp1],0,[wc.hInstance],0
        mov     [hSW],eax
        invoke  SendMessageA,eax,WM_SETFONT,[common_font],0

        invoke  CreateWindowExA,WS_EX_STATICEDGE,_button,_save_file,BS_PUSHBUTTON+WS_CHILD+WS_TABSTOP+WS_VISIBLE,6,44,137,25,[hGrp1],0,[wc.hInstance],0
        mov     [hSave],eax
        invoke  SendMessageA,eax,WM_SETFONT,[common_font],0
        invoke  CreateWindowExA,WS_EX_STATICEDGE,_button,_open_file,BS_PUSHBUTTON+WS_CHILD+WS_TABSTOP+WS_VISIBLE,6,69,137,25,[hGrp1],0,[wc.hInstance],0
        mov     [hOpen],eax
        invoke  SendMessageA,eax,WM_SETFONT,[common_font],0

        invoke  CreateWindowExA,WS_EX_STATICEDGE,_button,_run_script,BS_PUSHBUTTON+WS_CHILD+WS_TABSTOP+WS_VISIBLE,6,103,137,25,[hGrp1],0,[wc.hInstance],0
        mov     [hRun],eax
        invoke  SendMessageA,eax,WM_SETFONT,[common_font],0
        invoke  CreateWindowExA,WS_EX_STATICEDGE,_button,_pause,BS_PUSHBUTTON+WS_CHILD+WS_DISABLED+WS_TABSTOP+WS_VISIBLE,6,128,68,25,[hGrp1],0,[wc.hInstance],0
        mov     [hPause],eax
        invoke  SendMessageA,eax,WM_SETFONT,[common_font],0
        invoke  CreateWindowExA,WS_EX_STATICEDGE,_button,_kill,BS_PUSHBUTTON+WS_CHILD+WS_DISABLED+WS_TABSTOP+WS_VISIBLE,75,128,68,25,[hGrp1],0,[wc.hInstance],0
        mov     [hKill],eax
        invoke  SendMessageA,eax,WM_SETFONT,[common_font],0

        invoke  CreateWindowExA,0,_combobox,_names,CBS_AUTOHSCROLL+CBS_DROPDOWN+CBS_SORT+WS_CHILD+WS_TABSTOP+WS_VISIBLE+WS_VSCROLL,6,163,137,300,[hGrp1],0,[wc.hInstance],0
        mov     [hNames],eax
        invoke  SendMessageA,eax,WM_SETFONT,[common_font],0
        invoke  SendMessageA,[hNames],WM_SETTEXT,0,_names
        invoke  SendMessageA,[hNames],CB_SETDROPPEDWIDTH,300,0

        ;search history
        invoke  CreateWindowExA,0,_combobox,0,CBS_SORT+WS_CHILD,0,0,128,128,[hWnd],0,[wc.hInstance],0
        mov     [hSearchHistory],eax








;command line parse

cmdLn:
  .file_or_"file"_pattern:
        invoke  GetCommandLineA
        mov     esi,eax
        mov     edi,candidate_file_name
        lodsb
        cmp     al,'"'
        mov     ah,al
        je      .skip_us
        mov     ah,' '
  .skip_us:
        lodsb
        cmp     al,0
        jz      .no_file
        cmp     al,ah
        jne     .skip_us
  .find_file:
        lodsb
        cmp     al,0
        jz      .no_file
        cmp     al,' '
        je      .find_file
        cmp     al,'"'
        mov     ah,al
        je      .copy_file
        mov     ah,' '
        dec     esi
  .copy_file:
        mov     ecx,tokens.szFullNameBuf
    ..cf.loop:
        lodsb
        cmp     al,0
        jz      .copied_file
        cmp     al,ah
        je      .copied_file
        sub     ecx,1
        JNA     .no_file ;NZ&NC as there must be place for 0byte-terminator
        stosb
        jmp     ..cf.loop
  .copied_file:
        mov     byte[edi],0
        call    load_script_from_file.read
  .___line_number_pattern:
        stdcall posz,0,0,___line_,esi,1,0
        test    eax,eax
        jz      .no_line
        lea     eax,[esi+eax-1 +7] ;skip pattern
        ccall   get_float,eax,printf.buffer
        jc      .no_line
        push    eax
        fistp   dword[esp]
        pop     eax
        call    highlight_eax_line_in_text
  .no_line:
  .___colors_number_pattern:
        stdcall posz,0,0,___colors_,esi,1,0
        test    eax,eax
        jz      .no_colors
        lea     eax,[esi+eax-1 +9] ;skip pattern
        ccall   get_float,eax,printf.buffer
        jc      .no_colors
        push    eax
        fistp   dword[esp]
        pop     eax
        cmp     eax,(editor_colors.-editor_colors)/sizeof.EDITOR_COLORS
        ja      .no_colors
        dec     eax
        imul    eax,sizeof.EDITOR_COLORS
        add     eax,editor_colors
        call    cycle_editor_colors.apply
  .no_colors:
  .no_file:








;life

        invoke  LoadAcceleratorsA,[wc.hInstance],AXEL
        mov     [hAxel],eax
life:   invoke  GetMessageA,msg,0,0,0
        test    eax,eax
        jz      life.
        invoke  TranslateAcceleratorA,[hWnd],[hAxel],msg
        btr     [flags],flagAXEL_CONCEDED
        jc      .ok1
        test    eax,eax
        jnz     life
  .ok1: invoke  TranslateMessage,msg
        invoke  DispatchMessageA,msg
        jmp     life
  .:    invoke  DeleteObject,[common_font]
        invoke  DeleteObject,[fedit_font]
        invoke  ExitProcess,[msg.wParam]








;main dialog proc

WindowProc: ;wnd,msg,wparam,lparam
        push    ebp
        mov     ebp,esp
.lparam label dword at ebp+5*4
.wparam label dword at ebp+4*4
.msg    label dword at ebp+3*4
.wnd    label dword at ebp+2*4
        push    ebx esi edi








;IF-THEN top management :)

        mov     eax,[.msg]

        cmp     eax,SYNC.BMP32.SCREEN.DISABLE
        je      .SYNC.bmp32.screen.disable
        cmp     eax,SYNC.BMP32.SCREEN.ENABLE
        je      .SYNC.bmp32.screen.enable
        cmp     eax,SYNC.NAMES.DISABLE
        je      .SYNC.names.disable
        cmp     eax,SYNC.NAMES.ENABLE
        je      .SYNC.names.enable
        cmp     eax,SYNC.NAMES.LIST
        je      .SYNC.names.list
        cmp     eax,SYNC.LOCK_CONTROLS
        je      .SYNC.lock_controls
        cmp     eax,SYNC.UNLOCK_CONTROLS
        je      .SYNC.unlock_controls
        cmp     eax,FEM_HIGHLIGHTLINE
        je      .hTxt.FEM_HIGHLIGHTLINE

        cmp     eax,WM_CLOSE
        je      .wm_close
        cmp     eax,WM_COMMAND
        je      .wm_command
        cmp     eax,WM_CREATE
        je      .wm_create
        cmp     eax,WM_DROPFILES
        je      .wm_dropfiles
        cmp     eax,WM_GETMINMAXINFO
        je      .wm_getminmaxinfo
        cmp     eax,WM_INITMENU
        je      .wm_initmenu
        cmp     eax,WM_PAINT
        je      .wm_paint
        cmp     eax,WM_SIZE
        je      .wm_size
  .default:
        invoke  DefWindowProcA,[.wnd],[.msg],[.wparam],[.lparam]
        jmp     .ret

  .bn_clicked:
        mov     eax,[.lparam]
        cmp     eax,[hSW]
        je      .hSW.bn_clicked
        cmp     eax,[hSave]
        je      .hSave.bn_clicked
        cmp     eax,[hOpen]
        je      .hOpen.bn_clicked
        cmp     eax,[hRun]
        je      .hRun.bn_clicked
        cmp     eax,[hPause]
        je      .hPause.bn_clicked
        cmp     eax,[hKill]
        je      .hKill.bn_clicked
        jmp     .default

  .cbn_selchange:
        mov     eax,[.lparam]
        cmp     eax,[hNames]
        je      .hNames.cbn_selchange
        jmp     .default

  .en_change:
  .fen_textchange:
        mov     eax,[.lparam]
        cmp     eax,[hTxt]
        je      .hTxt.change
        jmp     .default

  .wm_close:
        bt      [flags],flagTEXT_CHANGED
        jnc     .close
        invoke  MessageBoxA,[hWnd],(_script+tokens.ScriptFileOf),_save_changed?,MB_YESNOCANCEL
        cmp     eax,IDCANCEL
        je      .retz
        cmp     eax,IDNO
        je      .close
        call    save_script_to_file
        jc      .retz
      .close:
        invoke  PostQuitMessage,0
        jmp     .retz

  .wm_command:
        cmp     [.lparam],0
        je      .wm_command_axel_or_menu
        movzx   eax,word[.wparam+2]
        cmp     eax,BN_CLICKED
        je      .bn_clicked
        cmp     eax,CBN_SELCHANGE
        je      .cbn_selchange
        cmp     eax,EN_CHANGE
        je      .en_change
        cmp     eax,FEN_TEXTCHANGE
        je      .fen_textchange
        jmp     .default

  .wm_command_axel_or_menu:
        movzx   eax,word[.wparam]

        cmp     eax,AXEL.SW
        je      .hSW.bn_clicked
        cmp     eax,AXEL.OPEN_FILE
        je      .hOpen.bn_clicked
        cmp     eax,AXEL.SAVE_FILE
        je      .hSave.bn_clicked
        cmp     eax,AXEL.RUN_SCRIPT
        je      .hRun.bn_clicked
        cmp     eax,AXEL.PAUSE
        je      .hPause.bn_clicked
        cmp     eax,AXEL.KILL
        je      .hKill.bn_clicked
        cmp     eax,AXEL.NAMES
        je      .hNames.cb_showdropdown

        cmp     eax,TEXT.MENU.UNDO
        je      .hTxt.menu.undo
        cmp     eax,TEXT.MENU.REDO
        je      .hTxt.menu.redo
        cmp     eax,TEXT.MENU.CUT
        je      .hTxt.menu.cut
        cmp     eax,TEXT.MENU.COPY
        je      .hTxt.menu.copy
        cmp     eax,TEXT.MENU.PASTE
        je      .hTxt.menu.paste
        cmp     eax,TEXT.MENU.DELETE
        je      .hTxt.menu.delete
        cmp     eax,TEXT.MENU.SELECTALL
        je      .hTxt.menu.selectall
        cmp     eax,TEXT.MENU.VERTICAL
        je      .hTxt.menu.vertical
        cmp     eax,TEXT.MENU.COLORS
        je      .hTxt.menu.colors
        cmp     eax,TEXT.MENU.FINDNEXT
        je      .hTxt.menu.findnext
        cmp     eax,TEXT.MENU.FINDR
        je      .hTxt.menu.findr

        jmp     .default

  .wm_create:
        invoke  SetFocus,[hTxt]
        jmp     .retz

  .wm_dropfiles:
        bt      [flags],flagTEXT_CHANGED
        jnc     .drag
        invoke  MessageBoxA,[hWnd],(_script+tokens.ScriptFileOf),_save_changed?,MB_YESNOCANCEL
        cmp     eax,IDCANCEL
        je      .drag_finish
        cmp     eax,IDNO
        je      .drag
        call    save_script_to_file
        jc      .drag_finish
      .drag:
        invoke  DragQueryFileA,[.wparam],0,candidate_file_name,tokens.szFullNameBuf
        call    load_script_from_file.read
      .drag_finish:
        invoke  DragFinish,[.wparam]
        jmp     .retz

  .wm_getminmaxinfo:
        mov     eax,[.wnd]
        cmp     eax,[hWnd]
        je      .hWnd.wm_getminmaxinfo
        cmp     eax,[hCam]
        je      .hCam.wm_getminmaxinfo
        jmp     .default

  .wm_initmenu:
        mov     eax,[.wparam]
        cmp     eax,[hTxt.menu]
        je      .hTxt.menu.init
        jmp     .default

  .wm_paint:
        mov     eax,[.wnd]
        cmp     eax,[hCam]
        je      .hCam.wm_paint
        jmp     .default

  .wm_size:
        mov     eax,[.wnd]
        cmp     eax,[hWnd]
        je      .hWnd.wm_size
        jmp     .default








;specialized managers, listed in the order of their respective controls

  .hWnd.wm_getminmaxinfo:
        mov     eax,[.lparam]
        mov     [eax+MINMAXINFO.ptMinTrackSize.x],WINDOW.WIDTH
        mov     [eax+MINMAXINFO.ptMinTrackSize.y],WINDOW.HEIGHT
        jmp     .retz

  .hWnd.wm_size:
        invoke  GetWindowRect,[.wnd],rect
        mov     esi,[rect+RECT.right]
        sub     esi,[rect+RECT.left]  ;width
        mov     edi,[rect+RECT.bottom]
        sub     edi,[rect+RECT.top]   ;height

        lea     eax,[esi-(WINDOW.WIDTH-INTERFACE.WIDTH)]
        mov     [Interface.width],eax
        lea     eax,[edi-(WINDOW.HEIGHT-INTERFACE.HEIGHT)]
        mov     [Interface.height],eax

        invoke  SetWindowPos,[hCam],0,INTERFACE.LEFT,INTERFACE.TOP,[Interface.width],[Interface.height],0
        invoke  SetWindowPos,[hTxt],0,INTERFACE.LEFT,INTERFACE.TOP,[Interface.width],[Interface.height],0

        lea     eax,[esi-(WINDOW.WIDTH-GROUP1.LEFT)]
        invoke  SetWindowPos,[hGrp1],0,eax,GROUP1.TOP,GROUP1.WIDTH,GROUP1.HEIGHT,0

        jmp     .retz

  .SYNC.lock_controls:
        invoke  GetWindowLongA,[hWnd],GWL_STYLE
        and     eax,not(WS_MAXIMIZEBOX or WS_SIZEBOX)
        invoke  SetWindowLongA,[hWnd],GWL_STYLE,eax
        invoke  RedrawWindow,[hWnd],0,0,RDW_INVALIDATE+RDW_FRAME+RDW_UPDATENOW

        invoke  EnableWindow,[hOpen],0
        invoke  DragAcceptFiles,[hWnd],0
        invoke  EnableWindow,[hRun],0
        invoke  EnableWindow,[hPause],1
        invoke  EnableWindow,[hKill],1

        invoke  SendMessageA,[hNames],CB_RESETCONTENT,0,0
        jmp     .retz

  .SYNC.unlock_controls:
        invoke  GetWindowLongA,[hWnd],GWL_STYLE
        or      eax,WS_MAXIMIZEBOX or WS_SIZEBOX
        invoke  SetWindowLongA,[hWnd],GWL_STYLE,eax
        invoke  RedrawWindow,[hWnd],0,0,RDW_INVALIDATE+RDW_FRAME+RDW_UPDATENOW

        invoke  EnableWindow,[hOpen],1
        invoke  DragAcceptFiles,[hWnd],1
        invoke  EnableWindow,[hRun],1
        invoke  EnableWindow,[hPause],0
        invoke  EnableWindow,[hKill],0
        jmp     .retz








  .hCam.under_sync:
        invoke  SendMessageA,[hCam],WM_SETTEXT,0,_camera_under_sync
        jmp     .default

  .hCam.wm_getminmaxinfo:
        mov     eax,[.lparam]
        mov     [eax+MINMAXINFO.ptMinTrackSize.x],32
        mov     [eax+MINMAXINFO.ptMinTrackSize.y],32
        jmp     .retz

  .hCam.wm_paint:
        bt      [flags],flagSYNC.BMP32.SCREEN.ENABLE
        jnc     .hCam.under_sync
        mov     ebx,[last_bmp32]
        test    ebx,ebx
        jz      .hCam.under_sync
        ;                           ;see bmp32.inc file first
        push    SRCCOPY             ;operation
        push    0                   ;0
            lea eax,[ebx+bmp32.BITMAPINFO]
        push    eax                 ;@BITMAPINFO
            mov eax,[ebx+bmp32.bfOffBits]
            add eax,ebx
        push    eax                 ;@bits
            mov eax,[ebx+bmp32.biHeight]
            neg eax
        push    eax                 ;src.rect.height: negative - StretchDIBits will scan lines down^up
        push    [ebx+bmp32.biWidth] ;src.rect.width
            not eax ;=neg-1
        push    eax                 ;src.y: at down-most line 0
        push    0                   ;src.x
        push    [Interface.height]  ;dst.rect.height
        push    [Interface.width]   ;dst.rect.width
        push    0                   ;dst.y
        push    0                   ;dst.x
         invoke BeginPaint,[hCam],ps
        push    eax                 ;dst
        invoke  StretchDIBits
        ;
        invoke  EndPaint,[hCam],ps
        invoke  SendMessageA,[hCam],WM_SETTEXT,0,_camera
        jmp     .retz

  .SYNC.bmp32.screen.disable:
        btr     [flags],flagSYNC.BMP32.SCREEN.ENABLE
        jmp     .retz

  .SYNC.bmp32.screen.enable:
        bts     [flags],flagSYNC.BMP32.SCREEN.ENABLE
        jmp     .retz








  .hTxt.axel.concede?:
        invoke  GetFocus
        cmp     eax,[hTxt]
        pop     eax
        jne     .hTxt.axel.concede
        jmp     eax
      .hTxt.axel.concede:
        bts     [flags],flagAXEL_CONCEDED
        jmp     .retz

  .hTxt.change:
        bts     [flags],flagTEXT_CHANGED
        invoke  SendMessageA,[hSave],WM_SETFONT,0,1
        jmp     .retz

  .hTxt.FEM_HIGHLIGHTLINE:
        mov     eax,[.wparam]
        call    highlight_eax_line_in_text
        jmp     .retz

  .hTxt.menu.init:
        invoke  SendMessageA,[hTxt],EM_CANUNDO,0,0
        xor     al,MF_GRAYED ;xor 1
        invoke  EnableMenuItem,[hTxt.menu],TEXT.MENU.UNDO,eax

        invoke  SendMessageA,[hTxt],FEM_CANREDO,0,0
        xor     al,MF_GRAYED
        invoke  EnableMenuItem,[hTxt.menu],TEXT.MENU.REDO,eax

        invoke  SendMessageA,[hTxt],FEM_GETPOS,fepos,0 ;TG: add FEM_ISSEL or GETPOS via EAX
        mov     ebx,[fepos.selectionLine]
        sub     ebx,[fepos.caretLine]
        mov     eax,[fepos.selectionPosition]
        sub     eax,[fepos.caretPosition]
        or      eax,ebx
        setz    al;MF_GRAYED if zero
        movzx   eax,al
        push    eax TEXT.MENU.CUT [hTxt.menu]  ;TG: in fasmw CUT remains visible - bug
        push    eax TEXT.MENU.COPY [hTxt.menu]
        push    eax TEXT.MENU.DELETE [hTxt.menu]
        invoke  EnableMenuItem
        invoke  EnableMenuItem
        invoke  EnableMenuItem

        invoke  IsClipboardFormatAvailable,CF_TEXT
        xor     al,MF_GRAYED
        invoke  EnableMenuItem,[hTxt.menu],TEXT.MENU.PASTE,eax

        invoke  SendMessageA,[hTxt],FEM_GETMODE,0,0
        test    eax,FEMODE_VERTICALSEL
        setnz   al
        movzx   eax,al
        imul    eax,MF_CHECKED ;*8
        invoke  CheckMenuItem,[hTxt.menu],TEXT.MENU.VERTICAL,eax

        jmp     .retz

  .hTxt.menu.undo:
        call    .hTxt.axel.concede? ;we check it as called both by the menu item and axel.
        invoke  SendMessageA,[hTxt],WM_UNDO,0,0
        jmp     .retz
  .hTxt.menu.redo:
        call    .hTxt.axel.concede?
        invoke  SendMessageA,[hTxt],FEM_REDO,0,0
        jmp     .retz
  .hTxt.menu.cut:
        call    .hTxt.axel.concede?
        invoke  SendMessageA,[hTxt],WM_CUT,0,0
        jmp     .retz
  .hTxt.menu.copy:
        call    .hTxt.axel.concede?
        invoke  SendMessageA,[hTxt],WM_COPY,0,0
        jmp     .retz
  .hTxt.menu.paste:
        call    .hTxt.axel.concede?
        invoke  SendMessageA,[hTxt],WM_PASTE,0,0
        jmp     .retz
  .hTxt.menu.delete:
        call    .hTxt.axel.concede?
        invoke  SendMessageA,[hTxt],WM_CLEAR,0,0
        jmp     .retz
  .hTxt.menu.selectall: ;TG: add FEM_SELECTALL
        call    .hTxt.axel.concede?
        mov     [fepos.selectionLine],1
        mov     [fepos.selectionPosition],1
        mov     [fepos.caretLine],-1
        mov     [fepos.caretPosition],1
        invoke  SendMessageA,[hTxt],FEM_SETPOS,fepos,0
        invoke  SendMessageA,[hTxt],FEM_GETPOS,fepos,0
        invoke  SendMessageA,[hTxt],FEM_GETLINELENGTH,[fepos.caretLine],0
        inc     eax
        mov     [fepos.caretPosition],eax
        invoke  SendMessageA,[hTxt],FEM_SETPOS,fepos,0
        jmp     .retz
  .hTxt.menu.vertical:
        call    .hTxt.axel.concede?
        invoke  SendMessageA,[hTxt],FEM_GETMODE,0,0
        xor     eax,FEMODE_VERTICALSEL
        invoke  SendMessageA,[hTxt],FEM_SETMODE,eax,0
        jmp     .retz
  .hTxt.menu.colors:
        ;call    .hTxt.axel.concede?
        call    cycle_editor_colors
        jmp     .retz
  .hTxt.menu.findnext:
        ;call    .hTxt.axel.concede?
        invoke  SendMessageA,[hTxt],FEM_FINDNEXT,0,0
        test    eax,eax
        jnz     .retz
        invoke  SendMessageA,[hTxt],FEM_RELEASESEARCH,0,0
  .hTxt.menu.findr:
        ;call    .hTxt.axel.concede?
        invoke  DialogBoxParamA,[wc.hInstance],TEXT.MENU.FINDR,[hWnd],FindrProc,0
        invoke  SetFocus,[hTxt]
        jmp     .retz








  .hSW.bn_clicked:
        call    switch_windows
        jmp     .retz

  .hSave.bn_clicked:
        call    save_script_to_file
        jmp     .retz
  .hOpen.bn_clicked:
        invoke  IsWindowEnabled,[hOpen] ;we check it as called both by the button and axel. while the button itself may be disabled
        test    eax,eax
        jz      .retz
        call    load_script_from_file
        jmp     .retz

  .hRun.bn_clicked:
        invoke  IsWindowEnabled,[hRun]
        test    eax,eax
        jz      .retz
        call    run_script
        jmp     .retz
  .hPause.bn_clicked:
        invoke  IsWindowEnabled,[hPause]
        test    eax,eax
        jz      .retz
        call    pause_script
        jmp     .retz
  .hKill.bn_clicked:
        invoke  IsWindowEnabled,[hKill]
        test    eax,eax
        jz      .retz
        call    kill_script
        jmp     .retz








  .hNames.cbn_selchange:
        bt      [flags],flagSYNC.NAMES.ENABLE
        jnc     .hNames.under_sync
        invoke  SendMessageA,[hNames],CB_GETCURSEL,0,0
        cmp     eax,-1
        je      .retz
        invoke  SendMessageA,[hNames],CB_GETITEMDATA,eax,0
        mov     ebx,eax
        call    highlight_ebx_token_in_text
        jmp     .retz

  .hNames.under_sync:
        invoke  SendMessageA,[hNames],WM_SETTEXT,0,_names_under_sync
        jmp     .retz

  .SYNC.names.disable:
        btr     [flags],flagSYNC.NAMES.ENABLE
        jmp     .retz

  .SYNC.names.enable:
        bts     [flags],flagSYNC.NAMES.ENABLE
        jmp     .retz

  .SYNC.names.list:
        bt      [flags],flagSYNC.NAMES.ENABLE
        jnc     .hNames.under_sync
        sub     esp,tokens.szFullNameBuf
        mov     edi,esp
        invoke  SendMessageA,[hNames],CB_GETCURSEL,0,0
        push    eax
        invoke  SendMessageA,[hNames],CB_RESETCONTENT,0,0
        mov     ebx,[names]
        jmp     .SYNC.names.list.last
      .SYNC.names.list.prev:
        mov     ebx,[ebx+token.chained]
      .SYNC.names.list.last:
        test    ebx,ebx
        jz      .SYNC.names.list.ret
        stdcall get_full_name_and_padzero,ebx,edi
        cmp     [ebx+token.ptr_in_table],tokens.label
        je      .SYNC.names.list.lbl
        fld     [ebx+token.var_rw]
        fstp    qword[ioResult]
        cinvoke printf,printf.buffer,printf.szBuffer,_printf.format_var, esp, edi,[ioResult],[ioResult+4]
        jmp     .SYNC.names.list.var
      .SYNC.names.list.lbl:
        cinvoke printf,printf.buffer,printf.szBuffer,_printf.format_lbl, esp, edi,[ebx+token.label_in_dataseg]
      .SYNC.names.list.var:
        invoke  SendMessageA,[hNames],CB_ADDSTRING,0,printf.buffer
        invoke  SendMessageA,[hNames],CB_SETITEMDATA,eax,ebx
        jmp     .SYNC.names.list.prev
      .SYNC.names.list.ret:
        add     esp,tokens.szFullNameBuf
        pop     eax
        invoke  SendMessageA,[hNames],CB_SETCURSEL,eax,0
        invoke  SendMessageA,[hNames],CB_SHOWDROPDOWN,1,0
        jmp     .retz

  .hNames.cb_showdropdown:
        invoke  SendMessageA,[hNames],CB_GETDROPPEDSTATE,0,0
        xor     al,1
        invoke  SendMessageA,[hNames],CB_SHOWDROPDOWN,eax,0
        jmp     .retz







;proc end

.retz:  sub     eax,eax
.ret:   pop     edi esi ebx
        pop     ebp
        ret     4*4








;findr dialog proc(s)
;mind eax,ecx,edx

ComboAddHistoryString: ;combo,history_string
        push    ebp
        mov     ebp,esp
.history_string label dword at ebp+3*4
.combo          label dword at ebp+2*4
        mov     eax,[.history_string]
        cmp     byte[eax],0
        jz      .ret
        invoke  SendMessageA,[.combo],CB_FINDSTRINGEXACT,-1,eax
        cmp     eax,-1
        jne     .ret
        invoke  SendMessageA,[.combo],CB_ADDSTRING,0,[.history_string]
  .ret: pop     ebp
        ret     2*4








ComboCopyStrings: ;dst_combo,src_combo,buffer
        push    ebp
        mov     ebp,esp
.buffer    label dword at ebp+4*4
.src_combo label dword at ebp+3*4
.dst_combo label dword at ebp+2*4
        invoke  SendMessageA,[.dst_combo],CB_RESETCONTENT,0,0
        invoke  SendMessageA,[.src_combo],CB_GETCOUNT,0,0
        push    eax
.id        label dword at ebp-1*4
  .loop:sub     [.id],1
        jc      .ret
        invoke  SendMessageA,[.src_combo],CB_GETLBTEXT,[.id],[.buffer]
        invoke  SendMessageA,[.dst_combo],CB_INSERTSTRING,0,[.buffer]
        jmp     .loop
  .ret: pop     eax
        pop     ebp
        ret     3*4








FindrProc: ;wnd,msg,wparam,lparam
        push    ebp
        mov     ebp,esp
.lparam label dword at ebp+5*4
.wparam label dword at ebp+4*4
.msg    label dword at ebp+3*4
.wnd    label dword at ebp+2*4

        mov     eax,[.msg]
        cmp     eax,WM_CLOSE
        je      .wm_close
        cmp     eax,WM_COMMAND
        je      .wm_command
        cmp     eax,WM_INITDIALOG
        je      .wm_initdialog

  .retz:sub     eax,eax

  .ret: pop     ebp
        ret     4*4

  .wm_close:
        invoke  EndDialog,[.wnd],eax
        jmp     .retz

  .wm_command:
        mov     eax,[.wparam]

        cmp     eax,BN_CLICKED shl 16 + TEXT.MENU.FINDR.CASE
        je      .case
        cmp     eax,BN_CLICKED shl 16 + TEXT.MENU.FINDR.WHOLE
        je      .whole
        cmp     eax,BN_CLICKED shl 16 + TEXT.MENU.FINDR.ASK
        je      .ask

        cmp     eax,BN_CLICKED shl 16 + TEXT.MENU.FINDR.LEFT
        je      .left
        cmp     eax,BN_CLICKED shl 16 + TEXT.MENU.FINDR.RIGHT
        je      .right
        cmp     eax,BN_CLICKED shl 16 + TEXT.MENU.FINDR.FINDR
        je      .findr

        jmp     .retz








  .case:
        xor     [findr.search_settings],FEFIND_CASESENSITIVE
        jmp     .retz
  .whole:
        xor     [findr.search_settings],FEFIND_INWHOLETEXT
        jmp     .retz
  .ask:
        xor     [findr.search_settings],FEFIND_ASKREPLACE ;TG: instead of command_flags
        jmp     .retz

  .left:
        or      [findr.search_settings],FEFIND_BACKWARD
        jmp     ..find_first
  .right:
        and     [findr.search_settings],not FEFIND_BACKWARD
    ..find_first:
        invoke  GetDlgItemTextA,[.wnd],TEXT.MENU.FINDR.TEXT,findr._search_string,findr.sz_search_string
        call    ..add_text_to_history
        invoke  SendMessageA,[hTxt],FEM_FINDFIRST,[findr.search_settings],findr._search_string
        test    eax,eax
        jnz     .wm_close
    ..not_found:
        invoke  SendMessageA,[hTxt],FEM_RELEASESEARCH,0,0
        invoke  MessageBoxA,[.wnd],_search_complete,_find_replace,MB_ICONINFORMATION
        jmp     .retz
    ..add_text_to_history:
        stdcall ComboAddHistoryString,[hSearchHistory],findr._search_string
        invoke  GetDlgItem,[.wnd],TEXT.MENU.FINDR.TEXT
        stdcall ComboAddHistoryString,eax,findr._search_string
        invoke  GetDlgItem,[.wnd],TEXT.MENU.FINDR.NEW
        stdcall ComboAddHistoryString,eax,findr._search_string
        ret
    ..add_new_to_history:
        stdcall ComboAddHistoryString,[hSearchHistory],findr._replace_string
        invoke  GetDlgItem,[.wnd],TEXT.MENU.FINDR.TEXT
        stdcall ComboAddHistoryString,eax,findr._replace_string
        invoke  GetDlgItem,[.wnd],TEXT.MENU.FINDR.NEW
        stdcall ComboAddHistoryString,eax,findr._replace_string
        ret
  .findr:
        invoke  GetDlgItemTextA,[.wnd],TEXT.MENU.FINDR.TEXT,findr._search_string,findr.sz_search_string
        invoke  GetDlgItemTextA,[.wnd],TEXT.MENU.FINDR.NEW,findr._replace_string,findr.sz_replace_string
        call    ..add_text_to_history
        call    ..add_new_to_history
        invoke  SendMessageA,[hTxt],FEM_FINDFIRST,[findr.search_settings],findr._search_string
        test    eax,eax
        jz      ..not_found
        invoke  SendMessageA,[hTxt],FEM_GETMODE,0,0
        push    eax
        and     eax,not (FEMODE_VERTICALSEL + FEMODE_OVERWRITE)
        invoke  SendMessageA,[hTxt],FEM_SETMODE,eax,0
        invoke  ShowWindow,[.wnd],SW_HIDE
    ..confirm_replace:
        test    [findr.search_settings],FEFIND_ASKREPLACE
        jz      ..replace
        invoke  MessageBoxA,[hWnd],_replace?,_find_replace,MB_ICONQUESTION+MB_YESNOCANCEL
        cmp     eax,IDCANCEL
        je      ..replace_finish
        cmp     eax,IDNO
        je      ..replace_next
    ..replace:
        invoke  SendMessageA,[hTxt],EM_REPLACESEL,FALSE,findr._replace_string
    ..replace_next:
        invoke  SendMessageA,[hTxt],FEM_FINDNEXT,0,0
        test    eax,eax
        jnz     ..confirm_replace
    ..replace_finish:
        pop     eax
        invoke  SendMessageA,[hTxt],FEM_SETMODE,eax,0
        invoke  ShowWindow,[.wnd],SW_SHOW
        jmp     ..not_found








  .wm_initdialog:
        invoke  GetDlgItem,[.wnd],TEXT.MENU.FINDR.TEXT
        stdcall ComboCopyStrings,eax,[hSearchHistory],findr._search_string
        invoke  GetDlgItem,[.wnd],TEXT.MENU.FINDR.NEW
        stdcall ComboCopyStrings,eax,[hSearchHistory],findr._search_string

        invoke  SendMessageA,[hTxt],FEM_GETWORDATCARET,findr.sz_search_string,findr._search_string
        invoke  SetDlgItemTextA,[.wnd],TEXT.MENU.FINDR.TEXT,findr._search_string

        sub     eax,eax
        test    [findr.search_settings],FEFIND_CASESENSITIVE
        setnz   al
        invoke  CheckDlgButton,[.wnd],TEXT.MENU.FINDR.CASE,eax

        sub     eax,eax
        test    [findr.search_settings],FEFIND_INWHOLETEXT
        setnz   al
        invoke  CheckDlgButton,[.wnd],TEXT.MENU.FINDR.WHOLE,eax

        sub     eax,eax
        test    [findr.search_settings],FEFIND_ASKREPLACE
        setnz   al
        invoke  CheckDlgButton,[.wnd],TEXT.MENU.FINDR.ASK,eax

        mov     eax,1
        jmp     .ret








;giant[the]copy-past'a
;authentic author - Tomasz Grysztar, www.FlatAssembler.net
;mind eax,ecx,edx

proc fasm_syntax lpLine,uChars,lpColors
        push    ebx esi edi
        mov     esi,[lpLine]
        mov     edi,[lpColors]
        mov     ebx,characters
        mov     ecx,[uChars]
        xor     edx,edx
  .scan_syntax:
        lodsb
  .check_character:
        cmp     al,20h
        je      .syntax_space
        cmp     al,3Bh
        je      .syntax_comment
        mov     ah,al
        xlatb
        or      al,al
        jz      .syntax_symbol
        or      edx,edx
        jnz     .syntax_neutral
        cmp     ah,27h
        je      .syntax_string
        cmp     ah,22h
        je      .syntax_string
        cmp     ah,24h
        je      .syntax_pascal_hex
        cmp     ah,39h
        ja      .syntax_neutral
        cmp     ah,30h
        jae     .syntax_number
  .syntax_neutral:
        or      edx,-1
        inc     edi
        loop    .scan_syntax
        jmp     .done
  .syntax_space:
        xor     edx,edx
        inc     edi
        loop    .scan_syntax
        jmp     .done
  .syntax_symbol:
        mov     al,1
        stosb
        xor     edx,edx
        loop    .scan_syntax
        jmp     .done
  .syntax_pascal_hex:
        cmp     ecx,1
        je      .syntax_neutral
        mov     al,[esi]
        mov     ah,al
        xlatb
        or      al,al
        jz      .syntax_neutral
        cmp     ah,24h
        jne     .syntax_number
        cmp     ecx,2
        je      .syntax_neutral
        mov     al,[esi+1]
        xlatb
        or      al,al
        jz      .syntax_neutral
  .syntax_number:
        mov     al,2
        stosb
        loop    .number_character
        jmp     .done
  .number_character:
        lodsb
        mov     ah,al
        xlatb
        xchg    al,ah
        or      ah,ah
        jz      .check_character
        cmp     al,20h
        je      .check_character
        cmp     al,3Bh
        je      .check_character
        mov     al,2
        stosb
        loop    .number_character
        jmp     .done
  .syntax_string:
        mov     al,3
        stosb
        dec     ecx
        jz      .done
        lodsb
        cmp     al,ah
        jne     .syntax_string
        mov     al,3
        stosb
        dec     ecx
        jz      .done
        lodsb
        cmp     al,ah
        je      .syntax_string
        xor     edx,edx
        jmp     .check_character
  .process_comment:
        lodsb
        cmp     al,20h
        jne     .syntax_comment
        inc     edi
        loop    .process_comment
        jmp     .done
  .syntax_comment:
        mov     al,4
        stosb
        loop    .process_comment
  .done:
        pop     edi esi ebx
        ret
;fasm orGasm :)
characters:
  .al=0
  while .al<256
    if .al=9 | .al=10 | .al=13 | .al=26 | .al=' ' | .al='+' | .al='-' | .al='/' | .al='*' | .al='=' | .al='<' | .al='>' | .al='(' | .al=')' | .al='[' | .al=']' | .al='{' | .al='}' | .al=':' | .al=',' | .al='|' | .al='&' | .al='~' | .al='#' | .al='`' | .al=';' | .al='\'
      db 0

    else if .al='^' ;we allow x^y expressions so make fedit treat it primitive token too
      db 0

    else if .al>='A' & .al<='Z'
      db .al or ' '
    else
      db .al
    end if
    .al=.al+1
  end while
endp








;routine procs
;mind eax,ecx,edx

cycle_editor_colors:
        mov     eax,[hTxt.editor_colors.?]
        add     eax,sizeof.EDITOR_COLORS
        cmp     eax,editor_colors.
        jne     .apply
        mov     eax,editor_colors
      .apply:
        mov     [hTxt.editor_colors.?],eax

        lea     ecx,[eax+EDITOR_COLORS.symbols]
        push    fasm_syntax                ecx                       FEM_SETSYNTAXHIGHLIGHT [hTxt]
        push    [eax+EDITOR_COLORS.stextb] [eax+EDITOR_COLORS.stext] FEM_SETSELCOLOR        [hTxt]
        push    [eax+EDITOR_COLORS.textb]  [eax+EDITOR_COLORS.text]  FEM_SETTEXTCOLOR       [hTxt]
        invoke  SendMessageA
        invoke  SendMessageA
        invoke  SendMessageA
        ret

get_open_file_name: push edi
        mov     edi,GetOpenFileNameA
        jmp     get_file_name
get_save_file_name: push edi
        mov     edi,GetSaveFileNameA
     get_file_name:
        mov     [ofn.lStructSize],sizeof.OPENFILENAME
        mov     eax,[hWnd]
        mov     [ofn.hwndOwner],eax
        mov     [ofn.lpstrFile],candidate_file_name
        mov     [ofn.nMaxFile],tokens.szFullNameBuf
        mov     [ofn.Flags],OFN_OVERWRITEPROMPT
        stdcall dword[edi],ofn
        cmp     eax,1 ;set flags.cf
        pop     edi
        ret

get_script_from_control:
        invoke  SendMessageA,[hTxt],WM_GETTEXTLENGTH,0,0
        cmp     eax,sz_script-tokens.ScriptTextOf
        jae     .increase_sz_script
        inc     eax
        invoke  SendMessageA,[hTxt],WM_GETTEXT,eax,(_script+tokens.ScriptTextOf)
        clc
        ret
      .increase_sz_script:
        invoke  MessageBoxA,[hWnd],tokens.errOutOfScript,0,0
        stc
        ret

highlight_eax_line_in_text:
          mov [fepos.selectionLine],eax
          mov [fepos.caretLine],eax
          invoke SendMessageA,[hTxt],FEM_GETLINELENGTH,eax,0
          inc eax
          mov [fepos.selectionPosition],eax
          mov [fepos.caretPosition],1
          invoke SendMessageA,[hTxt],FEM_SETPOS,fepos,0
        call    switch_windows.show_txt
        ret

highlight_ebx_token_in_text:
        invoke  FindWindowA,_micro3d,[ebx+token.file_on_disk]
        test    eax,eax
        jnz     .window_exists
    .window_!exists:
      .next_color:
        mov     eax,[hTxt.editor_colors.?]
        add     eax,sizeof.EDITOR_COLORS
        cmp     eax,editor_colors.
        jb      .colors_ok
        mov     eax,editor_colors
      .colors_ok:
        sub     eax,editor_colors
        sub     edx,edx
        mov     ecx,sizeof.EDITOR_COLORS
        div     ecx
        inc     eax
      .show_in_new_window:
        cinvoke printf,printf.buffer,printf.szBuffer,_printf.format_errExe,esp ,[ebx+token.file_on_disk],[ebx+token.line_in_text],eax
        invoke  ShellExecuteA,0,0,exePathName,printf.buffer,exePath,SW_SHOW
        ret
    .window_exists:
        push    0 [ebx+token.line_in_text] FEM_HIGHLIGHTLINE eax
        push    eax
        invoke  SetForegroundWindow
        invoke  SendMessageA
        ret

load_script_from_file:
        bt      [flags],flagTEXT_CHANGED
        jnc     .open
        invoke  MessageBoxA,[hWnd],(_script+tokens.ScriptFileOf),_save_changed?,MB_YESNOCANCEL
        cmp     eax,IDCANCEL
        je      .not_opened
        cmp     eax,IDNO
        je      .open
        call    save_script_to_file
        jc      .not_opened
      .open:
        call    get_open_file_name
        jc      .not_opened
.read:  invoke  CreateFileA,candidate_file_name,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
        cmp     eax,-1
        je      .not_opened_report
        push    eax
        invoke  GetFileSize,eax,esp ,0
        pop                          ecx
        test    ecx,ecx
        jnz     .increase_sz_script
        cmp     eax,sz_script-tokens.ScriptTextOf
        JB      .continue_open ;as there must be place for 0byte-terminator
      .increase_sz_script:
        invoke  CloseHandle
        call    get_script_from_control.increase_sz_script
        jmp     .not_opened
      .continue_open:
        mov     byte[_script+tokens.ScriptTextOf+eax],0
        invoke  ReadFile,dword[esp+4*4],(_script+tokens.ScriptTextOf),eax,ioResult,0
        invoke  CloseHandle
        invoke  SendMessageA,[hTxt],WM_SETTEXT,0,(_script+tokens.ScriptTextOf)
        btr     [flags],flagTEXT_CHANGED
        invoke  SendMessageA,[hSave],WM_SETFONT,[common_font],1
        stdcall memcopy,(_script+tokens.ScriptFileOf),candidate_file_name,tokens.szFullNameBuf
        stdcall Interface.get_full_pathname_lower_padzero,(_script+tokens.ScriptFileOf)
        invoke  SendMessageA,[hWnd],WM_SETTEXT,0,(_script+tokens.ScriptFileOf)
        clc
        jmp     .ret
      .not_opened_report:
        invoke  MessageBoxA,[hWnd],candidate_file_name,tokens.errCannotAccessFile,0
      .not_opened:
        stc
      .ret:
        pushf
        invoke  SetFocus,[hTxt]
        popf
        ret

save_script_to_file:
        push    ebx edi
        mov     edi,_script+tokens.ScriptFileOf
        cmp     byte[edi],0
        jnz     .save
      .save_as:
        call    get_save_file_name
        jc      .not_saved
        mov     edi,candidate_file_name
      .save:
        call    get_script_from_control
        jc      .not_saved
        mov     ebx,eax ;keep number of chars
        invoke  CreateFileA,edi,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
        push    eax
        invoke  WriteFile,eax,(_script+tokens.ScriptTextOf),ebx,ioResult,0
        mov     ebx,eax ;keep result
        invoke  CloseHandle
        test    ebx,ebx
        jz      .not_saved_report
        btr     [flags],flagTEXT_CHANGED
        invoke  SendMessageA,[hSave],WM_SETFONT,[common_font],1
        cmp     edi,candidate_file_name
        jne     .clc_ret
        stdcall memcopy,(_script+tokens.ScriptFileOf),edi,tokens.szFullNameBuf
        ;stdcall Interface.get_full_pathname_lower_padzero,(_script+tokens.ScriptFileOf)
        invoke  SendMessageA,[hWnd],WM_SETTEXT,0,(_script+tokens.ScriptFileOf)
      .clc_ret:
        clc
        jmp     .ret
      .not_saved_report:
        invoke  MessageBoxA,[hWnd],edi,tokens.errCannotAccessFile,0
      .not_saved:
        stc
      .ret:
        pushf
        invoke  SetFocus,[hTxt]
        popf
        pop     edi ebx
        ret

switch_windows:
        invoke  IsWindowVisible,[hCam]
        test    eax,eax
        jnz     .show_txt
      .show_cam:
        invoke  ShowWindow,[hCam],SW_SHOW
        invoke  ShowWindow,[hTxt],SW_HIDE
        ret
      .show_txt:
        invoke  ShowWindow,[hCam],SW_HIDE
        invoke  ShowWindow,[hTxt],SW_SHOW
        invoke  SetFocus,[hTxt]
        ret








;threading the script
;mind eax,ecx,edx

kill_script:   ;gui only
        invoke  TerminateThread,[hScript],0
        call    Interface.SYNC.names.list
        call    Interface.SYNC.unlock_controls
        ret

pause_script:  ;gui & thread, SuspendThread must be last line
        invoke  EnableWindow,[hRun],1
        invoke  EnableWindow,[hPause],0
        call    Interface.SYNC.names.list
        invoke  SuspendThread,[hScript]
        ret

run_script:    ;gui only
        invoke  IsWindowEnabled,[hKill]
        test    eax,eax
        jz      .run_clean
      .run_paused:
        invoke  EnableWindow,[hRun],0
        invoke  EnableWindow,[hPause],1
        invoke  ResumeThread,[hScript]
        ret
      .run_clean:
        call    Interface.SYNC.bmp32.screen.disable ;camera painting OFF
        call    Interface.SYNC.names.disable        ;names access    OFF
        call    Interface.SYNC.lock_controls        ;                OFF
        invoke  CreateThread,0,MB,ThreadFunc,0,0,ioResult
        mov     [hScript],eax
        ret
  ThreadFunc: ;lpParameter:dword

      .wipe_dataseg:
        cld
        mov     eax,0
        mov     edi,dataseg
        mov     ecx,szDataseg  / 4
        rep     stosd
;        mov     cl,szDataseg mod 4
;        rep     stosb

        finit
        mov     [names],0

        call    get_script_from_control ;save_script_to_file
        jc      .tf_exit
        stdcall _1_tokenize_script,_script,sz_script,tokenseg,szTokenseg
        jnc     .tf_1_ok
        cmp     eax,tokens.errOutOfTokenseg
        jne     .tf_errors
        invoke  MessageBoxA,[hWnd],eax,0,0
        jmp     .tf_exit
      .tf_1_ok:

        stdcall _2_surface_ref,tokenseg
        jnc     .tf_2_ok
        cmp     eax,tokens.errNameNotFound
        je      .tf_errors
        cmp     eax,tokens.errNameTooLong
        je      .tf_errors
        cmp     eax,tokens.errSyntax
        je      .tf_errors
        mov     eax,tokens.errNameDuplicate
        jmp     .tf_errors
      .tf_2_ok:
        mov     [names],eax
        call    Interface.SYNC.names.enable

        stdcall _3_surface_if,tokenseg
        jc      .tf_errors
        stdcall _3a_surface_while,tokenseg
        jc      .tf_errors

        stdcall _4_count_d?bytes_writing_label_in_dataseg,tokenseg,szDataseg
        jc      .tf_errors
        stdcall _4a_create_dataseg,tokenseg,dataseg,szDataseg,[names]
        jc      .tf_errors

        stdcall _5_cache_ExprBuf,tokenseg,exprseg,szExprseg
        jc      .tf_errors

        stdcall _6_run_script,tokenseg,dataseg,szDataseg
        jnc     .tf_exit

      .tf_errors:
        cinvoke printf,printf.buffer,printf.szBuffer,_printf.format_errMsg,esp ,eax,[ebx+token.file_on_disk],[ebx+token.line_in_text]
        invoke  MessageBoxA,[hWnd],printf.buffer,0,0
        call    highlight_ebx_token_in_text
      .tf_exit:
        call    Interface.SYNC.names.list
        call    Interface.SYNC.unlock_controls
        invoke  ExitThread,0








;script itself and Interface.procs

include once '../inc/script.inc'








;enu: these are os-specific procs
;     params [mostly] passed via eax,ebx,ecx,edx
;     result returned via eax,ebx,flags.cf
;     anyway, coordinate preserving with the caller


;rus: -. 
;      []   eax,ebx,ecx,edx
;       eax,ebx,flags.cf
;      ,    


Interface:

.bmp32.screen:
        call    .SYNC.bmp32.screen.disable
        mov     [last_bmp32],eax
        call    .SYNC.bmp32.screen.enable
        push    ecx edx
        invoke  RedrawWindow,[hCam],0,0,RDW_INVALIDATE+RDW_INTERNALPAINT+RDW_UPDATENOW
        pop     edx ecx
        ret

.cdA:   push    ecx edx
        invoke  SetCurrentDirectoryA,eax
        push    eax
        invoke  GetCurrentDirectoryA,tokens.szFullNameBuf,ebx
        pop     eax
        pop     edx ecx
        ret

.GetFileSizeA:
        push    ecx edx
        sub     esp,sizeof.WIN32_FIND_DATA shr 2 shl 2 + 100b ;4-align stack
        invoke  FindFirstFileA,eax,esp
        cmp     eax,INVALID_HANDLE_VALUE
        jne     .gfsa.ok
        or      eax,-1
        or      ebx,-1
        jmp     .gfsa.exit
  .gfsa.ok:
        invoke  FindClose,eax
        mov     eax,[esp+WIN32_FIND_DATA.nFileSizeLow]
        mov     ebx,[esp+WIN32_FIND_DATA.nFileSizeHigh]
  .gfsa.exit:
        add     esp,sizeof.WIN32_FIND_DATA shr 2 shl 2 + 100b
        pop     edx ecx
        ret

.GetFullPathNameA:
        push    edx ecx
        invoke  GetFullPathNameA,eax,ecx,ebx,0
        cmp     eax,0
        jz      .gfpna.nok
        cmp     eax,tokens.szFullNameBuf
        jna     .gfpna.ok
  .gfpna.nok:
        or      eax,-1
  .gfpna.ok:
        pop     ecx edx
        ret

.get_full_pathname_lower_padzero:   ;buffer
        push    eax ecx edx edi esi ;wapi,wapi,wapi,buffer,tempBuffer

        mov     edi,[esp+6*4]       ;buffer
        sub     esp,tokens.szFullNameBuf
        mov     esi,esp             ;tempBuffer

        invoke  GetFullPathNameA,edi,tokens.szFullNameBuf,esi,0
        cmp     eax,0
        jz      .gfplp.stc
        cmp     eax,tokens.szFullNameBuf
        ja      .gfplp.stc
        invoke  CharLowerBuffA,esi,eax

        pushf
        cld
        mov     ecx,eax             ;char count
        rep     movsb
        sub     ecx,eax             ;pad = tokens.szFullNameBuf - (0 - char count)
        add     ecx,tokens.szFullNameBuf
        mov     al,0
        rep     stosb
        popf

        clc
        jmp     .gfplp.ret
  .gfplp.stc:
        stc
  .gfplp.ret:
        lea     esp,[esp+tokens.szFullNameBuf]
        pop     esi edi edx ecx eax
        ret     1*4                 ;flags.cf <- 0k

.GetTickCount:
        push    ecx edx
        invoke  GetTickCount
        pop     edx ecx
        ret

.InputBoxA: .msg:
  .InputBoxA.DLG=1
  .InputBoxA.TXT=2
  .InputBoxA.YES=3
        mov     [Interface.InputBoxA.buffer],eax
        mov     [Interface.InputBoxA.szBuffer],ebx
        invoke  DialogBoxParamA,[wc.hInstance],.InputBoxA.DLG,[hWnd],.InputBoxA.DialogProc,0
        ret
  .InputBoxA.DialogProc: ;wnd,msg,wparam,lparam
        push    ebp
        mov     ebp,esp
    .InputBoxA.lparam label dword at ebp+5*4
    .InputBoxA.wparam label dword at ebp+4*4
    .InputBoxA.msg    label dword at ebp+3*4
    .InputBoxA.wnd    label dword at ebp+2*4
        mov     eax,[.InputBoxA.msg]
        cmp     eax,WM_CLOSE
        je      .InputBoxA.wm_close
        cmp     eax,WM_COMMAND
        je      .InputBoxA.wm_command
        cmp     eax,WM_INITDIALOG
        je      .InputBoxA.wm_initdialog
    .InputBoxA.retz:
        sub     eax,eax
    .InputBoxA.ret:
        mov     esp,ebp
        pop     ebp
        ret     4*4
    .InputBoxA.wm_close:
        invoke  EndDialog,[.InputBoxA.wnd],0
        jmp     .InputBoxA.retz
    .InputBoxA.wm_command:
        mov     eax,[.InputBoxA.wparam]
        cmp     eax,BN_CLICKED shl 16 + .InputBoxA.YES
        jne     .InputBoxA.retz
        invoke  SendDlgItemMessageA,[.InputBoxA.wnd],.InputBoxA.TXT,WM_GETTEXT,[Interface.InputBoxA.szBuffer],[Interface.InputBoxA.buffer]
        invoke  EndDialog,[.InputBoxA.wnd],eax
        jmp     .InputBoxA.retz
    .InputBoxA.wm_initdialog:
;        invoke  SendDlgItemMessageA,[.InputBoxA.wnd],.InputBoxA.TXT,FEM_SETTEXTCOLOR,[editor_colors+EDITOR_COLORS.text],[editor_colors+EDITOR_COLORS.textb]
;        invoke  SendDlgItemMessageA,[.InputBoxA.wnd],.InputBoxA.TXT,FEM_SETSELCOLOR,[editor_colors+EDITOR_COLORS.stext],[editor_colors+EDITOR_COLORS.stextb]
;        invoke  SendDlgItemMessageA,[.InputBoxA.wnd],.InputBoxA.TXT,FEM_SETSYNTAXHIGHLIGHT,(editor_colors+EDITOR_COLORS.symbols),fasm_syntax
        invoke  SendDlgItemMessageA,[.InputBoxA.wnd],.InputBoxA.TXT,WM_SETTEXT,0,[Interface.InputBoxA.buffer]
        jmp     .InputBoxA.retz

.MessageBoxA:
        push    ecx edx
        invoke  MessageBoxA,[hWnd],eax,ebx,ecx
        pop     edx ecx
        ret

.pause: call    highlight_ebx_token_in_text
        call    pause_script
        ret

.printfA:
        push    ecx edx
        cinvoke printf,eax,ebx,ecx,edx
        pop     edx ecx
        ret

.ReadFileA:
        push    [ReadFile]
        jmp     .rwfa.r
.WriteFileA:
        push    [WriteFile]
  .rwfa.r:
        push    INVALID_HANDLE_VALUE ebx ecx edx ebp ;to be result, to be file id, altered by win api, also, params ptr
        mov     ebp,esp
  .rwfa.count     label dword at ebp+4*11
  .rwfa.offset.hi label dword at ebp+4*10
  .rwfa.offset.lo label dword at ebp+4*09
  .rwfa.file      label dword at ebp+4*08
  .rwfa.buffer    label dword at ebp+4*07

  .rwfa.rw        label dword at ebp+4*05
  .rwfa.popeax    label dword at ebp+4*04

        invoke  CreateFileA,[.rwfa.file],GENERIC_READ+GENERIC_WRITE,0,0,OPEN_ALWAYS,0,0
        cmp     eax,INVALID_HANDLE_VALUE
        je      .rwfa.exit
        mov     ebx,eax

        lea     eax,[.rwfa.offset.hi]
        invoke  SetFilePointer,ebx,[.rwfa.offset.lo],eax,FILE_BEGIN

        lea     eax,[.rwfa.popeax]
        stdcall [.rwfa.rw],ebx,[.rwfa.buffer],[.rwfa.count],eax,0

        invoke  CloseHandle,ebx
  .rwfa.exit:
        pop     ebp edx ecx ebx eax
        add     esp,4
        ret     4*5

;0|title -> eax <- FALSE0|TRUE1
;buffer <-> ebx
.SelectDirA:
        push    ecx edx                               ;1=dirs
        invoke  SHBrowseForFolderA,esp, [hWnd],0,0,eax,1,0,0,0
        invoke  SHGetPathFromIDListA,eax,ebx
        add     esp,sizeof.BROWSEINFO
        pop     edx ecx
        ret

;0|title -> eax <- FALSE0|TRUE1
;buffer <-> ebx
.SelectFileA:
        push   ecx edx
        invoke GetOpenFileNameA,esp, sizeof.OPENFILENAME,[hWnd],0,0,0,0,0,ebx,tokens.szFullNameBuf,0,0,0,eax,OFN_OVERWRITEPROMPT,0,0,0,0,0
        add    esp,sizeof.OPENFILENAME
        pop    edx ecx
        ret

;flags.cf <- 0k
.set_cur_dir: ;dir
        push    eax ecx edx
.scd.dir label dword at esp+4*4
        invoke  SetCurrentDirectoryA,[.scd.dir]
        sub     eax,1 ;set flags.cf
        pop     edx ecx eax
        ret     1*4

.SetEndOfFileA:
        push    edx ecx ebx ebp
        mov     ebp,esp
  .seofa.eof.hi label dword at ebp+4*7
  .seofa.eof.lo label dword at ebp+4*6
  .seofa.fl     label dword at ebp+4*5
        invoke  CreateFileA,[.seofa.fl],GENERIC_WRITE,0,0,OPEN_ALWAYS,0,0
        mov     ebx,eax
        lea     eax,[.seofa.eof.hi]
        invoke  SetFilePointer,ebx,[.seofa.eof.lo],eax,FILE_BEGIN
        invoke  SetEndOfFile,ebx
        push    eax
        invoke  CloseHandle,ebx
        pop     eax
        pop     ebp ebx ecx edx
        ret     4*3

.sleep: push    ecx edx
        invoke  Sleep,eax
        pop     edx ecx
        ret

.SYNC.bmp32.screen.disable: .DrawOff:
        push    edx ecx eax
        invoke  SendMessageA,[hWnd],SYNC.BMP32.SCREEN.DISABLE,0,0
        pop     eax ecx edx
        ret
.SYNC.bmp32.screen.enable:  .DrawOn:
        push    edx ecx eax
        invoke  SendMessageA,[hWnd],SYNC.BMP32.SCREEN.ENABLE,0,0
        pop     eax ecx edx
        ret

.SYNC.lock_controls: ;internal, donot use in psedocode
        push    edx ecx eax
        invoke  SendMessage,[hWnd],SYNC.LOCK_CONTROLS,0,0
        pop     eax ecx edx
        ret
.SYNC.unlock_controls: ;internal, donot use in psedocode
        push    edx ecx eax
        invoke  SendMessage,[hWnd],SYNC.UNLOCK_CONTROLS,0,0
        pop     eax ecx edx
        ret

.SYNC.names.disable: ;internal, donot use in psedocode
        push    edx ecx eax
        invoke  SendMessageA,[hWnd],SYNC.NAMES.DISABLE,0,0
        pop     eax ecx edx
        ret
.SYNC.names.enable: ;internal, donot use in psedocode
        push    edx ecx eax
        invoke  SendMessageA,[hWnd],SYNC.NAMES.ENABLE,0,0
        pop     eax ecx edx
        ret
.SYNC.names.list: ;internal, donot use in psedocode
        push    edx ecx eax
        invoke  SendMessageA,[hWnd],SYNC.NAMES.LIST,0,0
        pop     eax ecx edx
        ret

.time:  push    ecx edx
        sub     esp,sizeof.SYSTEMTIME shr 2 shl 2 + 100b ;4-align stack
        invoke  GetLocalTime,esp
        movzx   eax,word[esp+ebx]
        add     esp,sizeof.SYSTEMTIME shr 2 shl 2 + 100b
        pop     edx ecx
        ret
  .time.year:
        mov     ebx,SYSTEMTIME.wYear
        jmp     .time
  .time.month:
        mov     ebx,SYSTEMTIME.wMonth
        jmp     .time
  .time.DayOfWeek:
        mov     ebx,SYSTEMTIME.wDayOfWeek
        jmp     .time
  .time.day:
        mov     ebx,SYSTEMTIME.wDay
        jmp     .time
  .time.hour:
        mov     ebx,SYSTEMTIME.wHour
        jmp     .time
  .time.minute:
        mov     ebx,SYSTEMTIME.wMinute
        jmp     .time
  .time.second:
        mov     ebx,SYSTEMTIME.wSecond
        jmp     .time
  .time.millisecond:
        mov     ebx,SYSTEMTIME.wMilliseconds
        jmp     .time
