| Index | Manual | Download | Source | Macros | Embedded word Case ins.
Sitemap | Links | Forum | Tests | Projects

# calcwing.htm
Data
Data
Procedures
MsgLoopMain
WndCreateMain
WndProcMain

This is a GUI module of EuroTool program EuroCalc for Windows.

             EUROASM CPU=X64,SIMD=Yes,Unicode=No
    calcwing PROGRAM Format=COFF,Width=64
               %DROPMACRO *
               INCLUDEHEAD argument.htm
               INCLUDE1 winansi.htm,fastcall.htm,winabi.htm,winsgui.htm,winsdlg.htm
               INCLUDE1 cpuext.htm,memory64.htm,string64.htm,status32.htm
               LINK ../objlib/winapi.lib

↑ Data

                                 ; Constants.
    xBtn  EQU  4                 ; Left  position of buttons array.
    yBtn  EQU 120                ; Upper position of buttons array.
    wiBtn EQU  70                ; Width of one button.
    heBtn EQU  30                ; Height of one button.
    [.rodata]                    ; Constant data.
    TitleWindow   DB "EuroCalc",0
    [.bss]                       ; Variable data.
    Msg           DS MSG
    WndClassEx    DS WNDCLASSEX
    PaintStruct   DS PAINTSTRUCT
    hWindowMain   D QWORD
    hWindowStatus D QWORD
    hDC           D QWORD
    hFont         D QWORD
    hBrushGrayBg  D QWORD
    hBrushWhiteBg D QWORD
    InpBufferPtr  D QWORD        ; Pointer
    LineSize      D DWORD        ; Max. number of characters in the input line and in the result line, depending on MainWidth.
    AveCharWidth  D DWORD        ; Average character width in pixels.
    [.text]

MsgLoopMain
  Message handling procedure. Entry point of GUI.
Called by
  MainCon.
Calls
  WndCreateMain,

    MsgLoopMain:: PROC
         CALL WndCreateMain
         WinABI ShowWindow,[hWindowMain],SW_SHOW
         WinABI UpdateWindow,[hWindowMain]
    .MsgLoop:
         WinABI GetMessage, Msg,0,0,0
         TEST RAX
         JZ .MsgQuit:                                 ; ZF signalizes message WM_QUIT - request for termination.
         WinABI TranslateMessage, Msg                 ; Remap character keys from national keyboards.
         WinABI DispatchMessage,  Msg                 ; Let Windows call our WndProc.
         JMP .MsgLoop:                                ; Wait for another message.
    .MsgQuit:
         TerminateProgram
       ENDP MsgLoopMain

WndCreateMain
  Register window class and create windows for displaying the output listing.

    WndCreateMain:: PROC     ; Register WndClassEx for the main window.
        MOVD [WndClassEx.cbSize],SIZE# WndClassEx
        MOVQ [WndClassEx.lpszClassName],TitleWindow
        MOVD [WndClassEx.style],CS_HREDRAW|CS_VREDRAW
        MOVQ [WndClassEx.lpfnWndProc],WndProcMain
        WinABI GetModuleHandle,0
        MOVQ [WndClassEx.hInstance],RAX
        WinABI LoadIcon,RAX,1             ; The 1st and only icon from [.rsrc] section.
        MOVQ [WndClassEx.hIcon],RAX
        WinABI LoadCursor,0,IDC_IBEAM
        MOVQ [WndClassEx.hCursor],RAX
        MOVQ [WndClassEx.hbrBackground],15+1 ; COLOR_BTNFACE+1
        WinABI RegisterClassExA, WndClassEx
        ; Create the main window.
        WinABI CreateWindowExA,0,       \
               TitleWindow,TitleWindow::,WS_OVERLAPPEDWINDOW, \
               CW_USEDEFAULT,CW_USEDEFAULT,6*(wiBtn+4)+20,7*(heBtn+4)+170,   \
               0, 0, [WndClassEx.hInstance], 0
        MOV [hWindowMain],RAX
        ;  Create other children windows of the main window.
        ; EuroCalc icon.
        WinABI CreateWindowExA,0,="STATIC",="#1",WS_CHILD+WS_VISIBLE+SS_ICON,\
               12,1,16,16,[hWindowMain],0,[WndClassEx.hInstance],0
        WinABI SendMessage,RAX,STM_SETICON,[WndClassEx.hIcon],0
       ; Title EuroCalc version.
        WinABI CreateWindowExA,0,="STATIC", Version::, WS_CHILD+WS_VISIBLE   +SS_SIMPLE, \
                50,10,280,20,[hWindowMain],0,[WndClassEx.hInstance],0
        ; Status window.
        WinABI CreateWindowExA,0,=B'STATIC',=B"", WS_CHILD+WS_VISIBLE+SS_CENTER, \
               4,92,6*(wiBtn+4)-2,24,[hWindowMain],0,[WndClassEx.hInstance],0
        MOV [hWindowStatus],RAX
        ; Set the unproportional font of digits.
        MOV ECX,8
        MOV [AveCharWidth],ECX
        WinABI CreateFont, 24, RCX, 0,0,FW_BOLD,0,0,0, ANSI_CHARSET,0,0,0,FIXED_PITCH|FF_MODERN,=B"Courier New"
        MOV [hFont],RAX
        WinABI SendMessage,[hWindowMain],WM_SETFONT,RAX,1
        ; Edit window width in pixels.
        MOV EAX,6*(wiBtn+4)-2
        XOR EDX,EDX
        MOV ECX,[AveCharWidth]
        DIV ECX
        MOV [LineSize],EAX
        MOV AL,' '
        LEA RDI,[InpBuffer::]
        MOV [InpBufferPtr],RDI
        MOV ECX,640
        REP STOSB
        LEA RDI,[OutBuffer::]
        MOV ECX,640
        REP STOSB
        WinABI CreateSolidBrush,0x00F0F0F0
        MOV [hBrushGrayBg],RAX
        WinABI CreateSolidBrush,0x00FFFFFF
        MOV [hBrushWhiteBg],RAX
        WinABI CreateCaret,[hWindowMain],0,10,3
        ; Array of 6 columns and 7 rows of buttons.
        LEA RDI,[TitleBtns::]
        MOV R14,0x6001            ; Here start WM_USER defined message numbers.
        MOV R13,yBtn
    .20:MOV R12,xBtn
    .30:CMP R13,yBtn+7*heBtn+7*4
        JAE .90:
        CMP R12,xBtn+ 6*wiBtn+6*4
        JAE .40:
        LEA RCX,[TitleBtnsEnd::]
        LEA RAX,[TitleBtns::]
        SUB RCX,RAX
        XOR EAX,EAX
        REPNE SCASB
    WinABI CreateWindowExA,0,=B'BUTTON',RDI, \
              BS_PUSHBUTTON+WS_CHILD+WS_VISIBLE+WS_TABSTOP, \
              R12,R13,wiBtn,heBtn, \
              [hWindowMain],R14,[WndClassEx.hInstance],0
        INC R14
        ADD R12,wiBtn+4
        JMP .30:
    .40:ADD R13,heBtn+4
        JMP .20:
    .90:RET
       ENDP WndCreateMain

WndProcMain, hWnd, uMsg, wParam, lParam

  This is a callback procedure which receives and handles messages for the MainWindow. Message parameters are by FastCall convention provided in registers RCX, RDX, R8, R9, we'll save them to shadow space with macro SaveToShadow . Thanks to this their contents will be available by formal names ( `[%hWnd], [%uMsg], [%wParam], [%lParam]`), too, in the entire WndProc body.

  Messages obtained from Windows are dispatched by WndProcMain to their handlers.
  Unhandled messages are passed to DefWindowProc.

Handler input
  RCX=[%hWnd] is the main window handle (the same as static [hWindowMain]).
  RDX=[%uMsg] is message identifier,
  R8=[%wParam] is message w-parameter,
  R9=[%lParam] is message l-parameter.
Handler output
  RAX=0 if the message was completely processed by the handler. Otherwise the message is processed by WinAPI DefWindowProc and RAX outputs its return value.
  Scratch registers RCX,RDX,R8..R11 may be destroyed in the handlers.
  Callee-save registers RBX,RSI,RDI,R12..R15 must be restored, if used in the handlers. This provides macro Uses.
Invoked by
  WinAPI DispatchMessage.

    WndProcMain Procedure hWnd, uMsg, wParam, lParam ; These parameters are provided in RCX,RDX,R8,R9.
        Uses RBX,RBP,RSI,RDI
        SaveToShadow
        ; Fork message uMsg=RAX to its handler using macro Dispatch:
         Dispatch EDX , WM_CHAR, WM_PAINT, WM_CTLCOLORSTATIC, WM_KEYDOWN, WM_SIZE, WM_COMMAND, \
                  WM_SETFOCUS, WM_KILLFOCUS, WM_LBUTTONUP, WM_DESTROY
    .Def:WinABI DefWindowProc,[%hWnd],[%uMsg],[%wParam],[%lParam]  ; Pass ignored event to DefWindowProc with unchanged arguments.
         JMP .Ret:     ; Go to EndProcedure with result value RAX as returned from DefWindowProc.
         ; All message handlers terminate with a jump to the label .Def: or .Ret0:.
    .WM_SIZE:
         MOVZX EDI,R9W                    ; Recalculate the new width of the window in pixels.
         SUB EDI,7
         MOV EAX,EDI
         XOR EDX,EDX
         DIVD [AveCharWidth]
         MOV [LineSize],EAX
         JMP .Ret0:
    .WM_CTLCOLORSTATIC:
         CMP R9,[hWindowStatus]
         JNE .Def:
         WinABI SetBkMode, R8, TRANSPARENT
         WinABI SetTextColor, R8, 0x000000C0  ; Red ink.
         MOV RAX,[hBrushGrayBg]
         JMP .Ret:
    .WM_SETFOCUS:
         WinABI ShowCaret,[hWindowMain]
         JMP .Ret0:
    .WM_KILLFOCUS:
         WinABI HideCaret,[hWindowMain]
         JMP .Ret0:
    .WM_LBUTTONUP:                         ; Mouse clicked.
         MOVZX EAX,R9W                     ; X-position in pixels.
         SHR R9,16                         ; Y-position in pixels.
         CMP R9W,28
         JB .Def:
         CMP R9W,50
         JA .10:
         ADD EAX,4                         ; Clicked at the input line. Move caret.
         MOV ECX,[AveCharWidth]
         XOR EDX,EDX
         DIV RCX
         LEA RSI,[InpBuffer::]
         ADD RAX,RSI
         MOV [InpBufferPtr],RAX
         JMP .10:
    .WM_PAINT:                              ; Draw input and output line.
         LEA RSI,[PaintStruct]
         WinABI BeginPaint,[hWindowMain], RSI
         MOV [hDC],RAX
         WinABI SelectObject,[hDC],[hFont]
         WinABI SetTextColor, [hDC], 0x00000000   ; Black ink.
         LEA RSI,[InpBuffer::]
         MOV RDI,[InpBufferPtr]
         SUB RDI,RSI
         MOV EAX,[AveCharWidth]
         MUL RDI
         ADD RAX,4
         WinABI SetCaretPos,RAX,52
         MOV ECX,[LineSize]
         WinABI TextOut,[hDC],4,34,RSI,RCX
         WinABI SetTextColor, [hDC], 0x00008000   ; Green ink.
         LEA RSI,[OutBuffer::]
         MOV ECX,[LineSize]
         WinABI TextOut,[hDC],4,56,RSI,RCX
         LEA RSI,[PaintStruct]
         WinABI EndPaint,[hWindowMain],RSI
         JMP .Ret0:
    .WM_CHAR:
         MOV RAX,R8
         Dispatch AL,0x08,0x0D,0x3D,0x1B   ; Backspace, Enter, =, Esc.
         LEA RSI,[InpBuffer::]             ; Otherwise AL is an ordinary character.
         MOV ECX,[LineSize]
         LEA RDI,[RSI+RCX-1]
         LEA RSI,[RDI-1]
         MOV RCX,RDI
         SUB RCX,[InpBufferPtr]
         JLE .Ret0:
         STD
           REP MOVSB                       ; Move characters at cursor one position right.
         CLD
         STOSB                             ; Store the new character.
         MOV [InpBufferPtr],RDI
         JNSt [Status::],ArgCalculated,.10:
         RstSt [Status::],ArgCalculated
         LEA RDI,[OutBuffer::]
         MOV ECX,[LineSize]
         MOV AL,' '
         REP STOSB                         ; Erase the old output line if ArgCalculated.
    .10: ; Common termination.
         WinABI InvalidateRect,[hWindowMain],0,1
         WinABI UpdateWindow,[hWindowMain]
         WinABI SetFocus,[hWindowMain]
         JMP .Ret0:
    .0n2:                                  ; Button #2 [ Bs ].
    .0x08:MOV EAX,[LineSize]               ; Key Backspace.
          LEA RSI,[InpBuffer::]
          MOV RDI,[InpBufferPtr]
          CMP RDI,RSI
          JNA .Ret0:
          LEA RCX,[RSI+RAX-1]
          DEC RDI
          SUB RCX,RSI
          MOV [InpBufferPtr],RDI
          LEA RSI,[RDI+1]
          REP MOVSB
          JMP .10:
    .WM_KEYDOWN:                           ; Noncharacter key was pressed.
          MOV AX,R8W
          Dispatch AX,VK_LEFT,VK_RIGHT,VK_HOME,VK_END,VK_DELETE,VK_ESCAPE
          JMP .Def:
    .VK_LEFT:                              ; Move caret left.
          MOV RDI,[InpBufferPtr]
          LEA RSI,[InpBuffer::]
          CMP RDI,RSI
          JNA .Ret0:
          DEC RDI
          MOV [InpBufferPtr],RDI
          JMP .10:
    .VK_RIGHT:                             ; Move caret right.
         MOV RDI,[InpBufferPtr]
         LEA RSI,[InpBuffer::]
         MOV ECX,[LineSize]
         LEA RCX,[RSI+RCX-2]
         CMP RDI,RCX
         JNB .Ret0:
         INC RDI
         MOV [InpBufferPtr],RDI
         JMP .10:
    .VK_END:                               ; Move caret at the end of the input.
         LEA RDI,[InpBuffer::]
         MOV ECX,[LineSize]
         LEA RDI,[RDI+RCX-1]
         MOV RSI,RDI
         MOV AL,' '
         STD
           REPE SCASB
         CLD
         ADD RDI,2
         CMP RDI,RSI
         JBE .20:
         DEC RDI
    .20: MOV [InpBufferPtr],RDI
         JMP .10:
    .VK_HOME:                              ; Move caret at the beginning.
         LEA RSI,[InpBuffer::]
         MOV [InpBufferPtr],RSI
         JMP .10:
    .VK_DELETE:                            ; Erase the character below caret.
         LEA RSI,[InpBuffer::]
         MOV ECX,[LineSize]
         ADD RCX,RSI
         MOV RDI,[InpBufferPtr]
         LEA RSI,[RDI+1]
         SUB RCX,RSI
         REP MOVSB
         JMP .10:
    .WM_COMMAND:                           ; Clicked somewhere int the main window.
         MOVZX EDX,R8B                     ; Button ordinal.
         CMP EDX,6*7
         JA .Def:
         Dispatch DL,0n1,0n2,0n42          ; DL=1..42 ordinal number of the clicked button.
         LEA RDI,[TitleBtns::]             ; Defined in calcmain.htm.
         LEA RCX,[TitleBtnsEnd::]
         LEA RAX,[TitleBtns::]
         SUB RCX,RAX
         XOR EAX,EAX
    .30: REPNE SCASB
         DEC DL
         JNZ .30:
         MOV RSI,RDI                       ; Pointer at the button title.
         MOV ECX,[LineSize]
         LEA RBX,[InpBuffer::]
         ADD RBX,RSI
    .35: MOV RDI,[InpBufferPtr]
         CMP RSI,RBX
         JNB .10:
         LODSB
         CMP AL,0
         JE .10:
         STOSB                             ; Store characters form the title to InpBuffer.
         MOV [InpBufferPtr],RDI
         JMP .35:
    .0n1:                                  ; Button #1 [ Clr ].
         WinABI SetWindowText,[hWindowStatus],=B""  ; Erase status.
         LEA RDI,[InpBuffer::]
         MOV RBX,RDI
         MOV [InpBufferPtr],RDI
         MOV ECX,640
         MOV AL,' '
         REP STOSB                         ; Erase InpBuffer.
         LEA RDI,[OutBuffer::]
         MOV ECX,640
         REP STOSB                         ; Erase OutBuffer.
         JMP .10:
    .0n42:                                 ; Button #42 [ = ].
    .0x0D:                                 ; Key Enter.
    .0x3D:                                ; Key =.
         ; Perform the calculation. Uses functions included from calcmain.htm.
         WinABI SetWindowText,[hWindowStatus],=B""
         LEA RSI,[InpBuffer::]
         MOV RCX,[InpBufferPtr]
         SUB RCX,RSI
         JZ .0n1:
    .40: LODSB
         CMP AL,' '
         JA .50:
         LOOP .40:
         JMP .0n1:
    .50: MOV RDI,[InpBufferPtr]
         MOV AL,'='
         STOSB
         LEA RSI,[InpBuffer::]
         MOV ECX,[LineSize]
         LEA RCX,[RSI+RCX-1]
         SUB RCX,RDI
         JLE .10:
         MOV AL,' '
         REP STOSB
         LEA RSI,[InpBuffer::]
         LEA RDI,[Pbuffer::]
         CALL Parse::                      ; Parse the ASCIIZ string at RSI.
         MOV [PbufferEnd::],RDI            ; Store numbers, parenthesis and functions to RDI=Pbuffer.
         JNC .60:
         WinABI SetWindowText,[hWindowStatus],=B"Syntax error."
         JMP .10:
    .60: LEA RSI,[Pbuffer::]
         MOV RDX,[PbufferEnd::]
         LEA RDI,[InpBuffer::]
         MOV [InpBufferPtr],RDI
         CALL EchoExpression::
         LEA RDI,[InpBuffer::]
         MOV ECX,[LineSize]
         MOV AL,'='
         REPNE SCASB
         MOV AL,' '
         REP STOSB
         LEA RSI,[Pbuffer::]
         MOV RDX,[PbufferEnd::]
         LEA RDI,[Nbuffer::]
         CALL Deparent::                   ; Remove N-records for parenthesis.
         MOV [NbufferEnd::],RDI
         JNC .70:
         WinABI SetWindowText,[hWindowStatus],=B"Unbalanced parenthesis."
         JMP .10:
    .70: CALL Calculate::
         JNC .80:
         WinABI SetWindowText,[hWindowStatus],=B"Error in expression or division by 0."
         JMP .10:
    .80: CALL DisplayDecimalProxy::        ; Put the output string to OutBuffer.
         SetSt [Status::],ArgCalculated    ; This trigger tells to erase OutBuffer on new input.
         LEA RDI,[OutBuffer::]
         XOR EAX,EAX
         MOV ECX,[LineSize]
         REPNE SCASB
         DEC RDI
         MOV AL,' '
         REP STOSB
         JMP .10:
    .0x1B:                                 ; Key Esc.
    .VK_ESCAPE:
    .WM_DESTROY:                           ; Program terminates.
         WinABI DestroyCaret
         WinABI DeleteObject,[hFont]
         WinABI ShowWindow,[hWindowMain],SW_HIDE
         WinABI PostQuitMessage,0          ; Tell Windows to quit this program with errorlevel 0.
    .Ret0:XOR EAX,EAX                      ; RAX=0 signalizes that the message was processed here.
    .Ret:EndProcedure WndProcMain

      ENDPROGRAM calcwing

▲Back to the top▲