;EasyCodeName=EasyCalc,1
Title	EasyCalc
; ___________________________________________________
;|                                                   |
;| GeneSys Calculator v1.0             Gene Brennick |
;| pbrennick@easycoder.org  http://www.pbrennick.com |
;|___________________________________________________|
;|                                                   |
;| A neat little calculator thingee that is a nice   |
;| tool for programmers and data gatherers.  There   |
;| are no bells and whistles as of yet but I will be |
;| combining this program with my Timer Utility and  |
;| some other things that are still in the dream     |
;| stage.  Certainly, the sum of the whole will be   |
;| greater than its parts...soon! A lot of thanks go |
;| out to Ewayne Wagner for all his help and also    |
;| for portions of the code.          Editor's note. |
;|___________________________________________________|
;|                                                   |
;
; Macros
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MOVmd   Macro Var1, Var2
        Push    Var2
        Pop     Var1
        EndM
;
.Const
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IDI_ICON1       Equ 101
IDR_MENU1       Equ 102
IDB_BUT07       Equ 207
IDB_BUT08       Equ 208
IDB_BUT09       Equ 209
IDB_BUTADD      Equ 218
IDB_BUTSQ       Equ 223
IDB_BUT04       Equ 204
IDB_BUT05       Equ 205
IDB_BUT06       Equ 206
IDB_BUTSUB      Equ 219
IDB_BUTPCT      Equ 224
IDB_BUT01       Equ 201
IDB_BUT02       Equ 202
IDB_BUT03       Equ 203
IDB_BUTMUL      Equ 220
IDB_BUTPOW      Equ 225
IDB_BUT00       Equ 200
IDB_BUTPER      Equ 216
IDB_BUTEQ       Equ 222
IDB_BUTDIV      Equ 221
IDB_BUTPM       Equ 217
IDB_BUTA        Equ 210
IDB_BUTB        Equ 211
IDB_BUTC        Equ 212
IDB_BUTD        Equ 213
IDB_BUTE        Equ 214
IDB_BUTF        Equ 215
IDB_BUTMC       Equ 226
IDB_BUTMR       Equ 227
IDB_BUTMS       Equ 228
IDB_BUTMP       Equ 229
IDB_BUTMM       Equ 230
IDB_BUTHYP      Equ 231
IDB_BUTREC      Equ 232
IDB_BUTXN       Equ 233
IDB_BUTPI       Equ 234
IDB_BUTSIN      Equ 235
IDB_BUTCOS      Equ 236
IDB_BUTTAN      Equ 237
IDB_BUTCSC      Equ 238
IDB_BUTSEC      Equ 239
IDB_BUTCOT      Equ 240
IDB_BUTLOG      Equ 241
IDB_BUT2X       Equ 242
IDB_BUT10X      Equ 243
IDB_BUTEX       Equ 244
B1              Equ 500
IDD_INFO        Equ 1999
IDD_ABOUT       Equ 2000
IDD_CALC        Equ 2102
IDM_CLOSE       Equ 6003
IDM_CUT         Equ 6004
IDM_COPY        Equ 6005
IDM_PASTE       Equ 6006
IDM_INFO        Equ 6026
IDM_ABOUT       Equ 6027
IDT_TOOLBAR1    Equ 301
IDT_TOOLBAR2    Equ 302
IDT_TOOLBAR3    Equ 303
IDT_TOOLBAR4    Equ 304
IDT_TOOLBAR5    Equ 305
IDC_URL         Equ 9
IDC_EXIT        Equ 3002
;
.Data
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FontName        DB  'Courier New', 0
FontName1       DB  'Times New Roman', 0
FmtA            DB  '%lu', 0                ; Output as ascii string
FmtH            DB  '%lX', 0                ; Output as hex UC
PLBuff          DB  50 Dup (?), 0
PRBuff          DB  50 Dup (?), 0
HLBuff          DB  50 Dup (?), 0
HRBuff          DB  50 Dup (?), 0
LBuff           DB  50 Dup (?), 0
RBuff           DB  50 Dup (?), 0
ConvH           DB  120 Dup (?), 0
ConvI           DB  120 Dup (?), 0
ConvO           DB  120 Dup (?), 0
Buffer          DB  120 Dup (?), 0
Clear           DB  50 Dup (' '), 0
Zeros           DB  64 Dup ('0'), 0
AppName         DB  '  GeneSys '               ; Do not separate this line from the next
class           DB  'Calculator', 0
ErrorMsg        DB  '** The output is out of range **            ', 0
szPaste         DB  'Your Paste Selection Is Out Of'
                DB  0DH, 0AH
                DB  'Range For The Base Setting!', 0
szTB            DB  ' Calculator v1.0', 0
Info            DB  38 Dup (' ')
                DB  'Most of the functions are self explanatory.'
                DB  0DH, 0AH, 0DH, 0AH
                DB  'There Are Three Two Step Functions.'
                DB  0DH, 0AH
                DB  '(1). X**n  Enter the base number click the X**n button enter the exponent click =.'
                DB  0DH, 0AH
                DB  '(2). HYP  Enter the X number click the HYP button enter the Y number click =.'
                DB  0DH, 0AH
                DB  '(3). %  Enter the first number click the X button enter the second number click %.'
                DB  0DH, 0AH
                DB  'Or Enter the first number click the +,-,x or div button enter the % number click % click =.', 0
EditPT          DB  'EDIT', 0
Butt            DB  'BUTTON', 0
Stat            DB  'STATIC', 0
float           DB  'Floating Point', 0
szArc           DB  'Arc', 0
BackS           DB  'Back Space', 0
CE              DB  'CE', 0
CLR             DB  'C', 0
DegT            DB  'Deg', 0
                DB  'Rad', 0
                DB  'Dec', 0
                DB  'Hex', 0
                DB  'Oct', 0
                DB  'Bin', 0
Pi              DB  '3.141592653589793238', 0
Period          DB  '.', 0
Zero            DB  '0', 0
One             DB  '1', 0
M               DB  'M', 0
                DB  '-', 0
PO              DB  '+', 0
SO              DB  '-', 0
MO              DB  'x', 0
DO              DB  '/', 0
EO              DB  '=', 0
Work            DD  0
                Word    10
CWRound         Word    037FH
CWNoRound       Word    0F7FH
RNum10          Real10  ?
RWrk10          Real10  ?
RMem10          Real10  ?
RDeg10          Real10  0.01745329252
RRad10          Real10  57.2957795130
                Real10  ?
QW              DQ  0
; DWORDS
;  1 - 4 Integers
;  5 - 8 Decimals
;  9 = Number of integers
; 10 = Number of decimals
; 11 = Number of leading zeroes
; 12 = Minus
A               DD  0, 0, 0, 0, 0, 0, 0, 0
B               DD  0, 0, 0, 0, 0, 0, 0, 0
D               DD  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
R               DD  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                DD  0, 0, 0, 0
R2              DD  0, 0, 0, 0
R3              DD  0, 0, 0, 0
R4              DD  0, 0, 0, 0, 0, 0, 0, 0
R5              DD  0, 0, 0, 0, 0, 0, 0, 0, 0, 0
PT              DD  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
MEM             DD  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Sav             DD  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
RH              DD  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
BackGC          DD  00B1987CH
hInst           DD  0
hWndMain        DD  0
hMenu           DD  0
hAccel          DD  0
hFont           DD  0
hDspF           DD  0
CommandLine     DD  0
hEdit           DD  0
hFloat          DD  0
hArc            DD  0
hMem            DD  0
hBkSp           DD  0
hOpr            DD  0
hCE             DD  0
hCLR            DD  0
hDeg            DD  0
hRad            DD  0
hDec            DD  0
hTB01           DD  0
				DD  0
				DD  0
SubEdit         DD  0
SubTool         DD  0
sedi            DD  0
sesi            DD  0
				DD  0
First           DD  0
sw1             DD  0
sw2             DD  0
sw3             DD  0
Min             DD  0
Key             DD  0
HPress          DD  0
NPress          DD  0
RPress          DD  0
BPress          DD  0
Branch          DD  0
Len             DD  0
HLen            DD  0
w1              DD  0
w2              DD  0
XP              DD  0
YP              DD  0
cnt             DD  0
ArcOn           DD  0
NoFix           DD  0
cpy             DD  0
Row             DD  0

Pos             DD  0
DecPos          DD  0
DP              DD  0
FPLZ            DD  0
PassDec         DD  0
I               DD  0
N               DD  0
T               DD  1
W               DD  0
Base            DD  10
HBase           DD  0
PrevBase        DD  0
StoreFlag       DD  0
SubZero         DD  0
AboutName       DB  "AboutDialog", 0    ; About Box Name
szOpen          DB  "open", 0           ; Action to perform
;
IDT             DD  IDT_TOOLBAR1, IDT_TOOLBAR2, IDT_TOOLBAR3, IDT_TOOLBAR4, IDT_TOOLBAR5
;
tb1     TBBUTTON    <0, IDB_BUTSIN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <1, IDB_BUTCOT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <2, IDB_BUTMC, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <3, IDB_BUT07, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <4, IDB_BUT08, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <5, IDB_BUT09, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <6, IDB_BUTADD, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <7, IDB_BUTSQ, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbb1    TBBUTTON    <8, IDB_BUTHYP, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbl1    Equ         ($ - tbb1)
;
tb2     TBBUTTON    <0, IDB_BUTCOS, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <1, IDB_BUTLOG, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <2, IDB_BUTMR, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <3, IDB_BUT04, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <4, IDB_BUT05, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <5, IDB_BUT06, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <6, IDB_BUTSUB, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <7, IDB_BUTPCT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbb2    TBBUTTON    <8, IDB_BUTREC, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbl2    Equ         ($ - tbb2)
;
tb3     TBBUTTON    <0, IDB_BUTTAN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <1, IDB_BUT2X, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <2, IDB_BUTMS, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <3, IDB_BUT01, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <4, IDB_BUT02, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <5, IDB_BUT03, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <6, IDB_BUTMUL, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <7, IDB_BUTPOW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbb3    TBBUTTON    <8, IDB_BUTXN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbl3    Equ         ($ - tbb3)
;
tb4     TBBUTTON    <0, IDB_BUTCSC, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <1, IDB_BUT10X, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <2, IDB_BUTMP, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <3, IDB_BUT00, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <4, IDB_BUTPER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <5, IDB_BUTEQ, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <6, IDB_BUTDIV, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <7, IDB_BUTPM, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbb4    TBBUTTON    <8, IDB_BUTPI, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbl4    Equ         ($ - tbb4)
;
tb5     TBBUTTON    <0, IDB_BUTSEC, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <1, IDB_BUTEX, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <2, IDB_BUTMM, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <3, IDB_BUTA, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <4, IDB_BUTB, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <5, IDB_BUTC, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <6, IDB_BUTD, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <7, IDB_BUTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbb5    TBBUTTON    <8, IDB_BUTF, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
tbl5    Equ         ($ - tbb5)
;
tb      DD          tb1, tb2, tb3, tb4, tb5
tbl     DD          tbl1, tbl2, tbl3, tbl4, tbl5
;
.Data?
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hover       BOOL        ?
orgStatic   DD          ?
hFinger     DD          ?
buff        DB          256 Dup (?)
wc          WNDCLASS    <?>
msg         MSG         <?>
lf          LOGFONT     <?>
;
;
.Code
;-------------------------------------------;
start:  Call InitCommonControls          ; Initialize the common ctrl lib
        Invoke  GetModuleHandle, 0
        Mov hInst, Eax                   ; hInstance is same as HMODULE
        Invoke  GetCommandLine
        Mov CommandLine, Eax
        Invoke  WinMain, hInst, NULL, CommandLine, SW_SHOWDEFAULT
        Invoke  ExitProcess, msg.wParam
;
;
; _________________________________________
;|                                         |
;|            WinMain Procedure            |
;|_________________________________________|
;
WinMain Proc hInstance:DWord, hPrevInst:DWord, CmdLine:DWord, CmdShow:DWord
;-------------------------------------------
;       Initialize the WndClass structure and register the class name
        Mov wc.style, CS_HREDRAW Or CS_VREDRAW Or CS_GLOBALCLASS
        Mov wc.lpfnWndProc, Offset WndProc
        Mov wc.cbClsExtra, 0
        Mov wc.cbWndExtra, 0
        Mov Eax, hInst
        Mov wc.hInstance, Eax
        Invoke  LoadIcon, Eax, IDI_ICON1
        Mov wc.hIcon, Eax
        Invoke  LoadCursor, 0, IDC_ARROW
        Mov wc.hCursor, Eax
        Mov wc.hbrBackground, COLOR_BTNFACE + 1
        Mov wc.lpszMenuName, 0
        Mov wc.lpszClassName, Offset class
        Invoke  RegisterClass, Offset wc
        Invoke  LoadMenu, hInst, IDR_MENU1
        Mov hMenu, Eax
;
;       [Center the window]
        Invoke  GetSystemMetrics, SM_CXSCREEN
        Sub Eax, 238
        Shr Eax, 1
        Push Eax
        Invoke  GetSystemMetrics, SM_CYSCREEN
        Sub Eax, 270
        Shr Eax, 1
        Pop Ebx
;
;       [Create the Main Window]
        Invoke  CreateWindowEx, 0, Addr class, Addr szTB,
                WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or WS_MINIMIZEBOX,
                Ebx, Eax, 238, 270, NULL, hMenu, hInstance, NULL
        Mov hWndMain, Eax
        Invoke  ShowWindow, hWndMain, SW_SHOWNORMAL
        Invoke  UpdateWindow, hWndMain
        Invoke  SetWindowPos, hWndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_SHOWWINDOW
        Invoke  LoadAccelerators, hInst, 2007
        Mov hAccel, Eax
BeginLoop:
        Invoke  GetMessage, Offset msg, 0, 0, 0
        Cmp Eax, 0
        Je EndLoop
        Invoke  TranslateAccelerator, hWndMain, hAccel, Offset msg
        Cmp Eax, 0
        Jne BeginLoop
        Invoke  TranslateMessage, Offset msg
        Invoke  DispatchMessage, Offset msg
        Jmp BeginLoop
EndLoop:
        Ret
;-------------------------------------------
WinMain EndP
;
;
; _________________________________________
;|                                         |
;|            WinProc Procedure            |
;|_________________________________________|
;
WndProc Proc hwnd:DWord, wmsg:DWord, wparam:DWord, lparam:DWord
;-------------------------------------------
        Mov Eax, wmsg
        Cmp Eax, WM_CREATE
        Je wmcreate
        Cmp Eax, WM_COMMAND
        Je wmcommand
        Cmp Eax, WM_CLOSE
        Je wmdestroy
        Cmp Eax, WM_NOTIFY
        Je wmnotify
        Cmp Eax, WM_INITMENUPOPUP
        Je wminitmenupopup
        .If wmsg == WM_KEYDOWN
          Invoke  SetFocus, hEdit
        .EndIf
        Jmp defwndproc
wmcommand:
        Mov Eax, wparam
        Cwde                                ; Only low word contains command
        Cmp Eax, IDM_CLOSE
        Je wmdestroy
        Cmp Eax, IDM_CUT
        Je idmcut
        Cmp Eax, IDM_COPY
        Je idmcopy
        Cmp Eax, IDM_PASTE
        Je idmpaste
        Cmp Eax, IDM_INFO
        Je idminfo
        Cmp Eax, IDM_ABOUT
        Je idmabout
        Cmp Eax, 1
        Je wmbs
        Cmp Eax, 2
        Je wmce
        Cmp Eax, 3
        Je wmclr
        .If Eax == 19
          Mov T, 1
          Invoke  SendMessage, hRad, BM_SETCHECK, BST_UNCHECKED, 0  ; Sets rad to unchecked
        .EndIf
        .If Eax == 20
          Mov T, 2
          Invoke  SendMessage, hDeg, BM_SETCHECK, BST_UNCHECKED, 0  ; Sets deg to unchecked
        .EndIf
;       21=Dec * 22=Hex * 23=Oct * 24=Bin
        And sw2, 0
        .If Eax == 21                       ; Dec
          .If Base != 10
            MOVmd PrevBase, Base
            Mov Base, 10
            Mov sw2, 10
            Call DsplyConv
          .EndIf
        .EndIf
        .If Eax == 22                       ; Hex
          .If Base != 16
            MOVmd PrevBase, Base
            Mov Base, 16
            Mov sw2, 16
            Call DsplyConv
          .EndIf
        .EndIf
        .If Eax == 23                       ; Oct
          .If Base != 8
            MOVmd PrevBase, Base
            Mov Base, 8
            Mov sw2, 8
            Call DsplyConv
          .EndIf
        .EndIf
        .If Eax == 24                       ; Bin
          .If Base != 2
            MOVmd PrevBase, Base
            Mov Base, 2
            Mov sw2, 2
            Call DsplyConv
          .EndIf
        .EndIf
        .If Eax > 20 && Eax < 25
          And I, 0
        .EndIf
        .If Eax == 43
          And float, 0
          Invoke  SendMessage, hFloat, BM_GETCHECK, 0, 0
          .If Eax == 1
            Or float, 1
          .EndIf
          Jmp wmclr
        .EndIf
        .If Eax == 50
          And ArcOn, 0
          Invoke  SendMessage, hArc, BM_GETCHECK, 0, 0
          .If Eax == 1
            Or ArcOn, 1
          .EndIf
        .EndIf
        Jmp defwndproc
wmcreate:
        Invoke  GetSysColor, COLOR_MENU
        Mov BackGC, Eax
        Invoke  lstrcpy, Addr lf.lfFaceName, Addr FontName
        Mov lf.lfHeight, -12
        Mov lf.lfWeight, 500
        Invoke  CreateFontIndirect, Addr lf
        Mov hFont, Eax
        Invoke  lstrcpy, Addr lf.lfFaceName, Addr FontName1
        Mov lf.lfHeight, -12
        Mov lf.lfWeight, 500
        Invoke  CreateFontIndirect, Addr lf
        Mov hDspF, Eax
        Invoke  CreateWindowEx, NULL, Addr Butt, Addr float,
                WS_CHILD Or WS_VISIBLE Or BS_AUTOCHECKBOX,
                106, 54, 130, 12, hwnd, 43, hInst, NULL ; Floating Point
        Mov hFloat, Eax
        Invoke  SendMessage, hFloat, WM_SETFONT, hFont, 0
        Invoke  CreateWindowEx, WS_EX_CLIENTEDGE, Addr EditPT, NULL,
                WS_CHILD Or WS_VISIBLE Or WS_BORDER Or ES_RIGHT Or ES_AUTOHSCROLL Or ES_SAVESEL,
                4, 0, 225, 22, hwnd, 44, hInst, NULL    ; Edit window
        Mov hEdit, Eax
        Invoke  SetWindowLong, hEdit, GWL_WNDPROC, EditProc
        Mov SubEdit, Eax
        Invoke  CreateWindowEx, NULL, Addr Butt, Addr szArc,
                WS_CHILD Or WS_VISIBLE Or BS_AUTOCHECKBOX,
                8, 32, 40, 12, hwnd, 50, hInst, NULL    ; Arc for trig
        Mov hArc, Eax
        Invoke  SendMessage, hArc, WM_SETFONT, hFont, 0
        Invoke  CreateWindowEx, WS_EX_CLIENTEDGE, Addr EditPT, NULL,
                WS_CHILD Or WS_VISIBLE Or WS_BORDER Or ES_CENTER Or ES_READONLY,
                65, 26, 25, 21, hwnd, 88, hInst, NULL   ; Memory window
        Mov hMem, Eax
        Invoke  CreateWindowEx, NULL, Addr Butt, Addr BackS,
                WS_CHILD Or WS_VISIBLE,
                104, 26, 80, 20, hwnd, 1, hInst, NULL   ; Backspace button
        Mov hBkSp, Eax
        Invoke  SendMessage, hBkSp, WM_SETFONT, hFont, 0
        Invoke  CreateWindowEx, WS_EX_CLIENTEDGE, Addr EditPT, NULL,
                WS_CHILD Or WS_VISIBLE Or WS_BORDER Or ES_CENTER Or ES_READONLY,
                203, 26, 25, 21, hwnd, 89, hInst, NULL  ; Operator window
        Mov hOpr, Eax
        Invoke  CreateWindowEx, NULL, Addr Butt, Addr CE,
                WS_CHILD Or WS_VISIBLE,
                185, 73, 20, 20, hwnd, 2, hInst, NULL   ; Clear error button
        Mov hCE, Eax
        Invoke  SendMessage, hCE, WM_SETFONT, hFont, 0
        Invoke  CreateWindowEx, NULL, Addr Butt, Addr CLR,
                WS_CHILD Or WS_VISIBLE,
                205, 73, 20, 20, hwnd, 3, hInst, NULL   ; Clear button
        Mov hCLR, Eax
        Invoke  SendMessage, hCLR, WM_SETFONT, hFont, 0
;       Check boxes and radio buttons
        Invoke  CreateWindowEx, NULL, Addr Butt, 0,
                WS_CHILD Or WS_VISIBLE Or BS_GROUPBOX,
                4, 43, 89, 28, hwnd, 14, hInst, NULL    ; Deg & Rad group box
        Invoke  CreateWindowEx, NULL, Addr Butt, 0,
                WS_CHILD Or WS_VISIBLE Or BS_GROUPBOX,
                4, 65, 178, 28, hwnd, 15, hInst, NULL   ; Base group box
        Xor Ebx, Ebx
        Mov XP, 8
        Mov N, 19
BuildRadio:
        .If N < 21
          Invoke  CreateWindowEx, NULL, Addr Butt, Addr DegT[Ebx],
                  WS_CHILD Or WS_VISIBLE Or BS_AUTOCHECKBOX,
                  XP, 55, 39, 12, hwnd, N, hInst, NULL  ; Deg & Rad check boxes
          Sub XP, 3
        .Else
          Invoke  CreateWindowEx, NULL, Addr Butt, Addr DegT[Ebx],
                  WS_CHILD Or WS_VISIBLE Or BS_AUTORADIOBUTTON,
                  XP, 77, 40, 12, hwnd, N, hInst, NULL  ; Base radio buttons
        .EndIf
        Mov hDeg[Ebx], Eax
        Invoke  SendMessage, hDeg[Ebx], WM_SETFONT, hFont, 0
        .If N < 24
          Add Ebx, 4
          Add N, 1
          .If N == 21
            Mov XP, 8
          .Else
            Add XP, 43
          .EndIf
          Jmp BuildRadio
        .EndIf
        Invoke  SendMessage, hDeg, BM_SETCHECK, BST_CHECKED, 0  ; Sets deg to checked
        Invoke  SendMessage, hDec, BM_SETCHECK, BST_CHECKED, 0  ; Sets dec to checked
;       Toolbars
        Xor Ebx, Ebx
        Mov XP, 4
        Mov YP, 94
        Mov Row, 0
        Mov I, 9
        Mov N, 11
        Mov W, 272
BuildTB:
        Invoke  CreateWindowEx, NULL, Addr Stat, 0,
                WS_CHILD Or WS_VISIBLE,
                XP, YP, W, 24, hwnd, 1, hInst, NULL     ; Toolbars
        Mov hTB01, Eax
        Invoke  SetWindowLong, hTB01, GWL_WNDPROC, ToolbarProc
        Mov SubTool, Eax
        Invoke  CreateToolbarEx, hTB01, WS_CHILD Or WS_VISIBLE Or CCS_NODIVIDER,
                IDT[Ebx], I, hInst, IDT[Ebx], tb[Ebx], N, 16, 16, 16, 16, tbl[Ebx]
        .If Row < 4
          Add Ebx, 4
          Add YP, 24
          Add Row, 1
          Jmp BuildTB
        .EndIf
        And I, 0
wmnotify:
        Jmp returnP
wminitmenupopup:
        Invoke  SendMessage, hEdit, EM_GETSEL, Addr w1, Addr w2
        Mov Eax, w1
        .If w2 > Eax
          Invoke  EnableMenuItem, hMenu, IDM_CUT, MF_BYCOMMAND Or MF_ENABLED
          Invoke  EnableMenuItem, hMenu, IDM_COPY, MF_BYCOMMAND Or MF_ENABLED
        .Else
          Invoke  EnableMenuItem, hMenu, IDM_CUT, MF_BYCOMMAND Or MF_GRAYED
          Invoke  EnableMenuItem, hMenu, IDM_COPY, MF_BYCOMMAND Or MF_GRAYED
        .EndIf
        Jmp returnP
idmcut: Invoke  SendMessage, hEdit, WM_CUT, 0, 0
        Jmp wmclr
idmcopy:
        Invoke  SendMessage, hEdit, WM_COPY, 0, 0
        Jmp returnP
idmpaste:
        Call ClearValues
        Invoke  SendMessage, hEdit, WM_PASTE, 0, 0
        Jmp returnP
idminfo:
        Invoke  MessageBox, NULL, Offset Info, Offset AppName, MB_OK Or MB_TOPMOST
        Jmp returnP
idmabout:
        Invoke  CreateDialogParam, hInst, Addr AboutName,
                hWndMain, Offset AboutDlgProc, NULL
        Jmp returnP
wmbs:   Invoke  SendMessage, hEdit, WM_GETTEXT, 35, Addr Buffer   ; Backspace
        Invoke  lstrlen, Addr Buffer
        .If Eax == 0
          Jmp returnP
        .EndIf
        .If Eax == 2 && Byte Ptr Buffer == '-'
          Jmp wmclr
        .EndIf
        Invoke  lstrcpyn, Addr ConvO, Addr Buffer, Eax
        Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr ConvO
        Invoke  SendMessage, hEdit, EM_SETSEL, 33, 33
        Invoke  SetFocus, hWndMain
        Invoke  lstrcpy, Addr Buffer, Addr ConvO
        Call AsciiToBase
        Invoke  lstrcpy, Addr Buffer, Addr ConvO
        Call AsciiToFloat
        Mov Edx, Offset RNum10
        Call FloatToAscii
        Jmp returnP
wmce:   Mov ConvO, 0H                   ; Clear error
        Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Offset ConvO
        Invoke  SetFocus, hWndMain
        Jmp returnP
wmclr:  Call ClearValues                 ; Clears all Fields
        Jmp returnP
defwndproc:
        Invoke  DefWindowProc, hwnd, wmsg, wparam, lparam
        Jmp finish
wmdestroy:
        Push 0
        Call PostQuitMessage             ; Quit
        Jmp returnP
returnP:
        Xor Eax, Eax
finish: Ret
;-------------------------------------------
WndProc EndP
;
;
; _________________________________________
;|                                         |
;|              Clear Values.              |
;|_________________________________________|
;
ClearValues Proc
;-------------------------------------------
        Mov ConvO, 0
        Mov ConvI, 0
        Mov Buffer, 0
        Mov LBuff, 0
        Mov RBuff, 0
        Mov PLBuff, 0
        Mov PRBuff, 0
        And HPress, 0
        And NPress, 0
        And RPress, 0
        And BPress, 0                   ; 1=add, 2=sub, 3=mul, 4=div
        And DP, 0
        Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Offset ConvO
        Invoke  SetFocus, hWndMain
        Invoke  SendMessage, hOpr, WM_SETTEXT, NULL, Addr Clear
        Mov Len, 0
        Invoke  CLRMW, Offset R, 32
        And First, 0
        Fldz
        Fstp RNum10
        Fldz
        Fstp RWrk10
        Ret
;-------------------------------------------
ClearValues EndP
;
; _________________________________________
;|                                         |
;|        Processes keyboard input.        |
;|_________________________________________|
;
EditProc Proc hwnd:DWord, wmsg:DWord, wparam:DWord, lparam:DWord
;-------------------------------------------
        Mov Key, 0
        .If wmsg == WM_KEYDOWN
          Invoke  SendMessage, hEdit, EM_GETSEL, Addr w1, Addr w2
          Mov Eax, w1
          .If w2 > Eax && wparam != 17      ; CTRL key
            Call ClearValues
          .EndIf
        .EndIf
        .If wmsg == WM_PASTE
          Call ClearValues
          Mov Key, 288
          Jmp pass
        .EndIf
        .If wmsg == WM_CHAR
          .If wparam == 2BH
            Mov wmsg, WM_KEYUP
            Mov wparam, 6BH
          .EndIf
          .If wparam == 2AH
            Mov wmsg, WM_KEYUP
            Mov wparam, 6AH
          .EndIf
        .EndIf
        .If wmsg == WM_KEYUP
          Invoke  SetFocus, hWndMain
          Invoke  SendMessage, hEdit, WM_GETTEXT, 35, Addr Buffer
          Invoke  lstrlen, Addr Buffer
          .If Eax > 16 && BPress == 3
            Invoke  MessageBeep, MB_OK
            Mov Buffer + 15, 0
            Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr Buffer
          .EndIf
          .If Eax > 19 && BPress == 4 || Eax > 19 && float == 1
            Invoke  MessageBeep, MB_OK
            Mov Buffer + 18, 0
            Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr Buffer
          .EndIf
          .If wparam > 2FH && wparam < 3AH
            MOVmd Key, wparam
            Sub Key, 48
            Add Key, 200
            Jmp pass
          .EndIf
          .If wparam > 5FH && wparam < 6AH
            MOVmd Key, wparam
            Sub Key, 96
            Add Key, 200
            Jmp pass
          .EndIf
          .If wparam > 40H && wparam < 47H
            MOVmd Key, wparam
            Sub Key, 55
            Add Key, 200
            Jmp pass
          .EndIf
          .If wparam == 6EH || wparam == 0BEH
            Mov Key, 216                ; .
          .ElseIf wparam == 6BH             ;|| wparam == 0bbh
            Mov Key, 218                ; +
          .ElseIf wparam == 6DH || wparam == 0BDH
            Mov Key, 219                ; -
          .ElseIf wparam == 6AH || wparam == 0BAH
            Mov Key, 220                ; *
          .ElseIf wparam == 6FH || wparam == 0BFH
            Mov Key, 221                ; /
          .ElseIf wparam == 0DH || wparam == 0BBH
            Mov Key, 222                ; =
          .Else
          .EndIf
        .EndIf
pass:   Invoke  CallWindowProc, SubEdit, hwnd, wmsg, wparam, lparam
        .If wmsg == WM_CUT
          Call ClearValues
        .EndIf
        .If Key > 0
          Call ToolbarProc
        .EndIf
        Ret
;-------------------------------------------
EditProc EndP
;
;
; _________________________________________
;|                                         |
;|       Processes calculator input.       |
;|_________________________________________|
;
ToolbarProc Proc hwnd:DWord, wmsg:DWord, wparam:DWord, lparam:DWord
;-------------------------------------------
        .If wmsg == WM_COMMAND || Key > 0
          Invoke  SendMessage, hOpr, WM_SETTEXT, NULL, Addr Clear
          .If Key > 0
            MOVmd wparam, Key
            Mov Key, 0
            Invoke  SetFocus, hWndMain
          .EndIf
          Invoke  SendMessage, hEdit, WM_GETTEXT, 35, Offset ConvO
          Invoke  SendMessage, hEdit, WM_GETTEXT, 35, Offset Buffer
          .If Buffer == '*'
            Jmp GetOut
          .EndIf
          Mov Eax, wparam
          Mov N, 0
          .If Eax == 288
            Mov ConvI, 0
            Invoke  lstrlen, Addr Buffer
            Mov Esi, Eax
            Xor Edi, Edi
            Mov Eax, '0'
            Mov Ecx, '0'
            Mov Edx, '0'
            .If Base == 10 || Base == 16
              Mov Ebx, '9'
              .If Base == 16
                Mov Ecx, 'A'
                Mov Edx, 'F'
              .EndIf
            .ElseIf Base == 2
              Mov Ebx, '1'
            .ElseIf Base == 8
              Mov Ebx, '7'
            .EndIf
            .While (Esi)
              .If Byte Ptr Buffer[Edi] > 90
                Sub Byte Ptr Buffer[Edi], 32
                Sub Byte Ptr ConvO[Edi], 32
              .EndIf
              .If Byte Ptr Buffer[Edi] >= Al && Byte Ptr Buffer[Edi] <= Bl \
                  || Byte Ptr Buffer[Edi] >= Cl && Byte Ptr Buffer[Edi] <= Dl
              .Else
                Call ClearValues
                Invoke  MessageBox, NULL, Addr szPaste, Addr AppName, MB_OK Or MB_ICONWARNING Or MB_TASKMODAL
                Jmp GetOut
              .EndIf
              Inc Edi
              Dec Esi
            .EndW
            Jmp DecP
          .EndIf
          .If Base == 10 || Base == 8       ; Dec or Oct
            Or N, 1
          .EndIf
          .If ((Eax > 199 && Eax < 210 && N == 1 || Eax > 199 && Eax < 216 && Base == 16)\
              || (Eax > 199 && Eax < 202 && Base == 2 || Eax == 216))
            Mov Eax, wparam
            Sub Eax, 200
            .If Eax == 16
              .If DP == 0
                Mov ConvI, '.'
                Mov ConvI + 1, 0
              .Else
                Mov ConvI, 0
              .EndIf
              Jmp DecP
            .EndIf
            Lea Ebx, Offset FmtA
            .If Base == 16
              Lea Ebx, Offset FmtH
            .EndIf
            Invoke  wsprintf, Addr ConvI, Ebx, Eax
DecP:       .If ConvO == '0' && ConvO + 1 == 0
              Mov ConvO, 0
            .EndIf
            Invoke  lstrcat, Offset ConvO, Offset ConvI
            Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Offset ConvO
            Invoke  lstrlen, Addr ConvO
            Mov Ebx, 34
            .If Base == 16
              Mov Ebx, 28
            .EndIf
            .If Eax > Ebx
              Invoke  MessageBeep, MB_OK
              Mov ConvO[Ebx], 0
              Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr ConvO
            .EndIf
            .If Eax > 16 && BPress == 3
              Invoke  MessageBeep, MB_OK
              Mov ConvO + 16, 0
              Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr ConvO
            .EndIf
            .If Eax > 19 && BPress == 4 || Eax > 19 && float == 1
              Invoke  MessageBeep, MB_OK
              Mov ConvO + 19, 0
              Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr ConvO
            .EndIf
            Invoke  SendMessage, hEdit, EM_SETSEL, 34, 34
            Invoke  lstrcpyn, Addr Buffer, Addr ConvO, 34
            Call AsciiToBase
            Invoke  lstrcpyn, Addr Buffer, Addr ConvO, 34
            Call AsciiToFloat
            Mov Edx, Offset RNum10
            Call FloatToAscii
            Mov Eax, wparam
          .EndIf
;         Memory clear
          .If Eax == IDB_BUTMC
            And StoreFlag, 0
            Fldz
            Fstp RMem10
            Invoke  CLRMW, Offset MEM, 12
            Invoke  SendMessage, hMem, WM_SETTEXT, NULL, Addr Clear
          .EndIf
;         Memory recall
          .If Eax == IDB_BUTMR
            .If BPress == 0
              Fld RMem10
              Fstp RNum10
              Fld RMem10
              Fstp RWrk10
            .Else
              Fld RNum10
              Fstp RWrk10
              Fld RMem10
              Fstp RNum10
            .EndIf
            Mov Edx, Offset RNum10
            Call FloatToAscii
            MOVmd MEM + 40, SubZero
            Invoke  CopyMW, Offset R, Offset MEM, 12
            Call BaseToAscii
            Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr ConvO
            Invoke  SendMessage, hEdit, EM_SETSEL, 33, 33
          .EndIf
;         Memory store
          .If Eax == IDB_BUTMS
StoreMem:   Mov StoreFlag, 1
            Fld RNum10
            Fstp RMem10
            Invoke  CopyMW, Offset MEM, Offset R, 12
            Invoke  SendMessage, hMem, WM_SETTEXT, NULL, Addr M
            Call StoreCLR
            Jmp GetOut
          .EndIf
;         Memory add
          .If Eax == IDB_BUTMP
            Cmp StoreFlag, 0
            Je StoreMem
            Fld RNum10
            Fld RMem10
            Fadd St(0), St(1)
            Fstp RMem10
            Mov Edx, Offset RMem10
            Call FloatToAscii
            Invoke  CopyMW, Offset PT, Offset MEM, 12
            Mov BPress, 1
            Call Prep
            Call AddEM
            Mov BPress, 0
            Invoke  CopyMW, Offset MEM, Offset R, 12
            Invoke  SendMessage, hMem, WM_SETTEXT, NULL, Addr M
            Call StoreCLR
          .EndIf
;         Memory subtract
          .If Eax == IDB_BUTMM
            Cmp StoreFlag, 0
            Je StoreMem
            Fld RNum10
            Fld RMem10
            Fsub St(0), St(1)
            Fstp RMem10
            Mov Edx, Offset RMem10
            Call FloatToAscii
            Invoke  CopyMW, Offset PT, Offset MEM, 12
            Mov BPress, 2
            Call Prep
            Call SubEM
            And BPress, 0
            Invoke  CopyMW, Offset MEM, Offset R, 12
            Invoke  SendMessage, hMem, WM_SETTEXT, NULL, Addr M
            Call StoreCLR
          .EndIf
;         Load pi
          .If Eax == IDB_BUTPI
            Fldpi
            Fstp RNum10
            Mov Edx, Offset RNum10
            Call FloatToAscii
            Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr Pi
            Invoke  SendMessage, hEdit, EM_SETSEL, 33, 33
            Invoke  lstrcpy, Addr Buffer, Addr Pi
            Call AsciiToBase
          .EndIf
;         Trig functions
          .If Eax == IDB_BUTSIN || Eax == IDB_BUTCOS || Eax == IDB_BUTTAN || \
              Eax == IDB_BUTSEC || Eax == IDB_BUTCSC || Eax == IDB_BUTCOT
            Finit
            Fld RNum10
            .If T == 1
              Fld RDeg10
              Fmul St(0), St(1)
              .If Eax == IDB_BUTTAN && ArcOn == 1
                Fld RNum10
              .EndIf
            .EndIf
            .If Eax == IDB_BUTSIN
              .If ArcOn == 0
                Fsin
              .Else
                Fld St(0)               ; Duplicate X on tos.
                Fmul                        ; Compute X**2.
                Fld St(0)               ; Duplicate X**2 on tos.
                Fld1                        ; Compute 1-X**2.
                Fsubr
                Fdiv                        ; Compute X**2/(1-X**2).
                Fsqrt                       ; Compute sqrt(x**2/(1-X**2)).
                Fld1                        ; To compute full arctangent.
                Fpatan                      ; Compute atan of the above.
              .EndIf
            .ElseIf Eax == IDB_BUTCOS
              .If ArcOn == 0
                Fcos
              .Else
                Fld St(0)               ; Duplicate X on tos.
                Fmul                        ; Compute X**2.
                Fld St(0)               ; Duplicate X**2 on tos.
                Fld1                        ; Compute 1-X**2.
                Fsubr
                Fdivr                       ; Compute (1-x**2)/X**2.
                Fsqrt                       ; Compute sqrt((1-X**2)/X**2).
                Fld1                        ; To compute full arctangent.
                Fpatan                      ; Compute atan of the above.
              .EndIf
            .ElseIf Eax == IDB_BUTTAN && ArcOn == 0
              Fptan
              Fmul St(0), St(1)
            .ElseIf Eax == IDB_BUTTAN && ArcOn == 1
              Fld1                          ; To compute full arctangent.
              Fpatan                        ; Compute atan of the above.
              .If T == 1
                Fld RRad10
                Fmul St(0), St(1)
              .EndIf
            .ElseIf Eax == IDB_BUTSEC
              .If ArcOn == 0
                Fcos
                Fld1
                Fdivr
              .Else
                Fld St(0)               ; Duplicate
                Fmul                        ; Compute x*x
                Fld1                        ; Load 1
                Fsub                        ; Compute x*x-1
                Fsqrt                       ; Compute sqrt(x*x-1)
                Fld1                        ; Load 1
                Fpatan                      ; Compute atan of above.
              .EndIf
            .ElseIf Eax == IDB_BUTCSC
              .If ArcOn == 0
                Fsin
                Fld1
                Fdivr
              .Else
                Fld St(0)               ; Duplicate
                Fmul                        ; Compute x*x
                Fld1                        ; Load 1
                Fsub                        ; Compute x*x-1
                Fld1                        ; Load 1
                Fdivr                       ; Compute 1/(x*x-1)
                Fsqrt                       ; Compute sqrt(1/(x*x-1))
                Fld1                        ; Load 1
                Fpatan                      ; Compute atan of above.
              .EndIf
            .ElseIf Eax == IDB_BUTCOT
              .If ArcOn == 0
                Fsincos
                Fdivr
              .Else
                Fld1                        ; fpatan computes
                Fxch                        ; atan(st(1)/st(0)).
                Fpatan                      ; atan(st(0)/st(1)).
              .EndIf
            .EndIf
            Fstp RNum10
            .If ArcOn == 0 || ArcOn == 1 && Eax == IDB_BUTTAN
              Or NoFix, 1
            .EndIf
            Mov Edx, Offset RNum10
            Call FloatToAscii
            And NoFix, 0
            Jmp FromSQ
          .EndIf
;         Log 10 function
          .If Eax == IDB_BUTLOG && Buffer != 0
            Finit
            Call AsciiToFloat
            Fld RNum10
            Fld1
            Fxch
            Fyl2x                           ; st(1) * log2(st(0)) 'alpha l not num 1'
            Fldl2t
            Fdiv
            Fstp RNum10
            Mov Edx, Offset RNum10
            Call FloatToAscii
            Jmp FromSQ
          .EndIf
;         Exponent functions
          .If Eax == IDB_BUT2X || Eax == IDB_BUT10X || Eax == IDB_BUTEX && Buffer != 0
            Finit
            Call AsciiToFloat
            Fld RNum10
            .If Eax == IDB_BUT2X
              Call TwoX
            .ElseIf Eax == IDB_BUT10X
              Call TenX
            .ElseIf Eax == IDB_BUTEX
              Call ExpX
            .EndIf
            Mov Edx, Offset RNum10
            Call FloatToAscii
            Jmp FromSQ
          .EndIf
;         Square root function
          .If Eax == IDB_BUTSQ && Buffer != 0
            Finit
            Call AsciiToFloat
            Fld RNum10
            Fsqrt
            Fstp RNum10
            Mov Edx, Offset RNum10
            Call FloatToAscii
            Jmp FromSQ
          .EndIf
;         Hypotenuse function
          .If Eax == IDB_BUTHYP
            Call StoreCLR
            Or HPress, 1
            Jmp GetOut
          .EndIf
;         Pecentage function
          .If Eax == IDB_BUTPCT
            Push BPress
            And BPress, 0
            Or BPress, 3
            Call Prep
            Invoke  CopyMW, Offset RH, Offset PT, 12
            Invoke  lstrcpy, Addr PLBuff, Addr HLBuff
            Invoke  lstrcpy, Addr PRBuff, Addr HRBuff
            Call MulEM
            Call BaseToAscii
            And BPress, 0
            Call StoreCLR
            Mov DWord Ptr Buffer, 0031302EH
            Call AsciiToBase
            Call BaseToAscii
            Call Prep
            Or BPress, 3
            Call MulEM
            Call BaseToAscii
            Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr ConvO
            Invoke  SendMessage, hEdit, EM_SETSEL, 33, 33
            Pop BPress
            .If BPress > 0
              Invoke  CopyMW, Offset PT, Offset RH, 12
              Invoke  lstrcpy, Addr HLBuff, Addr PLBuff
              Invoke  lstrcpy, Addr HRBuff, Addr PRBuff
              Jmp GetOut
            .EndIf
            Jmp GetOut
          .EndIf
;         X to the 2 power function
          .If Eax == IDB_BUTPOW && Buffer != 0
            .If float == 0
              Invoke  lstrcpy, Offset HLBuff, Offset LBuff
              Invoke  lstrcpy, Offset HRBuff, Offset RBuff
              Invoke  CopyMW, Offset PT, Offset R, 12
              .If PT + 36 > 0 || R + 36 > 0
                Mov BPress, 3
                Call ShiftDec
                Jmp EndIt
              .EndIf
              Call Prep
              Call MulMW
              Invoke  CopyMW, Offset R, Offset R3, 4
              Call BaseToAscii
              Jmp EndIt
            .EndIf
            Finit
            Call AsciiToFloat
            Fld RNum10
            Fld St(0)
            Fmulp St(1), St(0)
            Fstp RNum10
            Mov Edx, Offset RNum10
            Call FloatToAscii
EndIt:      Jmp FromSQ
          .EndIf
;         X to the Nth power function
          .If Eax == IDB_BUTXN
            Call StoreCLR
            Or NPress, 1
            Jmp GetOut
          .EndIf
;         Reciprocal of 1 function
          .If Eax == IDB_BUTREC && Buffer != 0
            Mov ConvH, 31H
            Mov HLBuff, 31H
            Mov HRBuff, 0
            Mov HLen, 0
            Invoke  CLRMW, Offset PT, 12
            Mov PT + 12, 1
            Mov BPress, 4
            Or RPress, 1
            Fld1
            Fstp RWrk10
            Jmp Continue
          .EndIf
;         Plus or Minus
          .If Eax == IDB_BUTPM
            Invoke  SendMessage, hEdit, WM_GETTEXT, 35, Offset ConvO
            .If ConvO != 2DH
              Mov Word Ptr ConvI, 002DH
              Invoke  lstrcat, Addr ConvI, Addr ConvO
            .Else
              Invoke  lstrcpy, Addr ConvI, Addr ConvO + 1
            .EndIf
            .If ConvI + 1 != 0
              Invoke  lstrcpy, Addr Buffer, Addr ConvI
              Call AsciiToBase
              Invoke  lstrcpy, Addr Buffer, Addr ConvI
              Call AsciiToFloat
            .EndIf
            Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr ConvI
          .EndIf
;         Addition function
          .If Eax == IDB_BUTADD
            Invoke  SendMessage, hOpr, WM_SETTEXT, NULL, Addr PO
            Call StoreCLR
            Mov BPress, 1
            Jmp GetOut
          .EndIf
;         Subtraction function
          .If Eax == IDB_BUTSUB
            Invoke  SendMessage, hOpr, WM_SETTEXT, NULL, Addr SO
            Call StoreCLR
            Mov BPress, 2
            Jmp GetOut
          .EndIf
;         Multiply function
          .If Eax == IDB_BUTMUL
            Invoke  SendMessage, hOpr, WM_SETTEXT, NULL, Addr MO
            Call StoreCLR
            Mov BPress, 3
            Jmp GetOut
          .EndIf
;         Divide function
          .If Eax == IDB_BUTDIV
            Invoke  SendMessage, hOpr, WM_SETTEXT, NULL, Addr DO
            Call StoreCLR
            Mov BPress, 4
            Jmp GetOut
          .EndIf
;         Equate function
          .If Eax == IDB_BUTEQ
            Invoke  SendMessage, hOpr, WM_SETTEXT, NULL, Addr EO
Continue:   .If float == 0                  ; Not floating point
              Call Prep
              .If BPress == 1
                Call AddEM
                Jmp FromSQ
              .ElseIf BPress == 2
                Call SubEM
                Jmp FromSQ
              .ElseIf BPress == 3
                Call MulEM
                Jmp FromSQ
              .ElseIf BPress == 4
                Call DivEM
                Jmp FromSQ
              .ElseIf NPress == 1
                .If PT + 36 == 0 && R + 36 == 0 ; No decimals
                  Call PowerN
                  Jmp FromSQ
                .Else
                  Jmp FP
                .EndIf
              .ElseIf HPress == 1
                Jmp FP
              .Else
                Jmp GetOut
              .EndIf
            .EndIf
FP:         Finit
            Fld RNum10
            Fld RWrk10
            .If BPress == 1
              Fadd St(0), St(1)
            .ElseIf BPress == 2
              Fsub St(0), St(1)
            .ElseIf BPress == 3
              Fmul St(0), St(1)
            .ElseIf BPress == 4 && R + 12 > 0 || BPress == 4 && R + 28 > 0
              Fdiv St(0), St(1)
            .ElseIf NPress == 1
              Fld1
              Fxch
              Fyl2x                         ; st(1) * log2(st(0)) 'alpha l not num 1'
              Fmul
              Call TwoX
            .ElseIf HPress == 1
              Fld RWrk10
              Fld St(0)                 ; Duplicate
              Fmulp St(1), St(0)
              Fstp RWrk10
              Fld RNum10
              Fld St(0)                 ; Duplicate
              Fmulp St(1), St(0)
              Fld RWrk10
              Fadd St(0), St(1)
              Fsqrt
            .EndIf
            Fstp RNum10
            Fld RNum10
            Fstp RWrk10
            Mov Edx, Offset RNum10
            Call FloatToAscii
FromSQ:     Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Addr ConvO
            Invoke  SendMessage, hEdit, EM_SETSEL, 33, 33
            And First, 0
            And HPress, 0
            And NPress, 0
            And RPress, 0
            And BPress, 0
            And DP, 0
            Invoke  SendMessage, hEdit, WM_GETTEXT, 34, Offset Buffer
            .If Buffer == '*'
              Mov Buffer, 0
            .EndIf
            Call AsciiToBase
            Call BaseToAscii
            Invoke  SendMessage, hEdit, WM_GETTEXT, 34, Offset Buffer ; For floating point
            Call AsciiToBase
            Fldz
            Fstp RWrk10
            Fldz
            Fstp RNum10
            Invoke  SendMessage, hEdit, WM_GETTEXT, 34, Offset Buffer ; For floating point
            Call AsciiToFloat
            And Min, 0
          .EndIf
        .EndIf
GetOut: Invoke  CallWindowProc, SubTool, hwnd, wmsg, wparam, lparam
        Ret
;-------------------------------------------
ToolbarProc EndP
;
;
; _________________________________________
;|                                         |
;|       Setup for addition routine.       |
;|_________________________________________|
;
AddEM Proc
;-------------------------------------------
        .If Branch
          Jmp DoAdd
        .EndIf
        Mov Eax, PT + 44
        Mov Ebx, R + 44
        .If Eax != Ebx                      ; Signs not equal
          MOVmd R5 + 32, PT + 44
          And BPress, 0
          Or BPress, 2
          Or Branch, 1
          Call SubEM
          Jmp Exit
        .EndIf
DoAdd:  Call AddMW
        Call BaseToAscii
        Mov Eax, R + 36
        .If Eax > HLen
          Mov HLen, Eax
        .EndIf
        Invoke  lstrlen, Offset RBuff
        .If Eax > HLen && DecPos > 0
          Call Round
        .EndIf
        And Branch, 0
Exit:   Ret
;-------------------------------------------
AddEM EndP
;
;
; _________________________________________
;|                                         |
;|      Setup for subtraction routine      |
;|_________________________________________|
;
SubEM Proc
;-------------------------------------------
        .If Branch
          Jmp DoSub
        .EndIf
        Mov Eax, PT + 44
        Mov Ebx, R + 44
        .If Eax != Ebx                      ; Signs not equal
          MOVmd R + 44, R5 + 36
          Or Branch, 1
          Call AddEM
          Jmp Exit
        .EndIf
        .If R5 + 32 == 1
          And R5 + 32, 0
        .Else
          Or R5 + 32, 1
        .EndIf
DoSub:  Mov Eax, R + 36                   ; R+36 = length of dec num's cur
        .If Eax > HLen                      ; HLen = length of dec num's prev
          Mov HLen, Eax
        .EndIf
        Invoke  lstrcmpi, Offset HRBuff, Offset RBuff
        .If Eax == -1                       ; A < B
          Call Round
        .EndIf
        MOVmd R + 44, R5 + 32
        Call SubMW
        Call BaseToAscii
        Invoke  lstrlen, Offset RBuff
        .If HLen > Eax && DecPos > 0
          Invoke  lstrcpy, Addr ConvO, Addr LBuff
          Invoke  lstrcat, Addr ConvO, Addr Period
          Invoke  lstrcat, Addr ConvO, Addr Zero
          Invoke  lstrcat, Addr ConvO, Addr RBuff
          Invoke  lstrlen, Offset LBuff + 1
          Invoke  lstrcpy, Addr RBuff, Addr ConvO[Eax]  ; nonDecimal number
        .EndIf
        Mov BPress, 0
        And Branch, 0
Exit:   Ret
;-------------------------------------------
SubEM EndP
;
;
; _________________________________________
;|                                         |
;|       Setup for  multiply routine       |
;|_________________________________________|
;
MulEM Proc
;-------------------------------------------;
        .If PT + 36 > 0 || R + 36 > 0           ; Decimal numbers
          Call ShiftDec
          Jmp Exit
        .EndIf
        Call MulMW
        Invoke  CopyMW, Offset R, Offset R3, 4
        Mov Eax, PT + 44
        Mov Ebx, R + 44
        And R + 44, 0
        .If Eax != Ebx                      ; Minus
          Or R + 44, 1
        .EndIf
        Call BaseToAscii
Exit:   Ret
;-------------------------------------------
MulEM EndP
;
;
; _________________________________________
;|                                         |
;|        Setup for divide routine.        |
;|_________________________________________|
;
DivEM Proc
;-------------------------------------------
        .If R > 0 || R + 4 > 0 || R + 4 > 0 || R + 8 > 0 || R + 24 > 0
          Call FPDivMW
          Jmp Exit
        .EndIf
        .If PT + 36 > 0 || R + 36 > 0
          Call ShiftDec
          Jmp Exit
        .EndIf
        Call DivMW
        Invoke  CopyMW, Offset R, Offset R2, 4
        Mov Eax, PT + 44
        Mov Ebx, R + 44
        And R + 44, 0
        .If Eax != Ebx                      ; Minus
          Or R + 44, 1
        .EndIf
        Call BaseToAscii
Exit:   Ret
;-------------------------------------------
DivEM EndP
;
;
; _________________________________________
;|                                         |
;| Rounding or borrowing for decimal add   |
;| and subtract.                           |
;|_________________________________________|
;
Round Proc
;-------------------------------------------
        Cmp BPress, 2
        Je SubEM
        Invoke  lstrlen, Addr LBuff
        Add Eax, 2
        Invoke  lstrcpyn, Addr Buffer, Addr ConvI, Eax
        Invoke  lstrcat, Addr Buffer, Addr RBuff + 1
        Call AsciiToBase
        .If HRBuff > '0'
          Add R + 12, 1
        .EndIf
        Call BaseToAscii
        Jmp Done
Subem:  Invoke  lstrcpy, Addr Buffer, Addr HLBuff
        Invoke  lstrcat, Addr Buffer, Addr Period
        Invoke  lstrcat, Addr Buffer, Addr One
        Invoke  lstrcat, Addr Buffer, Addr HRBuff
        Call AsciiToBase
        Sub R + 12, 1
        Invoke  lstrcpy, Addr Buffer, Addr LBuff
        Invoke  lstrcat, Addr Buffer, Addr Period
        Invoke  lstrcat, Addr Buffer, Addr Zero
        Invoke  lstrcat, Addr Buffer, Addr RBuff
        Invoke  CopyMW, Offset PT, Offset R, 12
        Call AsciiToBase
        Push R5 + 32
        Call Prep
        Pop R5 + 32
Done:   Ret
;-------------------------------------------
Round EndP
;
;
; _________________________________________
;|                                         |
;| Converts ascii string of Dec, Hex, Oct  |
;| or Bin to a 128 bit num value.          |
;|_________________________________________|
;
AsciiToBase Proc
;-------------------------------------------
        And DP, 0
        And Pos, 0
        And cnt, 0
        Invoke  CLRMW, Offset R, 32
        Invoke  lstrlen, Addr Buffer
        .If sw1 == 19 && Eax > 19 && BPress == 3    ; Limit Multiplicand & Multiplier to 19
          Mov Edx, Offset Buffer
          Add Edx, 18
          .If Byte Ptr [Edx] + 1 >= 35H
            Inc Byte Ptr [Edx] + 0        ; + 1
          .EndIf
          Mov Byte Ptr [Edx] + 1, 0
          Sub Eax, 19
          Mov Work, Eax
        .EndIf
        Invoke  lstrlen, Addr Buffer
        Mov Ecx, Offset Buffer
        Xor Edx, Edx
        .While (Eax)
          .If Byte Ptr [Ecx] > 60H
            Sub Byte Ptr [Ecx], 57H
            And Pos, 0
          .ElseIf Byte Ptr [Ecx] > 40H
            Sub Byte Ptr [Ecx], 37H
            And Pos, 0
          .ElseIf Byte Ptr [Ecx] == 2EH
            Or Pos, 1
            Or cnt, 1
            Or DP, 1
;           Reduce decimal numbers to 19    ; 16
            Push Eax
            Push Ecx
            Push Edx
            Invoke  lstrlen, Addr Buffer
            Pop Edx
            Mov Ebx, Offset Buffer
            Add Ebx, Edx
            Sub Eax, Edx
            .If Eax > 19
              .If Byte Ptr [Ebx] + 20 >= 35H
                Inc Byte Ptr [Ebx] + 19   ; +1
              .EndIf
              Mov Byte Ptr [Ebx] + 20, 0  ; Terminate string
            .EndIf
            Pop Ecx
            Pop Eax
          .ElseIf Byte Ptr [Ecx] == 2DH
            Or R + 44, 1                 ; Minus
          .Else
            Xor Byte Ptr [Ecx], 30H
            .If Byte Ptr [Ecx] == 0H && Pos == 1
              Add R + 40, 1               ; Number of leading zeros after decimal
            .Else
              And Pos, 0
            .EndIf
          .EndIf
          Inc Ecx
          Inc Edx
          .If cnt == 0
            Mov R + 32, Edx               ; Number of whole numbers
          .EndIf
          Cmp Edx, 32                   ; 64
          Jnb done
          Dec Eax
        .EndW
done:   .If Edx == 0 || Edx == 1 && R + 44 == 1
          Inc Edx
        .EndIf
        MOVmd HBase, Base
        Mov Edi, Offset Buffer              ; edi points to string to copy
        Mov R3 + 12, 1
        Mov R4 + 12, 1
        Add Edi, Edx
        Dec Edi
        And cnt, 0
        .If R + 44 == 1
          Dec Edx
          Sub R + 32, 1
        .EndIf
Conv:   .If Byte Ptr [Edi] == 2EH
          MOVmd D + 32, R + 32                ; Number of whole numbers
          MOVmd D + 36, cnt                 ; Number of decimal numbers
          MOVmd D + 40, R + 40                ; Number of leading zeros after decimal
          MOVmd D + 44, R + 44                ; Minus
          Invoke  CopyMW, Offset D + 16, Offset R, 4
          Invoke  CLRMW, Offset R, 32
          Invoke  CopyMW, Offset R + 16, Offset D + 16, 8
          Mov R3 + 12, 1
          Mov R4 + 12, 1
          Jmp PastDec
        .EndIf
        Add cnt, 1
        Mov Al, Byte Ptr [Edi]           ; Move byte edi points to into al
        And Eax, 000000FFH
        Invoke  CLRMW, Offset B, 4
        Mov B + 12, Eax
        Invoke  CopyMW, Offset A, Offset R4, 4
        Call MulMW
        Invoke  CopyMW, Offset A, Offset R, 4
        Invoke  CopyMW, Offset B, Offset R3, 4
        Or PassDec, 1
        Call AddMW
        And PassDec, 0
        Invoke  CopyMW, Offset A, Offset R4, 4
        Invoke  CLRMW, Offset B, 4
        MOVmd B + 12, Base
        Call MulMW
        Invoke  CopyMW, Offset R4, Offset R3, 4
PastDec:
        Dec Edi
        Dec Edx
        Jnz Conv
        Ret
;-------------------------------------------
AsciiToBase EndP
;
;
; _________________________________________
;|                                         |
;| Converts a 128 bit num value to a Dec,  |
;| Hex, Oct or Bin ascii string.           |
;|_________________________________________|
;
BaseToAscii Proc
;-------------------------------------------
        Mov DecPos, 0
        Push Base
        Push Esi
        Push Edi
        .If sw2 != 0
          MOVmd Base, sw2
        .EndIf
        Mov Pos, 0
        .If R + 28 > 0
          Invoke  CopyMW, Offset A, Offset R + 16, 4
          Mov Pos, 1
        .Else
          Invoke  CopyMW, Offset A, Offset R, 4
        .EndIf
        MOVmd B + 12, Base
        Xor Edi, Edi
        Xor Esi, Esi
Loop1:  Or R5 + 24, 1
        Call DivMW
        And R5 + 24, 0
        Invoke  CopyMW, Offset A, Offset R2, 4
        .If Dl > 9H
          Add Dl, 37H                    ; Convert to hex ASCII
        .Else
          Add Dl, 30H                    ; Convert to dec ASCII
        .EndIf
        Mov Buffer[Esi], Dl
        Inc Edi
        .If A + 12 > 0 || A + 8 > 0 || A + 4 > 0 || A > 0
          Inc Esi
          Jmp Loop1
        .EndIf
        .If R + 28 > 0 && Pos == 1            ; Decimal portion
          Inc Esi
          Mov Eax, R + 40
          Inc Eax
          Push Edi
          Push Esi
          Invoke  lstrcpyn, Addr Buffer[Esi], Addr Zeros, Eax ; Number of leading zeros after dec
          Pop Esi
          Pop Edi
          Add Edi, R + 40
          Add Esi, R + 40
          Mov Byte Ptr Buffer[Esi], 2EH
          Mov DecPos, Esi
          Inc Edi
          Inc Esi
          Invoke  CopyMW, Offset A, Offset R, 4
          Mov Pos, 0
          Jmp Loop1
        .EndIf
        Xor Ecx, Ecx
        .If R + 44 == 1                       ; Minus
          Mov Byte Ptr ConvI, 2DH
          Inc Ecx
        .EndIf
Loop2:  Mov Al, Byte Ptr Buffer[Esi]
        Mov Byte Ptr ConvI[Ecx], Al
        Inc Ecx
        Dec Esi
        Dec Edi
        Jnz Loop2
        Mov Byte Ptr ConvI[Ecx], 0H
        Mov Eax, Base
        .If Eax == HBase
          Mov RBuff, 0H
          Invoke  lstrlen, Addr ConvI
          Mov Esi, Offset ConvI
          Mov Edi, Offset LBuff
Loop3:    .If Byte Ptr [Esi] == 2EH
            Mov Byte Ptr [Edi], 0H
            Mov Edi, Offset RBuff
            Inc Esi
            Dec Eax
            Jz AllDone
          .EndIf
          Mov Bl, Byte Ptr [Esi]
          Mov Byte Ptr [Edi], Bl
          Inc Edi
          Inc Esi
          Dec Eax
          Jnz Loop3
          Mov Byte Ptr [Edi], 0H
        .EndIf
        .If Base == 10 && !sw3
          MOVmd SubZero, R + 40
        .EndIf
AllDone:
        .If cpy != 8
          Invoke  lstrcpy, Addr ConvO, Addr ConvI
        .EndIf
        Pop Edi
        Pop Esi
        Pop Base
        Ret
;-------------------------------------------
BaseToAscii EndP
;
;
; _________________________________________
;|                                         |
;|         Clears multiple dwords.         |
;|_________________________________________|
;
CLRMW Proc To:DWord, Num:DWord
;-------------------------------------------
        PushAD
        Xor Eax, Eax
        Mov Ebx, To
        Mov Ecx, Num
Loop1:  Mov DWord Ptr [Ebx + Eax], 0
        Add Eax, 4
        Loop Loop1
        PopAD
        Ret
;-------------------------------------------
CLRMW EndP
;
;
; _________________________________________
;|                                         |
;|         Copies multiple dwords.         |
;|_________________________________________|
;
CopyMW Proc To:DWord, From:DWord, Num:DWord
;-------------------------------------------
        PushAD
        Xor Eax, Eax
        Mov Edx, To
        Mov Ebx, From
        Mov Ecx, Num
Loop1:  Push DWord Ptr [Ebx + Eax]
        Pop DWord Ptr [Edx + Eax]
        Add Eax, 4
        Loop Loop1
        PopAD
        Ret
;-------------------------------------------
CopyMW EndP
;
;
; _________________________________________
;|                                         |
;|        Compares multiple dwords.        |
;|_________________________________________|
;
CompMW Proc Left:DWord, Right:DWord, Num:DWord
;-------------------------------------------
        PushAD
        Xor Eax, Eax
        Mov Work, 0
        Mov Ebx, Left
        Mov Edx, Right
        Mov Ecx, Num
Loop1:  Mov Esi, DWord Ptr [Ebx + Eax]
        .If Esi > DWord Ptr [Edx + Eax]
          Or Work, 1                   ; A > B
          Jmp Done
        .EndIf
        .If Esi < DWord Ptr [Edx + Eax]
          Or Work, 2                   ; A < B
          Jmp Done
        .EndIf
        Push DWord Ptr [Ebx + Eax]
        Pop DWord Ptr [Edx + Eax]
        Add Eax, 4
        Loop Loop1
Done:   PopAD
        Mov Eax, Work
        And Work, 0
        Ret
;-------------------------------------------
CompMW EndP
;
;
; _________________________________________
;|                                         |
;| Determines the decimal position and the |
;| number of leading zeros for multiply    |
;| and divide.                             |
;|_________________________________________|
;
ShiftDec Proc
;-------------------------------------------
        Push Edi
        Push Esi
        Push Ebx
        Mov Sav, 0
        Mov Work, 0
        Invoke  CLRMW, Offset R5, 8
        MOVmd R5, PT + 36                   ; Decimal numbers dividend or Multiplicand
        MOVmd R5 + 4, R + 36                  ; Decimal numbers divisor or Multiplier
        MOVmd R5 + 32, PT + 44                ; Minus dividend or Multiplicand
        MOVmd R5 + 36, R + 44                 ; Minus divisor or Multiplier
        .If RBuff == 0H
          Mov R5 + 4, 0
        .EndIf
        Mov sw1, 19
        Invoke  CLRMW, Offset R, 32
        Invoke  lstrcpy, Offset Buffer, Offset HLBuff
        Invoke  lstrcat, Offset Buffer, Offset HRBuff
        Call AsciiToBase
        Mov Eax, Work                   ; Work is built in AsciiToBase
        .If R5 >= Eax
          Sub R5, Eax                   ; Adjust the number of decimals
        .EndIf
        .If BPress == 4
          Mov R3 + 12, 1
          Mov Ecx, R5 + 4
          .If R5 >= Ecx
            Sub R5, Ecx
            Jmp NoExtend
          .Else
            Sub Ecx, R5
            Mov R5, 0
          .EndIf
Extender: Invoke  CopyMW, Offset A, Offset R3, 4
          Invoke  CLRMW, Offset B, 4
          MOVmd B + 12, Base
          Call MulMW
          Loop Extender
          Invoke  CopyMW, Offset A, Offset R, 4     ; Dividend
          Invoke  CopyMW, Offset B, Offset R3, 4    ; Extend value
          Call MulMW
          Invoke  CopyMW, Offset R, Offset R3, 4    ; Product
        .EndIf
NoExtend:
        Mov Work, 0
        Invoke  CopyMW, Offset PT, Offset R, 12
        Invoke  CLRMW, Offset R, 32
        Invoke  lstrcpy, Offset Buffer, Offset LBuff
        Invoke  lstrcat, Offset Buffer, Offset RBuff
        Call AsciiToBase
        Mov Eax, Work
        .If R5 + 4 >= Eax
          Sub R5 + 4, Eax                 ; Adjust the number of decimals
        .EndIf
        Call Prep
        .If BPress == 3
          Call MulMW
          Invoke  CopyMW, Offset R, Offset R3, 4
        .ElseIf BPress == 4
          Call DivMW
          Invoke  CopyMW, Offset R, Offset R2, 4
        .EndIf
        Mov Eax, R5 + 32
        Mov Ebx, R5 + 36
        And R + 44, 0
        .If Eax != Ebx                      ; Minus
          Or R + 44, 1
        .EndIf
        Call BaseToAscii
        Invoke  lstrlen, Offset ConvI
        Mov Ecx, Eax
        Mov Ebx, Eax
        Mov Edx, Eax
        Xor Esi, Esi
        Xor Edi, Edi
        .If BPress == 3
          Mov Ecx, R5
          Add Ecx, R5 + 4
          Sub Eax, R5
          Sub Eax, R5 + 4
          Mov R5, Ecx
        .ElseIf BPress == 4
FindDec:  Mov Bl, Byte Ptr ConvI[Esi]   ; Find decimal in Quotient
          .If Bl == 2EH
            Mov Ecx, Esi
            Inc Esi
            Jmp FindDec
          .EndIf
          Inc Esi
          Cmp Bl, 0H
          Jne FindDec
          Mov Ebx, Ecx                  ; Decimal position, length of Quotient whole number
          .If Ecx >= R5
            Sub Ecx, R5
          .Else
            Mov Ecx, R5
          .EndIf
          Mov Eax, Ecx
          Sub Ecx, Ebx
          Inc Ecx
        .EndIf
        Xor Esi, Esi
        Xor Edi, Edi
        .If Ebx >= R5                       ; No zero pad
          Jmp Loop1
        .EndIf
        .If BPress == 3
          Sub Ecx, Ebx
          Inc Ecx
        .EndIf
        Mov Byte Ptr ConvO[Edi], 2EH
        Mov Sav, Edi
        Add Edi, Ecx
        Push Edi
        Push Esi
        Invoke  lstrcpyn, Offset ConvO + 1, Offset Zeros, Ecx
        Pop Esi
        Pop Edi
        Xor Eax, Eax
Loop1:  Mov Bl, Byte Ptr ConvI[Esi]     ; Shift right
        .If Bl == 2EH
          Inc Esi
          Jmp Loop1
        .EndIf
        .If Eax == Edi
          Mov Byte Ptr ConvO[Edi], 2EH
          Mov Sav, Edi
          Inc Edi
        .EndIf
        Mov Byte Ptr ConvO[Edi], Bl
        Inc Edi
        Inc Esi
        Cmp Bl, 0H
        Jne Loop1
        Mov sw1, 0
        Invoke  lstrcpy, Offset Buffer, Offset ConvO
        Call AsciiToBase
        Call BaseToAscii
        Mov Ebx, Offset ConvO
        Add Ebx, Sav
        Call Fixem
        Pop Ebx
        Pop Esi
        Pop Edi
        Ret
;-------------------------------------------
ShiftDec EndP
;
;
; _________________________________________
;|                                         |
;| Stores the current input and performs   |
;| the math functions for running totals.  |
;|_________________________________________|
;
StoreCLR Proc
;-------------------------------------------
        .If First == 0
          Invoke  SendMessage, hEdit, WM_GETTEXT, 35, Offset ConvH
CopyIt:   Invoke  lstrcpy, Offset HLBuff, Offset LBuff
          Invoke  lstrcpy, Offset HRBuff, Offset RBuff
          Invoke  lstrlen, Offset RBuff
          Mov HLen, Eax
          Invoke  CopyMW, Offset PT, Offset R, 12
          Cmp sw1, 3
          Je ClrDsply
          Fld RNum10
          Fstp RWrk10
          Or First, 1
        .EndIf
        .If float == 0
          Call Prep
          .If BPress == 1
            Call AddEM
            And BPress, 0
          .ElseIf BPress == 2
            Call SubEM
            And BPress, 0
          .ElseIf BPress == 3
            Call MulEM
            And BPress, 0
          .ElseIf BPress == 4 && Buffer != 0
            Call DivEM
            And BPress, 0
          .EndIf
          Invoke  lstrcpy, Offset Buffer, Offset ConvO
          Call AsciiToBase
          Call BaseToAscii
          Invoke  lstrcpy, Offset ConvH, Offset ConvO
          Or sw1, 3
          Jmp CopyIt
        .EndIf
        Finit
        Fld RNum10
        Fld RWrk10
        .If BPress == 1
          Fadd St(0), St(1)
          And BPress, 0
        .ElseIf BPress == 2
          Fsub St(0), St(1)
          And BPress, 0
        .ElseIf BPress == 3
          Fmul St(0), St(1)
          And BPress, 0
        .ElseIf BPress == 4 && R + 12 > 0 || BPress == 4 && R + 28 > 0
          Fdiv St(0), St(1)
          And BPress, 0
        .EndIf
        Fstp RWrk10
ClrDsply:
        Mov ConvO, 0
        Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Offset ConvO
        And sw1, 0
        And DP, 0
        Ret
;-------------------------------------------
StoreCLR EndP
;
;
; _________________________________________
;|                                         |
;| Adjusts the decimals numbers.  Prepares |
;| the input for the math functions.       |
;|_________________________________________|
;
Prep Proc
;-------------------------------------------
;       Sets the base power for the decimal number
        .If BPress == 1 || BPress == 2
          Mov R5 + 32, 1
          MOVmd R5 + 36, PT + 44
          Invoke  CompMW, Offset PT, Offset R, 8
          .If Eax == 2                      ; For add & sub flip A & B if B > A
            Invoke  CopyMW, Offset Sav, Offset R, 12
            Invoke  CopyMW, Offset R, Offset PT, 12
            Invoke  CopyMW, Offset PT, Offset Sav, 12
            Invoke  lstrcpy, Offset ConvH, Offset ConvO
            Invoke  lstrcpy, Offset HLBuff, Offset LBuff
            Invoke  lstrcpy, Offset HRBuff, Offset RBuff
            Call BaseToAscii
            Invoke  lstrlen, Offset HRBuff
            Mov HLen, Eax
            Mov R5 + 32, 0
            MOVmd R5 + 36, R + 44
          .EndIf
        .EndIf
        .If PT + 36 > 0 || R + 36 > 0
          Invoke  CLRMW, Offset A, 16
          Mov A + 12, 1
          MOVmd B + 12, HBase
          Mov Eax, R + 36
          .If PT + 36 > Eax
            Mov Ecx, PT + 36
            Sub Ecx, Eax
            Jmp LoopA
          .ElseIf PT + 36 < Eax
            Mov Ecx, Eax
            Sub Ecx, PT + 36
LoopA:      Call MulMW
            Invoke  CopyMW, Offset A, Offset R3, 4
            Loop LoopA
            .If PT + 36 < Eax
              Invoke  CopyMW, Offset B, Offset PT + 16, 4
            .Else
              Invoke  CopyMW, Offset B, Offset R + 16, 4
            .EndIf
            Call MulMW
            .If PT + 36 < Eax
              Invoke  CopyMW, Offset PT + 16, Offset R3, 4
            .Else
              Invoke  CopyMW, Offset R + 16, Offset R3, 4
            .EndIf
          .EndIf
          .If BPress != 4
            Mov Edx, R + 40
            .If PT + 40 > Edx
            .Else
              MOVmd R + 40, PT + 40
            .EndIf
          .EndIf
        .EndIf
        Invoke  CopyMW, Offset A, Offset PT, 8
        Invoke  CopyMW, Offset B, Offset R, 8
        Ret
;-------------------------------------------
Prep EndP
;
;
; _________________________________________
;|                                         |
;|          Adds multiple dwords.          |
;|_________________________________________|
;
AddMW Proc
;-------------------------------------------
        Cmp PassDec, 1
        Je Pass
        Mov Eax, A + 28
        Add Eax, B + 28
        Mov R + 28, Eax
        Mov Eax, A + 24
        Adc Eax, B + 24
        Mov R + 24, Eax
        Mov Eax, A + 20
        Adc Eax, B + 20
        Mov R + 20, Eax
        Mov Eax, A + 16
        Adc Eax, B + 16
        Mov R + 16, Eax
Pass:   Mov Eax, A + 12
        Add Eax, B + 12
        Mov R + 12, Eax
        Mov Eax, A + 8
        Adc Eax, B + 8
        Mov R + 8, Eax
        Mov Eax, A + 4
        Adc Eax, B + 4
        Mov R + 4, Eax
        Mov Eax, A
        Adc Eax, B
        Mov R, Eax
        Ret
;-------------------------------------------
AddMW EndP
;
;
; _________________________________________
;|                                         |
;|        Subtracts multiple dwords        |
;|_________________________________________|
;
SubMW Proc
;-------------------------------------------
        Cmp PassDec, 1
        Je Pass
        Mov Eax, A + 28
        Sub Eax, B + 28
        Mov R + 28, Eax
        Mov Eax, A + 24
        Sbb Eax, B + 24
        Mov R + 24, Eax
        Mov Eax, A + 20
        Sbb Eax, B + 20
        Mov R + 20, Eax
        Mov Eax, A + 16
        Sbb Eax, B + 16
        Mov R + 16, Eax
Pass:   Mov Eax, A + 12
        Sub Eax, B + 12
        Mov R + 12, Eax
        Mov Eax, A + 8
        Sbb Eax, B + 8
        Mov R + 8, Eax
        Mov Eax, A + 4
        Sbb Eax, B + 4
        Mov R + 4, Eax
        Mov Eax, A
        Sbb Eax, B
        Mov R, Eax
        And Eax, 80000000H
        Cmp Eax, 80000000H
        Jnz PlusNum
        Invoke  CopyMW, Offset A, Offset B, 8
        Invoke  CopyMW, Offset B, Offset PT, 8
        Call SubMW
PlusNum:
        Ret
;-------------------------------------------
SubMW EndP
;
;
; _________________________________________
;|                                         |
;| Floating point divide used when the     |
;| divisor is greater then one dword.      |
;|_________________________________________|
;
FPDivMW Proc
;-------------------------------------------
        Finit
        Fld RNum10
        Fld RWrk10
        Fdiv St(0), St(1)
        Fstp RNum10
        Fld RNum10
        Fstp RWrk10
        Mov Edx, Offset RNum10
        .If !RPress
          Or NoFix, 1
        .EndIf
        Call FloatToAscii
        And NoFix, 0
        Ret
;-------------------------------------------
FPDivMW EndP
;
;
; _________________________________________
;|                                         |
;|       Multiplies multiple dwords.       |
;|_________________________________________|
;
MulMW Proc
;-------------------------------------------
        PushAD
;       Multiply B+12 dword of Multiplier times A+12 & A+8 & A+4 & A:
        Mov Eax, B + 12                   ;
        Mov Ebx, Eax                    ; Save Multiplier val
        Mul A + 12                        ; Multiply L.O. dwords
        Mov R3 + 12, Eax                  ; Save partial product
        Mov Ecx, Edx                    ; Save H.O. dword
        Mov Eax, Ebx                    ; Get Multiplier in ebx
        Mul A + 8                         ; Multiply B+12 * A+8.
        Add Eax, Ecx                    ; Add partial product
        Adc Edx, 0                      ; Don't forget carry!
        Mov Ebx, Eax                    ; Save partial product
        Mov Ecx, Edx                    ; For now.
        Mov Eax, B + 12                   ; Get Multiplier in B+12
        Mul A + 4                         ; Multiply B+12 * A+4.
        Add Eax, Ecx                    ; Add partial product
        Adc Edx, 0                      ; Don't forget carry!
        Mov w1, Eax                     ; Save partial product
        Mov Ecx, Edx                    ; For now.
        Mov Eax, B + 12                   ; Get Multiplier in B+12
        Mul A                           ; Multiply B+12 * A.
        Add Eax, Ecx                    ; Add partial product
        Adc Edx, 0                      ; Don't forget carry!
        Mov w2, Eax                     ; Save partial product
        Mov Ecx, 0                      ; For now.
;       Multiply B+8 dword of Multiplier times A+12 & A+8 & A+4 & A:
        Mov Eax, B + 8                    ; Get B+8. Multiplier
        Mul A + 12                        ; Times A+12. dword
        Add Eax, Ebx                    ; Add partial product
        Mov R3 + 8, Eax                   ; Save partial product
        Adc Ecx, Edx                    ; Add in carry/B+8!
        Mov Eax, B + 8                    ; Multiply the B+8.
        Mul A + 8                         ; Words together.
        Add Eax, Ecx
        Push Edx
        Adc Edx, w2                     ; Works if B > A, Don't forget the carry!
        Mov Ebx, Edx
        Pop Edx
        Add Eax, w1                     ; Add partial product
        Mov R3 + 4, Eax                   ; Save partial product
        Adc Edx, w2                     ; Works if A > B    Don't forget carry!
        Mov R3, Ebx
        .If w1 > Ecx
          Mov R3, Edx
        .EndIf
        PopAD
        Ret
;-------------------------------------------
MulMW EndP
;
;
; _________________________________________
;|                                         |
;|        Divides multiple dwords.         |
;|_________________________________________|
;
DivMW Proc
;-------------------------------------------
        Push Ecx
        .If B + 12 == 00000000H
          Jmp DivRet
        .EndIf
        Xor Edx, Edx
        Mov Eax, A                      ; Dividend
        Div B + 12                        ; Divisor
        Mov R2, Eax                     ; Quotient
        Mov Eax, A + 4
        Div B + 12
        Mov R2 + 4, Eax
        Mov Eax, A + 8
        Div B + 12
        Mov R2 + 8, Eax
        Mov Eax, A + 12
        Div B + 12
        Mov R2 + 12, Eax
        Cmp R5 + 24, 1
        Je DivRet                     ; From BaseToAscii no need to find decimals
        Xor Ecx, Ecx
        Mov HRBuff, 0H
        Mov Eax, Edx
Loop1:  .If Edx > 0 && Ecx < 19             ; 16, 12, 24
          Inc Ecx
          Mov Eax, Edx
          Mul Base
          Mov Sav + 8, Edx
          Mov Sav + 12, Eax
          Xor Edx, Edx
          Mov Eax, Sav + 8
          Div B + 12
          Mov Eax, Sav + 12
          Div B + 12
          Mov sesi, Ecx
          Mov sedi, Edx
          Push Eax
          .If Base == 16
            Push Offset FmtH
          .Else
            Push Offset FmtA
          .EndIf
          Push Offset ConvI
          Call wsprintfA
          Add Esp, 12
          Invoke  lstrcat, Offset HRBuff, Offset ConvI
          Mov Edx, sedi
          Mov Ecx, sesi
          Jmp Loop1
        .EndIf
        .If Ecx > 0
          Invoke  lstrcat, Offset HRBuff, 0H
          Mov Ebx, Offset HRBuff
          Call Fixem
          Mov Byte Ptr Buffer, 2EH
          Invoke  lstrcpy, Offset Buffer + 1, Offset HRBuff
          Invoke  CopyMW, Offset PT, Offset R2, 4
          Call AsciiToBase
          Call BaseToAscii
          Invoke  CopyMW, Offset R2, Offset PT, 4
          .If sedi > 0
            Add R + 28, 1
          .EndIf
        .EndIf
DivRet: Pop Ecx
        Ret
;-------------------------------------------
DivMW EndP
;
;
; _________________________________________
;|                                         |
;| Computes X to the Nth power integers    |
;| only.                                   |
;|_________________________________________|
;
PowerN Proc
;-------------------------------------------
        Invoke  CLRMW, Offset A, 16
        Invoke  CLRMW, Offset R + 16, 4
        MOVmd B + 12, PT + 12
        MOVmd R3 + 12, 1
        Mov Ecx, R + 12
Power:  Invoke  CopyMW, Offset A, Offset R3, 4
        Call MulMW
        Loop Power
        Invoke  CopyMW, Offset R, Offset R3, 4
        Call BaseToAscii
        Ret
;-------------------------------------------
PowerN EndP
;
;
; _________________________________________
;|                                         |
;|       Computes 2 to the Nth power       |
;|_________________________________________|
;
TwoX Proc
;-------------------------------------------
        Fldcw CWNoRound
        Fld St(0)                       ; Duplicate tos.
        Fld St(0)
        Frndint                             ; Compute integer portion.
        Fxch                                ; Swap whole and int values.
        Fsub St(0), St(1)                ; Compute fractional part.
        F2xm1                               ; Compute 2**frac(x)-1.
        Fld1                                ; Load 1
        Fadd                                ; Compute 2**frac(x).
        Fxch                                ; Get integer portion.
        Fld1                                ; Compute 1*2**int(x).
        Fscale
        Fstp St(1)                       ; Remove st(1) (which is 1).
        Fmul                                ; Compute 2**int(x) * 2**frac(x).
        Fldcw CWRound                     ; Restore rounding mode.
        Fld St(0)
        Fstp RNum10
        Ret
;-------------------------------------------
TwoX EndP
;
;
; _________________________________________
;|                                         |
;|      Computes 10 to the Nth power.      |
;|_________________________________________|
;
TenX Proc
;-------------------------------------------
        Fldl2t                              ; Put lg(10) onto the stack
        Fmul                                ; Compute x*lg(10)
        Call TwoX                        ; Compute 2**(x * lg(10)).
        Ret
;-------------------------------------------
TenX EndP
;
;
; _________________________________________
;|                                         |
;|       Computes e to the Nth power       |
;|_________________________________________|
;
ExpX Proc
;-------------------------------------------;
        Fldl2e                              ; Put lg(e) onto the stack.
        Fmul                                ; Compute x*lg(e).
        Call TwoX                        ; Compute 2**(x * lg(e)).
        Ret
;-------------------------------------------
ExpX EndP
;
;
; _________________________________________
;|                                         |
;| Rounds and removes excess zeros after   |
;| Mul, Div or floating point operations.  |
;|_________________________________________|
;
Fixem Proc
;-------------------------------------------
        Mov Edx, Ebx
        Inc Edx
        Push Ebx
        Invoke  CompareString, LOCALE_USER_DEFAULT, NORM_IGNORECASE, Edx, 9, Offset Zeros, 9
        Pop Ebx
        .If Eax == 2 && !RPress             ; 2 = match, so remove excess zeros
          Mov Byte Ptr [Ebx], 0         ; Terminate string
        .EndIf
        Cmp float, 1
        Je Pass
        Mov Pos, 0
        Push Ebx
        Invoke  lstrlen, Ebx
        Pop Ebx
        Mov Ecx, Eax
        Xor Edx, Edx
        .While (Ecx)
          .If Byte Ptr [Ebx] == 30H
            .If Pos == 0
              Mov Edx, Ebx
              Or Pos, 1
            .EndIf
          .Else
            Xor Edx, Edx
          .EndIf
          Inc Ebx
          Dec Ecx
        .EndW
        .If Edx > 0
          Mov Byte Ptr [Edx], 0         ; Terminate string
        .EndIf
Pass:   Inc Ebx
        Push Ebx
        Invoke  lstrlen, Ebx
        Pop Ebx
        .If Eax == 0
          Jmp Exit
        .EndIf
        Mov Ecx, Eax
        Add Ebx, 1
        Sub Ecx, 1
        Mov cnt, Ebx
        Add cnt, 1                      ; '2' removes (7) 0's after ., '3' removes (8) 0's after .
        .While (Ecx)
          Push Ebx
          Push Ecx
          Invoke  CompareString, LOCALE_USER_DEFAULT, NORM_IGNORECASE, Ebx, 9, Offset Zeros, 9
          Pop Ecx
          Pop Ebx
          .If Eax == 2 && Ebx > cnt         ; 2 = match remove excess zeros
Again:      .If Byte Ptr [Ebx] - 1 == 30H
              Dec Ebx
              Jmp Again
            .EndIf
            Mov Byte Ptr [Ebx], 0       ; Terminate string
            .If Byte Ptr [Ebx] - 1 == 2EH
              Mov Byte Ptr [Ebx] - 1, 0   ; Terminate string
            .EndIf
            Jmp Exit
          .EndIf
          .If ((Byte Ptr [Ebx] - 1 != '9')\
              && (Byte Ptr [Ebx] + 0 == '9')\
              && (Byte Ptr [Ebx] + 1 == '9'))
            Inc Byte Ptr [Ebx] - 1        ; +1
            Mov Byte Ptr [Ebx], 0       ; Terminate string
            .Break                          ; Exit loop
          .EndIf
          Dec Ecx                       ; Continue
          Inc Ebx
        .EndW
Exit:   Ret
;-------------------------------------------
Fixem EndP
;
;
; _________________________________________
;|                                         |
;|       Used to convert the display       |
;|_________________________________________|
;
DsplyConv Proc
;-------------------------------------------
        .If float == 0
          Call BaseToAscii
          Jmp NoDec
        .EndIf
        Or cpy, 8
        Invoke  lstrcpy, Offset Buffer, Offset PLBuff
        Push Base
        MOVmd Base, PrevBase
        Call AsciiToBase
        Pop Base
        Call BaseToAscii
        Invoke  lstrcpy, Offset ConvO, Offset ConvI
        .If I != 1
;         I = 1 comes from display, I = 0 comes from convert base
          Invoke  lstrcpy, Offset PLBuff, Offset ConvI
        .EndIf
        Invoke  lstrlen, Offset PRBuff
        Cmp Eax, 0
        Je NoDec
        Invoke  lstrlen, Offset ConvI
        Invoke  lstrcat, Offset ConvO, Offset Period
        Invoke  lstrcpy, Offset Buffer, Offset PRBuff + 1
        Push Base
        MOVmd Base, PrevBase
        Call AsciiToBase
        Pop Base
        Call BaseToAscii
        Xor Ebx, Ebx
LoopA:  .If Byte Ptr PRBuff[Ebx + 1] == 30H
;         Insert proper number of zeros after the decimal place
          Invoke  lstrcat, Offset ConvO, Offset Zero
          Inc Ebx
          Jmp LoopA
        .EndIf
        Invoke  lstrcat, Offset ConvO, Offset ConvI
        .If I != 1
;         I = 1 comes from display, I = 0 comes from convert base
          Invoke  lstrcpy, Offset PRBuff, Offset Period
          Invoke  lstrcat, Offset PRBuff, Offset ConvI
        .EndIf
NoDec:  .If I != 1
;         I = 1 comes from display, I = 0 comes from convert base
          Invoke  SendMessage, hEdit, WM_SETTEXT, NULL, Offset ConvO
          Invoke  SendMessage, hEdit, EM_SETSEL, 33, 33
          Invoke  SetFocus, hWndMain
        .EndIf
        And sw2, 0
        And cpy, 0
        Ret
;-------------------------------------------
DsplyConv EndP
;
;
; _________________________________________
;|                                         |
;| Converts ascii string of Dec, Hex, Oct  |
;| or Bin to a REAL10 value.               |
;|_________________________________________|
;
AsciiToFloat Proc
;-------------------------------------------
        PushAD
        And Min, 0
        Invoke  lstrlen, Addr Buffer          ; Input
        Cmp Eax, 0
        Je GetOut
        Xor Ecx, Ecx
        Mov Edx, Offset Buffer
        .While (Eax)
          .If Byte Ptr [Edx] > 60H
            Sub Byte Ptr [Edx], 57H
          .ElseIf Byte Ptr [Edx] > 40H
            Sub Byte Ptr [Edx], 37H
          .ElseIf Byte Ptr [Edx] == 2EH
            Mov Byte Ptr [Edx], 2EH
          .ElseIf Byte Ptr [Edx] == 2DH
            Or Min, 1
          .Else
            Sub Byte Ptr [Edx], 30H
          .EndIf
          Inc Ecx
          Inc Edx
          Dec Eax
        .EndW
        .If Ecx == 0
          Inc Ecx
        .EndIf
        Mov Ebx, Offset Buffer            ; Ascii string
        Mov Esi, Ebx
        Add Esi, Ecx                    ; Set esi at the end of Buffer
        Dec Esi
        .If Min == 1
          Dec Ecx
          Inc Ebx
        .EndIf
        Finit
        Fldz                                ; Initialize ST(0) = 0
Loop1:  Xor Eax, Eax                    ; Set eax=0 for later
        Mov Al, Byte Ptr [Ebx]
        Inc Ebx
        Cmp Al, '.'
        Je Loop2                       ; Loop before the decimal point
        Mov Work, Eax                   ; Set Work to number for loading
        Fild Base                        ; Load base for adding next digit
        Fmulp St(1), St                   ; ST(1)=ST(1)*ST & pop ST(0)
        Fild Work                        ; Load Work integer to ST(0)
        Faddp St(1), St                   ; ST(1)=ST(1)+ST & pop ST(0)
        Loop Loop1                       ; Next part of loop
        Fldz                                ; Load a zero for decimal places
        Jmp NoMore                      ; No more characters
Loop2:  Fldz                                ; Load another zero for the decimal portion
Loop3:  Dec Ecx                         ; The actual loop after the decimal point
        Jz NoMore                      ; If out of characters or last one was a '.'
        Mov Al, Byte Ptr [Esi]           ; Get next character
        Dec Esi                         ; Now esi is used for an index
        Mov Work, Eax                    ; Store to Work
        Fild Work                        ; Load Work
        Faddp St(1), St                   ; Add new char to old value
        Fild Base                        ; Load base
        Fdivp St(1), St                   ; Divide by base to retain decimal
        Jmp Loop3
NoMore: Faddp St(1), St                   ; Add integer & decimal
        .If Min == 1
          Fchs
        .EndIf
        Fstp TByte Ptr [RNum10]           ; Store real
GetOut: PopAD
        Ret
;-------------------------------------------
AsciiToFloat EndP
;
;
; _________________________________________
;|                                         |
;| Converts a REAL10 value to a Dec, Hex,  |
;| Oct or Bin ascii string.                |
;|_________________________________________|
;
FloatToAscii Proc
;-------------------------------------------
        Invoke  CopyMW, Offset Sav, Offset R, 12
        Mov PLBuff, 0
        Mov PRBuff, 0
        Mov Esi, Offset PRBuff
        Mov Ebx, Edx
        Fldcw CWNoRound
        Fld TByte Ptr [Ebx]              ; Load number
        Fst Work
        And Work, 80000000H
        Cmp Work, 80000000H
        Jnz PlusNum
        Mov Work, 1
        Fchs                                ; Changes sign
PlusNum:
        Fld St(0)                       ; Duplicate
        Fistp QW
        Invoke  CLRMW, Offset R, 32
        MOVmd R + 8, DWord Ptr QW + 4
        MOVmd R + 12, DWord Ptr QW
        MOVmd R + 44, Work
        Mov sw3, 1
        Call BaseToAscii
        And sw3, 0
        Invoke  lstrcpy, Addr PLBuff, Addr ConvO
        Fild QW                          ; ST(0) : xxxxx,  ST(1) : xxxxx.yyyyy
        Fsubp St(1), St(0)                ; ST(0) = 0.yyyyy
        Fst Work
        Cmp Work, 0
        Jz Buildit                     ; No decimal
        Invoke  lstrlen, Addr PLBuff
        Mov Byte Ptr [Esi], 2EH
        Inc Esi
        Mov Dx, Sp                       ; Save stack pointer
        Xor Ecx, Ecx
        Mov Edi, Edx
CalcDec:
        Fild Base                        ; Base 10, 16, 8, 2
        Fmulp St(1), St(0)
        Fld St(0)                       ; Duplicate
        Call Extend
        Fist Work                        ; Looks good at this point first int after dec
        Fsubp St(1), St(0)
        Mov Eax, Work
        .If Eax == 19999999H
          Mov Ebx, Esp
          Jmp GetOut
        .EndIf
        .If Al > 9H
          Add Al, 37H                   ; Convert to hex ASCII
        .Else
          Add Al, 30H                   ; Convert to dec ASCII
        .EndIf
        Mov Byte Ptr [Esi], Al           ; Ascii output
        Inc Esi
        Inc Ecx
        Cmp Ecx, 19                     ;20, 12, 15
        Jnz CalcDec
        Mov Ebx, Esp
GetOut: Mov Edx, Edi
        Mov Sp, Dx                      ; Restore SP
        Mov Byte Ptr [Esi], 0H
Buildit:
        Invoke  lstrcpy, Addr ConvO, Addr PLBuff       ; Non decimal number
        Invoke  lstrcat, Addr ConvO, Addr PRBuff       ; Decimal number
        Fstp Work                        ; Get rid of ST(0)
        Cmp PRBuff, 0
        Je Exit
        Invoke  lstrlen, Offset PLBuff
        .If Eax > 18
          Invoke  lstrcpy, Addr ConvO, Addr ErrorMsg    ; Error
          Mov PLBuff, 0
          Mov PRBuff, 0
          Fldz
          Fstp RNum10
          Jmp Exit
        .EndIf
        Mov Ebx, Offset ConvO
        Mov Edx, Ebx
        Add Ebx, Eax
        .If RPress == 1
          Push Edx
          Invoke  lstrlen, Offset ConvO
          Pop Edx
          Add Edx, Eax
          .If Byte Ptr [Edx] - 1 != 39H
            Inc Byte Ptr [Edx] - 1        ; +1
          .EndIf
        .EndIf
        .If (!NoFix)
          Call Fixem
        .EndIf
        Invoke  lstrlen, Offset PLBuff
        Mov Ebx, Eax
        Inc Ebx
        Invoke  lstrcpyn, Addr PLBuff, Addr ConvO, Ebx  ; nonDecimal number
        Dec Ebx
        Invoke  lstrcpy, Addr PRBuff, Addr ConvO[Ebx]   ; Decimal number
Exit:   Invoke  CopyMW, Offset R, Offset Sav, 12
        MOVmd FPLZ, R + 40
        Ret
;-------------------------------------------
FloatToAscii EndP
;
;
Extend Proc
;-------------------------------------------;
        Fild Base                        ; Base 16, 10, 8, 2
        Fmulp St(1), St(0)
        Fistp w1
        Mov Eax, w1
        Xor Edx, Edx
        Div Base                        ; Base 16, 10, 8, 2
        Mov w1, Eax
        Fild w1
        Ret
;-------------------------------------------
Extend EndP
;
;
HyperLinkWndProc Proc HWnd:DWord,
                      uMsg:DWord,
                      wParam:DWord,
                      lParam:DWord
;---------------------------------------
        Local tmpFont:LOGFONT
        Local rect:RECT
        Local point:POINT
;
        Mov Eax, uMsg
        .If Eax == WM_NCHITTEST
          Mov Eax, 1                ; We want to handle the non client hit test so we return true or 1
          Ret
        .ElseIf Eax == WM_CTLCOLORSTATIC
          Push Ebx
          Push Edx
          Invoke  SendMessage, HWnd, WM_GETFONT, 0, 0
          Mov Edx, Eax
          Invoke  GetObject, Edx, SizeOf LOGFONT, Addr tmpFont
          Mov tmpFont.lfUnderline, TRUE
          Invoke  CreateFontIndirect, Addr tmpFont
          Mov Ebx, Eax
          Invoke  SelectObject, wParam, Ebx
          .If hover == FALSE
            Invoke  SetTextColor, wParam, Blue
          .Else
            Invoke  SetTextColor, wParam, Red
          .EndIf
          Invoke  GetSysColor, COLOR_MENU
          Invoke  SetBkColor, wParam, Eax
          Invoke  DeleteObject, Ebx
          Invoke  GetStockObject, HOLLOW_BRUSH
          Pop Edx
          Pop Ebx
          Ret
        .ElseIf Eax == WM_MOUSEMOVE
          Invoke  GetParent, HWnd
          Push Ebx
          Mov Ebx, Eax
          Invoke  GetActiveWindow
          .If Eax == Ebx
            Invoke  GetCursorPos, Addr point
            Invoke  GetWindowRect, HWnd, Addr rect
            Invoke  PtInRect, Addr rect, point.x, point.y
            .If Eax
              Invoke  GetCapture
              .If !Eax
                Invoke  SetCapture, HWnd
                Mov hover, TRUE
                Invoke  InvalidateRect, HWnd, FALSE, FALSE
                Invoke  SetCursor, hFinger
              .EndIf
            .Else
              Invoke  GetCapture
              .If Eax
                Invoke  ReleaseCapture
                Mov hover, FALSE
                Invoke  InvalidateRect, HWnd, FALSE, FALSE
              .EndIf
            .EndIf
          .EndIf
          Pop Ebx
          Xor Eax, Eax
          Ret
        .ElseIf Eax == WM_LBUTTONDOWN
          Invoke  GetWindowText, HWnd, Offset buff, SizeOf buff ; Change this for using a preset url
          Invoke  ShellExecute, NULL, Offset szOpen, Offset buff, NULL, NULL, SW_MAXIMIZE   ; Change this to represent your preset url
          Mov hover, FALSE
          Invoke  InvalidateRect, HWnd, FALSE, FALSE
          Invoke  SendMessage, HWnd, WM_GETFONT, 0, 0           ; Get the defualt system font
          Mov Edx, Eax                                      ; Store result
          Invoke  GetObject, Edx, SizeOf LOGFONT, Addr tmpFont  ; Get our font into a logfont structure
          Mov tmpFont.lfUnderline, TRUE                     ; Under line the link
          Invoke  CreateFontIndirect, Addr tmpFont              ; Create the new font
          Mov Ebx, Eax                                      ; We need the return to free the memory later
          Invoke  SelectObject, wParam, Ebx                     ; Select our control
          Invoke  SetTextColor, wParam, Blue                    ; Change this to change the color of the link
          Xor Eax, Eax                                      ; No errors
          Ret                                                   ; Return
        .EndIf
        Invoke  CallWindowProc, orgStatic, HWnd, uMsg, wParam, lParam   ;Passes message information to the next stop
        Ret                                                 ; Return
;---------------------------------------
HyperLinkWndProc EndP
;
;
AboutDlgProc Proc hwnd:HWND, iMsg:DWord, wParam:WPARAM, lParam:LPARAM
;---------------------------------------
        Mov Eax, iMsg
        .If Eax == WM_INITDIALOG
          Invoke  GetDlgItem, hwnd, IDC_URL
          Invoke  SetWindowLong, Eax, GWL_WNDPROC, Addr HyperLinkWndProc
          Mov orgStatic, Eax
          Mov hFinger, Eax
          Xor Eax, Eax
          Ret
        .ElseIf Eax == WM_CTLCOLORSTATIC
          Invoke  SendMessage, lParam, iMsg, wParam, lParam
          Ret
        .ElseIf Eax == WM_CLOSE
          Invoke  EndDialog, hwnd, NULL
        .ElseIf Eax == WM_COMMAND
          Push Edx
          Mov Eax, wParam
          Mov Edx, Eax
          Shr Edx, 16
          .If Eax == IDC_EXIT
            Invoke  SendMessage, hwnd, WM_CLOSE, NULL, NULL
            Invoke  EndDialog, hwnd, NULL
          .EndIf
          Pop Edx
        .Else
          Mov Eax, FALSE
          Ret
        .EndIf
        Mov Eax, TRUE
        Ret
;---------------------------------------
AboutDlgProc EndP


        End     start
