;EasyCodeName=GeneSys,1
;
Title	GeneSys Editor+, 1.5.0
; ___________________________________________________
;|                                                   |
;| GeneSys Editor+, 1.5.0              Gene Brennick |
;| pbrennick@verizon.net    http://www.pbrennick.com |
;|___________________________________________________|
;|                                                   |
;| Version key is as follows, GeneSys Editor+ a.b.c  |
;|           a:  a major change to the GUI           |
;|           b:  functions added and/or changed      |
;|           c:  bug fixes                           |
;|                                                   |
;| Version History:                                  |
;| December 28, 2004  Version Upgrade.  Repair Paste |
;|                    fuction to strip any intro-    |
;|                    duced character formatting.    |
;|                    Clean up of the Print funtion. |
;|                                                   |
;| September 23, 2003 Reworked and cleaned up the    |
;|                    code to make it more readable. |
;|                                                   |
;| February 12, 2002  Major rewrite and first        |
;|                    release of the software        |
;|                    Version tracking starts        |
;|                    from this point, on.           |
;|                                                   |
;| This nice little editor is used to create Tab     |
;| Delimited text files suitable for assemblers and  |
;| compilers.  It can be used to create/modify very  |
;| large documents making it a powerful editor.      |
;|                                     Editor's Note |
;|___________________________________________________|
;
; Macro Section
;---------------------------------------;
MsgBox Macro Resource:req, Title: = < ERROR > , Flags: = < MB_OK Or MB_ICONEXCLAMATION >
        Mov Eax, Resource
        Lea Ebx, Title
        Mov Ecx, Flags
        Call ErrorMsg
        EndM
;
MOVmw   Macro Var1, Var2                ; Macro
        PushAD                          ; Save flags
        Lea Esi, Var2                  ; Get passed argument #1
        Lea Edi, Var1                  ; Get passed argument #2
        REPEAT  2                       ; Repeat twice, as a subroutine
        Mov Al, [Esi]                  ; Get byte value of word data
        Mov [Edi], Al                  ; Store byte value of word data
        Inc Esi                        ; Update the source pointer
        Inc Edi                        ; Update the destination pointer
        EndM                            ; Macro exit of repeats
        PopAD                           ; Restore Flags
        EndM                            ; Macro exit
;
EditMsg Macro msg:req, wparam:=<0>, lparam:=<0>	; Macro
        inv  SendMessage, hREd, MSG, WPARAM, LPARAM ; Send message to edit control
        EndM                            ; Macro exit
;
MOVmd   Macro Var1, Var2
        Push Var2
        Pop Var1
        EndM
;
.Const
;---------------------------------------;
IDC_URL             Equ 9               ;
IDC_EXIT            Equ 3002            ;
TM_PLAINTEXT		Equ 1               ;
inv                 Equ Invoke          ; The finger saver!!
IDB_TBRBMP          Equ 150             ; Toolbar bitmap
IDR_ACCEL           Equ 200             ; Accelerator Table
;
;Help Stuff
;---------------------------------------;
IDC_SHORTS          Equ 3003            ; Shortcuts Button
IDC_REPORT          Equ 3004            ; Error Reporting Button
IDC_NOTES           Equ 3005            ; Notes Button
IDC_ABOUT           Equ 3006            ; About Button
;
; Used by Find and/or Replace
;---------------------------------------;
IDD_FINDDLG         Equ 2000            ; Dialog Box
IDD_ASCII           Equ 2020            ; Dialog id of key ascii dialog
IDC_FINDTEXT        Equ 2001            ; Edit Box
IDC_BTN_REPLACE     Equ 2007            ; Button
IDC_REPLACETEXT     Equ 2002            ; Edit Box
IDC_REPLACESTATIC   Equ 2009            ; Text Box
IDC_BTN_REPLACEALL  Equ 2008            ; Button
IDC_CHK_WHOLEWORD   Equ 2004            ; Checkbox
IDC_CHK_MATCHCASE   Equ 2003            ; Checkbox
IDC_RBN_DOWN        Equ 2005            ; Radio Button
IDC_RBN_UP          Equ 2006            ; Radio Button
;
; Used by the Editor
;---------------------------------------;
IDD_DLG             Equ 1000            ; Application GUI
IDC_SBR             Equ 1003            ; Statusbar Window
IDC_TBR             Equ 1001            ; Toolbar Window
IDC_RED             Equ 1002            ; Edit Window
IDC_OK              Equ 123             ; 'Okay' Pushbutton
IDC_CANCEL          Equ 124             ; 'Cancel' Pushbutton
IDD_LINENUMBER      Equ 125             ; 'Goto Line' Dialog box
IDC_LINENUMBER      Equ 126             ; 'Goto Line' Edit Control
;
; Used by the Menu
;---------------------------------------;
IDM_NEW             Equ 10001           ; New
IDM_OPEN            Equ 10002           ; Open
IDM_SAVE            Equ 10003           ; Save
IDM_SAVEAS          Equ 10004           ; Save As
IDM_PRINT           Equ 10005           ; Print
IDM_PSETUP          Equ 10120           ; Page Setup
IDM_EXIT            Equ 10006           ; Exit
IDM_UNDO            Equ 10101           ; Undo
IDM_REDO            Equ 10102           ; Redo
IDM_DELETE          Equ 10103           ; Delete
IDM_CUT             Equ 10104           ; Cut
IDM_COPY            Equ 10105           ; Copy
IDM_PASTE           Equ 10106           ; Paste
IDM_SELECTALL       Equ 10107           ; Select All
IDM_FIND            Equ 10108           ; Find
IDM_FINDNEXT        Equ 10110           ; Find Next
IDM_FINDPREV        Equ 10111           ; Find Previous
IDM_REPLACE         Equ 10109           ; Replace
IDM_WWRAP           Equ 10112           ; WordWrap
IDM_SETFGCOLOR      Equ 10113           ; Set Foreground Color
IDM_SETBGCOLOR      Equ 10114           ; Set Background Color
IDM_FLIPCASE        Equ 10115           ; Flip Case
IDM_TOLOWERCASE     Equ 10116           ; Convert to Lowercase
IDM_TOUPPERCASE     Equ 10117           ; Convert to Uppercase
IDM_TOOLBAR         Equ 10008           ; Toolbar On/Off
IDM_STATUSBAR       Equ 10009           ; Statusbar On/Off
IDM_FONT            Equ 10007           ; Select Font
IDM_HELP_ABOUT      Equ 10201           ; About
IDM_ASCII           Equ 10202           ; Key Code To ASCII Converter
IDM_GOTOLINE        Equ 10118           ; Goto Line
IDM_MENU            Equ 10000           ; Menu
IDM_HELP            Equ 10119           ; Help System
IDM_BUGS            Equ 10121           ; OK, What's Your Sob Story...Sheesh!
IDM_HOMEPAGE        Equ 10122           ; Load My WebPage
;
; Structure for ToolBar buttons
;---------------------------------------
tbrbtns TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <6, IDM_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <7, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <8, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <0, IDM_CUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <1, IDM_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <2, IDM_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <3, IDM_UNDO, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <4, IDM_REDO, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <5, IDM_DELETE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <12, IDM_FIND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <13, IDM_REPLACE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
        TBBUTTON    <14, IDM_PRINT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0>
        TBBUTTON    <0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0>
ntbrbtns            Equ 18              ; Number of buttons and separators in the toolbar
;
.Data
;---------------------------------------;
AboutName       DB  "AboutDialog", 0    ; About Box Name
szOpen          DB  "open", 0           ; Action to perform
RichEditDLL     DB  'riched20.dll', 0   ; RichEdit DLL filename
ClassName       DB  'DLGCLASS', 0       ; Classname of this application
Libname         DB  'Splash.dll', 0     ; Startup Screen -> Splash.dll
AppName         DB  'GeneSys Editor', 0 ; Name of this application
Dummy           DB  256 Dup(0)          ; Path and FileName, if any, from commandline
Ending1         DB  ' *]', 0            ; One of two possible Title Bar suffix
Ending2         DB  ']', 0              ; One of two possible Title Bar suffix
Prefix          DB  ' - [', 0           ; End of the Constant prefix
fr              DD  0                   ; Find/Replace flags
;---------------------------------------;
; Prepare to open the file specified on ;
; the commandline by setting the        ;
; following flag.                       ;
;---------------------------------------;
bypass          DB  0                   ; Flag used to bypass the 'Open File' dialog box
tempword        DD  0                   ; Used to save new line number used by Edit, Goto Line
Replace         DB  'Replace ..', 0     ; Label
szError1        DB  'The RICHED20.DLL was not found!', 0    ; Error Message
OpenFileFail    DB  'Cannot open the file', 0               ; Error Message
SaveFileFail    DB  'Cannot save the file', 0               ; Error Message
cantfind        DB  'Sorry, cannot find that file.', 0      ; Error Message
WannaSave       DB  'Want to save changes to', 0DH, 0       ; User prompt
NewFile         DB  '(Untitled)', 0     ; Default label
PathName        DB  'Untitled', 248 Dup(0)  ; Path and FileName defaults to 'Untitled'
szNULL          DB  0                   ; Null value
command         DB  "open", 0
whoami          DB  "mailto:pbrennick@verizon.net", 0
browser         DB  "c:\Program Files\Internet Explorer\iexplore.exe", 0
url             DB  "http://www.pbrennick.com", 0
findbuff        DB  256 Dup(0)          ; Buffer for text to find
replacebuff     DB  256 Dup(0)          ; Buffer for text to replace
szFlipCase      DB  255 Dup(0)          ; Buffer for flipping lower case to upper and vice-versa
szTitle         DB  256 Dup(0)          ; Title Bar message is built here
Flag            DB  0                   ; Flag used by the 'Change Case' routine
FindEnd         DB  'There Are No More Matches.'            ; Message
                DB  0DH, 0AH                                ; CRLF
                DB  'Would You Like To Restart From The'    ; User Prompt
TopBot          DB  ' Top? '            ; End of User Prompt
                DB  0                   ; ASCIIZ
Top             DB  ' Top? '            ; User Prompt modifier
Bot             DB  ' Bot? '            ; User Prompt modifier
szFR            DB  'Find And Replace', 0                   ; Dialog box title
hAscii          DD  0
EditPT          DB  'EDIT', 0
hAsciibox       DD  0
lpAsciibox      DD  0
Misc            DB  40 Dup (?)
w4              DD  0
;
;Help Stuff
;---------------------------------------;
SpecialDLGName  DB  'SpecialDLG', 0     ; Special Help/Information Dialog Box
szButton3       DB  '  A - Select all the text.', 13, 10
                DB  '  B - Select Background color.', 13, 10
                DB  '  C - Copy text to the clipboard.', 13, 10
                DB  '  F - Find text.', 13, 10
                DB  '  G - Goto Line.', 13, 10
                DB  '  K - Flip Case of selected text.', 13, 10
                DB  '  L - Convert selected text to lowercase.', 13, 10
                DB  '  N - New Document.', 13, 10
                DB  '  O - Open file using a dialog box.', 13, 10
                DB  '  P - Print.', 13, 10
                DB  '  R - Replace selected text.', 13, 10
                DB  '  S - Save the current document.', 13, 10
                DB  '  T - Select Text color.', 13, 10
                DB  '  U - Convert selected text to uppercase.', 13, 10
                DB  '  V - Copy text from the clipboard.', 13, 10
                DB  '  W - WordWrap toggle, click on, click off.', 13, 10
                DB  '  X - Cut text from document to clipboard.', 13, 10
                DB  '  Y - Redo.  Undo an undo.', 13, 10
                DB  '  Z - Undo last keyboard/mouse action.', 13, 10, 13, 10
                DB  'DEL - Delete selected text from document.', 13, 10


                DB  'ESC - Close dialog box.', 13, 10, 13, 10
                DB  ' F1 - Show Help and information screens.', 13, 10
                DB  ' F3 - Find Next.', 13, 10
                DB  ' F3 - +CTRL, Find previous match.', 13, 10
                DB  ' F4 - +ALT, Exit this program.', 13, 10, 0
szButton4       DB  'If you encounter an error, please send an e-mail to me at the address listed at the '
                DB  'bottom (and top) of this help box and it will be dealt with promptly. '
                DB  'Enjoy and thank you for your help.', 13, 10, 13, 10
                DB  'pbrennick@verizon.net', 0
szButton5       DB  'The GeneSys Editor+ can be used to create Tab Delimited text files suitable '
                DB  'for streaming into assemblers and compilers, etc.  It can create and/or modify '
                DB  'very large documents making it a powerful editor (not just a toy, its '
                DB  'small footprint can be VERY misleading).  All that and it is FREE!!  '
                DB  13, 10, 13, 10, 'As this program develops, more and more ideas occur to me or are '
                DB  'suggested to me by my beta testers.  Please keep those ideas coming, I need '
                DB  'that sort of help.  All ideas have value and will be saved for consideration.  '
                DB  'Those that do not appear in this project will undoubtedly appear in the next.'
                DB  13, 10, 13, 10, 'Paul E. Brennick, Coder', 13, 10, 'Ingrid Brennick, Associate Designer', 0
szButton6       DB  'Change Logs:', 13, 10
                DB  '----------------------', 13, 10
                DB  13, 10, 13, 10, 13, 10
                DB  13, 10, 13, 10, 13, 10, 13, 10, 13, 10
                DB  'Paul E. Brennick', 0
;
; 'Replaced Phrase' counter messaging system
;---------------------------------------;
HowMany         DD  0                   ; Replace function tracks the count here
CMessagePrefix  DB  ' Replaced ', 0      ; Message prefix
HowManyASCIIZ   DB  10 Dup (48)         ; ASCIIZ value of 'HowMany'
CMessageSuffix  DB  ' occurrence(s)', 0 ; Message suffix
ShowMessage     DB  64 Dup (0)          ; 'Replaced Phrase' message is built and stored here
;
; Font stuff
;---------------------------------------;
FontName        DB  'Courier', 25 Dup(0)    ; 32 bytes max (including ASCIIZ terminator)
FontHeight      DD  - 13                 ; -12=9pt., -13=10pt., -15=11pt., etc.
FontWeight      DD  400                 ; 400=normal, 700=bold
PointSize       DD  100                 ; PointSize*10, actually
BgColor         DD  0B0FFFFH            ; Very light yellow [format is reversed in memory]
rgb             DD  800000H             ; Text Color, Navy blue [format is reversed in memory]
SetBgColor      DB  0                   ; Request 'Set BGColor' flag
CustClrs        DD  16  Dup(?)          ; Custom Colors storage buffer, not really used yet
FirstRun        DB  0                   ; First run of this program?
Modified        DB  0                   ; Document 'is modified' flag
WWrap           DD  1                   ; WordWrap toggle flag
;
; Row/Column Display
;---------------------------------------;
BinRow          DD  0                   ; Binary row value
BinRowTotal     DD  0                   ; Binary total amount of rows value
BinColumn       DD  0                   ; Binary column value
BinColumnTotal  DD  0                   ; Binary total amount of columns value
BinColOffset    DD  0                   ; Cursor position within the line
FileOff         DD  0                   ; Cursor position of line start - 1
ShowRow         DB  24 Dup(0)           ; Status Bar 'Row' message is built and stored here
ShowColumn      DB  24 Dup(0)           ; Status Bar 'Column' message is built and stored here
RowMsg          DB  ' Row:  ', 0        ; Data used to build message
OfMsg           DB  ' of ', 0           ; Data used to build message
Row             DB  6 Dup(0)            ; ASCII row value
RowTotal        DB  6 Dup(0)            ; ASCII total amount of rows value
ColumnMsg       DB  ' Col:  ', 0        ; Data used to build message
Column          DB  5 Dup(0)            ; ASCII column value
ColumnTotal     DB  5 Dup(0)            ; ASCII total amount of columns value
;
; Statusbar Banner Stuff
;---------------------------------------;
Minute          DD  0                   ; Current minute
Counter         DB  0                   ; Current message index pointer
Message1        DB  ' pbrennick@verizon.net', 0 ; Status Bar message
Message2        DB  ' File is modified.', 0     ; Status Bar message
Message3        DB  ' File is not modified.', 0 ; Status Bar message
Message4        DB  ' '                         ; Status Bar message
Stuffing        DB  128 Dup(0)          ; Message4 and Stuffing should not be separated!
DecValue        DB  10                  ; Base is 10
Delimit         DB  ', ', 0             ; Delimiter used in building Message 4
EndOfString     DB  ' Pt.', 0           ; Delimiter used in building Message 4
ASCIIPointSize  DB  4 Dup(0), 0         ; ASCII Pointsize is built and stored here
;
; Registry Stuff
;---------------------------------------;
szMRU_File1     DB  256 Dup(0)          ; First MRU file registration
szMRU_File2     DB  256 Dup(0)          ; Second MRU file registration
szMRU_File3     DB  256 Dup(0)          ; Third MRU file registration
szMRU_File4     DB  256 Dup(0)          ; Fourth MRU file registration
szMRU_File5     DB  256 Dup(0)          ; Fifth MRU file registration
MRUBufLen1      DWord SizeOf szMRU_File1 + 1    ; Size of first MRU file registration
MRUBufLen2      DWord SizeOf szMRU_File2 + 1    ; Size of second MRU file registration
MRUBufLen3      DWord SizeOf szMRU_File3 + 1    ; Size of third MRU file registration
MRUBufLen4      DWord SizeOf szMRU_File4 + 1    ; Size of fourth MRU file registration
MRUBufLen5      DWord SizeOf szMRU_File5 + 1    ; Size of fifth MRU file registration
szMRUMessage1   DB  'MRU_File1', 0      ; First MRU file Registry label
szMRUMessage2   DB  'MRU_File2', 0      ; Second MRU file Registry label
szMRUMessage3   DB  'MRU_File3', 0      ; Third MRU file Registry label
szMRUMessage4   DB  'MRU_File4', 0      ; Fourth MRU file Registry label
szMRUMessage5   DB  'MRU_File5', 0      ; Fifth MRU file Registry label
MRUDump         DB  256 Dup(0)          ; First MRU file dump
                DB  256 Dup (0)          ; Second MRU file dump
                DB  256 Dup (0)          ; Third MRU file dump
                DB  256 Dup (0)          ; Fourth MRU file dump
                DB  256 Dup (0)          ; Fifth MRU file dump
EndOfDump       DB  0                   ; End of dump flag
szMenuEntry     DB  256 Dup(0)          ; Pointer to menu entry
szStrLength     DD  0                   ; Amount of bytes to write for each MRU entry
hSubMenu        DD  0                   ; Handle of menu containing the MRU
itemcount       DD  0                   ; Amount of items in that subMenu
Block           DD  0                   ; Offset to MRU entries in MRUDump
isModified      DD  0                   ; Has the current file been modified?
amtAdded        DD  0                   ; Maximum amount of entries to be added to the subMenu
Partial         DD  0                   ; Amount of items to remove during MRU reset
MenuID          DD  0                   ; wParam menu selection
;
; More Registry Stuff
;---------------------------------------;
szFontName      DB  32 Dup(0)           ; FontName, loaded from Registry
szFontHeight    DD  0                   ; FontHeight, loaded from Registry
szFontWeight    DD  0                   ; Font Weight, loaded from Registry
szPointSize     DD  0                   ; Point Size, loaded from Registry
szBgColor       DD  0                   ; Background Color, loaded from Registry
szFgColor       DD  0                   ; Text Color, loaded from Registry
szKeyName       DB  'Software\Editor+\', 0  ; Name of Registry entry for this editor
szFontMessage   DB  'Character Font', 0 ; Title of Registry entry
FNBufferLength  DWord SizeOf szFontName + 1 ; Length of FontName string
szBGCMessage    DB  'Background Color', 0    ; Title of Registry entry
szFGCMessage    DB  'Text Color', 0     ; Title of Registry entry
szPointMessage  DB  'Point Size', 0     ; Title of Registry entry
szFHeightMsg    DB  'Font Height', 0    ; Title of Registry entry
szFWeightMsg    DB  'Font Weight', 0    ; Title of Registry entry
;
; Printer
;---------------------------------------;
mB              DD  0                   ; Bottom margin of printed page
mL              DD  0                   ; Left margin of printed page
mR              DD  0                   ; Right margin of printed page
mT              DD  0                   ; Top margin of printed page
RTwips1000      Real10  1.44            ; Twips constant
w1              DD  0                   ; Scratch variable used when calculating margins
pTitle          DB  'GeneSys Editor', 0 ; Document Title
Sel             DD  0                   ; Flags a 'Range' type print job, currently unused
xPerInch        DD  0                   ; Width of printable area
yPerInch        DD  0                   ; Height of printable area
;
; New Printer Stuff
;---------------------------------------
szSelect        DB  'Selected Text!', 0
szBuff          DB  256 Dup (?), 0
szWork          DB  256 Dup (?), 0
ExtType         DB  4 Dup (?), 0
BackGC          DD  00FFFFFFH           ; BackGround Color
TextC           DD  00808000H           ; Text Color
PrtHead         DD  1
PrtColor        DD  0
cnt             DD  0
RTF             DD  0
E1              Equ 1801
E2              Equ 1802
; Equates used by the Printer Routines
ERROR_NO_SELECTION  Equ 30012
;
.Data?
;---------------------------------------;
hover           BOOL    ?
hwndDlg         DD      ?
orgStatic       DD      ?
hFinger         DD      ?
buff            DB      256 Dup (?)
hRichEdDLL      DD      ?               ; Handle
hInstance       DD      ?               ; Handle
CommandLine     DD      ?               ; Pointer to the commandline ( stored in PSP)
hIcon           DD      ?               ; Handle
hAccel          DD      ?               ; Handle
hWnd            HWND    ?               ; Handle
hREd            HWND    ?               ; Handle
hMenu           DD      ?               ; Handle
hFind           HWND    ?               ; Handle
FileName        DB      MAX_PATH Dup(?) ; Buffer for Filename w/Path
fView           DD      ?               ; Amount of items used by GUI
TabSize         DD      ?               ; Store tabsize (will be set to 4)
hFont           DD      ?               ; Handle
fres            DD      ?               ; 'Resume' Flag, used to denote the continuation of a search
sbParts         DD      4 Dup(?)        ; Width of each of four parts of status bar
;
; Structures used by the Editor Routines
;---------------------------------------
cc      CHOOSECOLOR     <?>             ; Choose Color commdlg
charF   CHARFORMAT2     <?>             ; For EM_GETCHARFORMAT/EM_SETCHARFORMAT
cr      CHARRANGE       <?>             ; Character range
ft      FINDTEXTEX      <>              ; For EM_EXGETSEL/EM_EXSETSEL
lfnt    LOGFONT         <>              ; For CreateFontIndirect
sTime   SYSTEMTIME      <?>             ; For Current Date and Time
;
; Structures used by the Printer Routines
doci    DOCINFO         <?>             ; Docinfo (printing support)
fr_1    FORMATRANGE     <?>             ; For EM_FORMATRANGE
psd     PAGESETUPDLG    <?>             ; Page setup common dialog structure
pd      PRINTDLG        <?>             ; Print
rect_1  RECT            <?>             ; Rectangle
;
;
.Code
;---------------------------------------;
start:  inv GetModuleHandle, NULL      ; returns a module handle for this instance
        Mov hInstance, Eax             ; Save handle
        inv LoadLibrary, Addr Libname  ; Splash screen
        .If !Eax
          Jmp NoLib
        .EndIf
        inv FreeLibrary, Eax
NoLib:  inv GetCommandLine             ; Get offset pointer to commandline
        Mov CommandLine, Eax           ; Save it
        inv LoadLibrary, Offset RichEditDLL    ; Map RICHED20.DLL into the address space of this process
        Mov hRichEdDLL, Eax            ; Save the handle
        .If !Eax                        ; If fails...
          inv MessageBox, NULL, Addr szError1, Addr AppName, MB_OK Or MB_ICONERROR ; Report the error
          Jmp NoGo                     ; Exit the process, close the door behind you
        .EndIf                          ; End of conditional
        inv WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT  ; Display window and enter the message loop
        Push Eax                        ; Save exit value, 0==no errors, for instance
        inv FreeLibrary, hRichEdDLL    ; Free the RICHED20.DLL resource
        Pop Eax                        ; Restore exit value
NoGo:   inv ExitProcess, Eax           ; See ya!
;
;
WinMain Proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWord
;---------------------------------------;
        Local wc:WNDCLASSEX           ; This application's class, created below
        Local msg:MSG                 ; Windows messaging
        Local lpArg:DWord             ; Scratch variable
;
        Mov wc.cbSize, SizeOf WNDCLASSEX   ; Size of the class
        Mov wc.style, CS_HREDRAW Or CS_VREDRAW ; Declare some styles
        Mov wc.lpfnWndProc, Offset WndProc ; Points to the window procedure
        Mov wc.cbClsExtra, NULL        ; Specifies the number of extra bytes to allocate following the window-class structure
        Mov wc.cbWndExtra, DLGWINDOWEXTRA  ; Specifies the number of extra bytes to allocate following the window instance
        Push hInst                      ; Save handle to instance
        Pop wc.hInstance               ; Identifies the instance that the window procedure of this class is within
        Mov wc.hbrBackground, NULL     ; Identifies the class background brush
        Mov wc.lpszMenuName, IDM_MENU  ; If this member is NULL, the window belonging to this class has no default menu
        Mov wc.lpszClassName, Offset ClassName ; Specifies the window class name
        inv LoadIcon, NULL, IDI_APPLICATION    ; Get handle of the icon
        Mov hIcon, Eax                         ; Save the handle
        Mov wc.hIcon, Eax                      ; Store it in the class structure
        Mov wc.hIconSm, Eax                    ; Store the thumbnail's handle
        inv LoadCursor, NULL, IDC_ARROW        ; Get cursor
        Mov wc.hCursor, Eax                    ; Store it in the class structure
        inv RegisterClassEx, Addr wc           ; Register the class
        inv CreateDialogParam, hInstance, IDD_DLG, NULL, Offset WndProc, NULL  ; Create window
        Mov hWnd, Eax                          ; Save the handle to the window
        inv ShowWindow, hWnd, SW_SHOWNORMAL    ; Show the window
        inv UpdateWindow, hWnd                 ; Update [paint] the window's client area
;
;       Get any command line filename
;       --------------------------------
        inv PathGetArgs, CommandLine   ; Get command line, if it exists
        Mov lpArg, Eax                 ; Save the pointer to the command line
        Mov Esi, Eax                   ; Prepare for testing
        Lodsb                           ; Get a possible character into 'al'
        Cmp Al, 0                      ; No command line argument?
        Je noArgs                     ; Jump if no argument
        Cmp Al, 34                     ; Quotation mark?
        Jne J001                       ; Jump if no quotation mark
        inv PathUnquoteSpaces, lpArg   ; Parse the command line, remove chaff
        Mov lpArg, Eax                 ; Save the pointer to the command line
J001:   inv exist, lpArg               ; Valid path and/or filename?
        .If Eax == 1                    ; If true ...
          inv lstrcpy, Offset Dummy, lpArg ; Save filename/path from the commandline
          inv lstrcpy, Offset PathName, lpArg  ; Save filename/path from the commandline
          Mov bypass, 1                ; Open file later, when initialization is complete
        .Else                           ; If false ...
          inv MessageBox, hWnd, lpArg, Addr cantfind, MB_OK ; Bitch about it
        .EndIf                          ; End of conditional
noArgs: inv LoadMenu, hInstance, IDM_MENU  ; Menu ID
        Mov hMenu, Eax                 ; Save the handle
        inv SetMenu, hWnd, Eax         ; Add the Menu to the window
        inv GtFrmRegistry              ; Load settings from Registry
        inv ShowWindow, hWnd, SW_SHOWNORMAL    ; Set the window's show state
        inv UpdateWindow, hWnd         ; Send a WM_PAINT message directly to the window procedure
        inv LoadAccelerators, hInstance, IDR_ACCEL ; Load the accelerator key table
        Mov hAccel, Eax                ; Save handle to the list
        .While TRUE                     ; Parse the message buffer
          inv GetMessage, Addr msg, NULL, 0, 0 ; Check messages
          .Break .If !Eax               ; If no ...
          inv IsDialogMessage, hFind, Addr msg ; Dialog box message?
          .If !Eax                      ; If no ...
            inv TranslateAccelerator, hWnd, hAccel, Addr msg   ; Accelerator key?
            .If !Eax                    ; If no ...
              inv TranslateMessage, Addr msg   ; Translates virtual-key message into character message and place into the queue
              inv DispatchMessage, Addr msg    ; Dispatches message to the window procedure
            .EndIf                      ; End of conditional
          .EndIf                        ; End of conditional
          inv LoadMRUFiles             ; Load MRU files from Registry
          inv AppendToMenu             ; Store the MRU in the menu
          inv ShowPosition             ; Display cursor coordinates on the Status Bar
          inv EnableDisable            ; Control various buttons and menuitems
          inv QFour                    ; Display the Statusbar messaging system
        .EndW                           ; End of conditional
        Mov Eax, msg.wParam            ; Get message to pass as exit code
        Ret                             ; Bye
;---------------------------------------
WinMain EndP
;
;
WndProc Proc hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
;---------------------------------------;
        Local pt:POINT                ; Structure
        Local rect:RECT               ; Structure
        Local ht:DWord                ; Height of window
        Local hCtl:HWND               ; Temporary handle storage (shared)
        Local chrg:CHARRANGE          ; Structure
        Local cf:CHOOSEFONT           ; Structure
        Local buffer[256]:Byte        ; Buffer
;
        Mov Eax, uMsg                  ; Get message
        .If Eax == WM_INITDIALOG          ; If it is a request to initialize the window
          Push hWin                     ; Save handle
          Pop hWnd                     ; Restore the handle to a new variable
          .If fr == 0                   ; Definitely the first pass?
            Mov fr, FR_DOWN            ; Default searches to downwards
          .EndIf                        ; End of 'first pass' conditional
          Mov fView, 3                 ; Initialize the control flag
          Mov TabSize, 4               ; Set the tab size
;         Set the toolbar buttons
          inv GetDlgItem, hWin, IDC_TBR    ; Get handle of the toolbar
          inv DoToolBar, hInstance, Eax    ; Create the toolbar
;         Set FileName to NewFile
          inv lstrcpy, Offset FileName, Offset NewFile ; Set filename to 'UNTITLED'
          inv SetWinCaption            ; Display the filename as the caption
;         Get handle of RichEdit window and give it focus
          inv GetDlgItem, hWin, IDC_RED    ; Get handle for the edit control
          Mov hREd, Eax                ; Save the handle
          inv SendMessage, hREd, EM_SETTEXTMODE, 0, TM_PLAINTEXT
;         Set event mask
          inv SendMessage, hREd, EM_SETEVENTMASK, 0, ENM_SELCHANGE ; Set the event mask for the rich edit control
;         Set the text limit. The default is 64K
          inv SendMessage, hREd, EM_LIMITTEXT, -1, 0   ; Set maximum file size to the maximum memory available
;         Create font
          inv lstrcpy, Offset lfnt.lfFaceName, Offset FontName ; Get fontname
          Mov Eax, FontHeight          ; Get font height
          Mov lfnt.lfHeight, Eax       ; Store the font height in the logfont structure
          Mov Eax, FontWeight          ; Get font weight
          Mov lfnt.lfWeight, Eax       ; Store the font weight in the logfont structure
          inv CreateFontIndirect, Offset lfnt  ; Create the font
          Mov hFont, Eax               ; Store it
          inv ShowFont                 ; Update the Status Bar Messaging
          inv GtFrmRegistry            ; Load settings from Registry
          inv LoadMRUFiles             ; Load MRU from Registry
          Mov Eax, BgColor             ; Get BackGround Color
          Mov charF.crBackColor, Eax   ; Store it in the structure
          inv SendMessage, hREd, EM_SETBKGNDCOLOR, 0, Eax    ; Set background color
          Mov Byte Ptr FirstRun, 1     ; Used to suppress the dialog box
          Call SetColor                 ; Set ForeGround Color
          Mov Byte Ptr FirstRun, 0     ; Clear for normal operation henceforth
;         Set font & format
          inv SetFormat, hREd          ; Set tab stops, etc.
;         Initialize the RichEdit control
          inv SendMessage, hREd, EM_SETMODIFY, FALSE, 0    ; Set the document to 'not modified'
          inv SendMessage, hREd, EM_EMPTYUNDOBUFFER, 0, 0  ; Empty the undo buffer
          inv SetFocus, hREd                               ; Set focus to the richedit control
        .ElseIf Eax == WM_COMMAND                             ; If a command is waiting to be processed
;         Menu and toolbar has the same ID's
          Mov Eax, wParam              ; Get message
          And Eax, 0FFFFH              ; Just the LSWord
          .If Eax == IDM_NEW            ; New Document request?
            inv WantToSave             ; Check state of current document, if any
            .If !Eax                    ; If edit control is empty
              inv SetWindowText, hREd, Offset szNULL   ; Clear the current caption
              inv lstrcpy, Offset FileName, Offset NewFile ; Set filename to 'UNTITLED'
              Mov Modified, 0          ; Reset the 'document modified' flag
              Mov Flag, 0              ; Clear the 'Set Caption' flag
              inv SetWinCaption        ; Set the window caption
            .EndIf                      ; End of conditional
            inv SetFocus, hREd         ; Set focus to the edit control
;         If a file is selected from the MRU list
;         ------------------------------
          .ElseIf wParam > 1200 && wParam < 1206    ; Is selection from the MRU?
            Mov Eax, wParam            ; Get value
            Sub Eax, 1201              ; Get index from it
            Mov Block, 0               ; Start at the beginning
            .While Eax > 0              ; If still more to be parsed...
              Add Block, 256           ; Move to next entry
              Dec Eax                  ; Update the counter
            .EndW                       ; Continue parsing until done
            Mov Esi, Offset MRUDump    ; Point to the MRU database
            Add Esi, Block             ; Add the offset to correct filename
            Mov Edi, Offset PathName   ; Offset to PathName
transfer:   Mov Al, [Esi]              ; Get a filename character
            Mov [Edi], Al              ; Store it
            Inc Esi                    ; Update source pointer
            Inc Edi                    ; Update destination pointer
            Cmp Al, 0                   ; ASCIIZ?
            Jne transfer               ; Continue transfer until terminator is found
            inv WantToSave             ; Check for an opened, modified file
            .If !Eax                    ; If check performed successfully
              inv lstrcpy, Offset Dummy, Offset PathName   ; Save filename/path from the commandline
              inv LoadFile, Addr Dummy     ; Go open the file
              inv SetFocus, hREd       ; Set focus to the edit window
            .EndIf                      ; End of conditional
          .ElseIf Eax == IDM_OPEN         ; If File Open request?
            inv WantToSave             ; Check state of current document, if any
            .If !Eax                    ; If control is empty
              inv OpenEdit             ; Open a file
            .EndIf                      ; End of conditional
            inv SetFocus, hREd         ; Set focus to the edit control
          .ElseIf Eax == IDM_SAVE         ; If File Save request?
            inv SaveEdit               ; Save file
            inv SetFocus, hREd         ; Set focus to the edit window
          .ElseIf Eax == IDM_SAVEAS       ; If File Save As request?
            inv SaveEditAs             ; Save File As
            inv SetFocus, hREd         ; Set focus to the edit window
          .ElseIf Eax == IDM_GOTOLINE     ; Go To Line request?
            inv DialogBoxParam, hInstance, IDD_LINENUMBER, hWin, Offset DlgProc, NULL  ; Process the request
            Cmp Eax, IDCANCEL          ; Cancel?
            Je NoChange               ; Jump if cancelled
            Mov Eax, tempword          ; Get line number
            Dec Eax                    ; Zero base
            EditMsg EM_LINEINDEX, Eax, 0    ; Get character offset to that line
            EditMsg EM_SETSEL, Eax, Eax ; Move to that line
NoChange: .ElseIf Eax == IDM_HELP       ; Help, Information?
            inv DialogBoxParam, hInstance, Addr SpecialDLGName, 0, Addr SpecialProc, 0 ; Show Information Dialog Box
          .ElseIf Eax == IDM_BUGS       ; Bug Reports or just plain chit chat
            inv ShellExecute, NULL, Addr command, Addr whoami, NULL, NULL, SW_RESTORE
          .ElseIf Eax == IDM_HOMEPAGE   ; Check for updates
            inv ShellExecute, NULL, Addr command, Addr browser, Addr url, NULL, SW_RESTORE
          .ElseIf Eax == IDM_PRINT        ; Print Document request?
            Call PrintProc              ; Print the document
          .ElseIf Eax == IDM_PSETUP     ; Page Setup?
            Call DoPageSU               ; Do Page Setup
          .ElseIf Eax == IDM_EXIT         ; Quit?
            inv SendMessage, hWin, WM_CLOSE, 0, 0  ; Close the file
          .ElseIf Eax == IDM_UNDO         ; Undo?
            inv SendMessage, hREd, EM_UNDO, 0, 0   ; Undo the last action
          .ElseIf Eax == IDM_REDO         ; Redo?
            inv SendMessage, hREd, EM_REDO, 0, 0   ; Redo the last action
          .ElseIf Eax == IDM_DELETE       ; Delete text?
            inv SendMessage, hREd, EM_REPLACESEL, TRUE, 0  ; Delete the selected text
          .ElseIf Eax == IDM_CUT          ; Cut text?
            inv SendMessage, hREd, WM_CUT, 0, 0    ; Remove the selected text from the control and place it in the clipboard
          .ElseIf Eax == IDM_COPY         ; Copy text?
            inv SendMessage, hREd, WM_COPY, 0, 0   ; Copy selected text from the control to the clipboard
          .ElseIf Eax == IDM_PASTE        ; Select Paste?
            inv SendMessage, hREd, WM_PASTE, 0, 0  ; Paste the contents of the clipboard into the edit control
            inv SetFormat, hREd        ; Strip all formatting included in the Paste
          .ElseIf Eax == IDM_WWRAP      ; Word Wrap?
            Call WordWrap               ; Go toggle Word Wrap mode
          .ElseIf Eax == IDM_SETFGCOLOR ; Format, Text Color?
            Call SetColor               ; Go change text color
            inv SavToRegistry          ; Update the Registry
          .ElseIf Eax == IDM_SETBGCOLOR ; Format, Background Color?
            Mov SetBgColor, 1          ; Set flag to change background color
            Call SetColor               ; Go change background color
            Mov SetBgColor, 0          ; Clear the flag
            inv SavToRegistry          ; Update the Registry
          .ElseIf Eax == IDM_FLIPCASE   ; Flip Case?
            Mov Byte Ptr Flag, 3       ; Set the flag
            inv ChangeCase             ; Routine used to change case of a string
          .ElseIf Eax == IDM_TOUPPERCASE    ; Change to UpperCase?
            Mov Byte Ptr Flag, 2       ; Set the flag
            inv ChangeCase             ; Routine used to change case of a string
          .ElseIf Eax == IDM_TOLOWERCASE    ; Change to LowerCase?
            Mov Byte Ptr Flag, 1       ; Set the flag
            inv ChangeCase             ; Routine used to change case of a string
          .ElseIf Eax == IDM_SELECTALL    ; Select all text in the control
            Mov chrg.cpMin, 0          ; Text start
            Mov chrg.cpMax, -1         ; Text end
            inv SendMessage, hREd, EM_EXSETSEL, 0, Addr chrg   ; Select all the text
          .ElseIf Eax == IDM_FIND         ; Find Text?
            inv SendMessage, hREd, EM_EXGETSEL, 0, Offset cr   ; Get start and ending positions of highlighted text
            Mov Eax, cr.cpMax          ; Get end position
            Sub Eax, cr.cpMin          ; Minus the start position
            .If Eax                     ; Anything highlighted?
              .If Eax < 255             ; If yes and in range...
                inv SendMessage, hREd, EM_GETSELTEXT, 0, Addr findbuff ; Get selected text
              .EndIf                    ; End of conditional
            .EndIf                      ; End of conditional
            .If hFind == 0                ; If dialog box is not showing ...
              inv CreateDialogParam, hInstance, IDD_FINDDLG, hWin, Offset FindDlgProc, FALSE   ; Show it
            .Else                       ; If it is ...
              inv SetFocus, hFind      ; Set focus to it
            .EndIf                      ; End of conditional
          .ElseIf Eax == IDM_REPLACE      ; Replace Text?
            Xor Eax, Eax               ; Clear the counter
            Mov HowMany, Eax           ; Store the cleared value (zero the counter)
            inv SendMessage, hREd, EM_EXGETSEL, 0, Offset cr   ; Get start and ending positions of highlighted text
            Mov Eax, cr.cpMax          ; Get end position
            Sub Eax, cr.cpMin          ; Minus the start position
            .If Eax                     ; Anything highlighted?
              .If Eax < 255             ; If yes and in range...
                inv SendMessage, hREd, EM_GETSELTEXT, 0, Addr findbuff ; Get selected text
              .EndIf                    ; End of conditional
            .EndIf                      ; End of conditional
            .If hFind == 0                ; If dialog box is not showing ...
              inv CreateDialogParam, hInstance, IDD_FINDDLG, hWin, Addr FindDlgProc, TRUE  ; Show it
            .Else                       ; If it is...
              inv SetFocus, hFind      ; Set focus to it
            .EndIf                      ; End of conditional
          .ElseIf Eax == IDM_FINDNEXT     ; Find next occurrence?
            Mov Al, findbuff           ; Get first character in the buffer
            .If Al                      ; Valid?
              inv Find, FR_DOWN        ; Continue the search if it is valid
            .EndIf                      ; End of conditional
          .ElseIf Eax == IDM_FINDPREV     ; Find previous occurrence?
            Mov Al, findbuff           ; Get first character in the buffer
            .If Al                      ; Valid?
              inv Find, 0              ; Continue the search if it is valid
            .EndIf                      ; End of conditional
          .ElseIf Eax == IDM_TOOLBAR      ; View Toolbar?
            inv GetDlgItem, hWin, IDC_TBR  ; Get handle of the toolbar control
            Mov hCtl, Eax              ; Save the handle
            Xor fView, 1               ; Toolbar = 1
            Mov Eax, fView             ; Save it
            And Eax, 1                 ; Toolbar bit set?
            .If Eax                     ; If yes ...
              inv ShowWindow, hCtl, SW_SHOWNA  ; Show it
            .Else                       ; Or
              inv ShowWindow, hCtl, SW_HIDE    ; Hide it
            .EndIf                      ; End of conditional
            inv SendMessage, hWin, WM_SIZE, 0, 0   ; Size the control
          .ElseIf Eax == IDM_STATUSBAR    ; View Statusbar?
            inv GetDlgItem, hWin, IDC_SBR  ; Get handle of the Statusbar control
            Mov hCtl, Eax              ; Save the handle
            Xor fView, 2               ; Statusbar = 2
            Mov Eax, fView             ; Save it
            And Eax, 2                 ; Statusbar bit set?
            .If Eax                     ; If yes ...
              inv ShowWindow, hCtl, SW_SHOWNA  ; Show it
            .Else                       ; Or
              inv ShowWindow, hCtl, SW_HIDE    ; Hide it
            .EndIf                      ; End of conditional
            inv SendMessage, hWin, WM_SIZE, 0, 0   ; Tell the control to size itself
          .ElseIf Eax == IDM_FONT         ; Change Font?
            inv RtlZeroMemory, Addr cf, SizeOf cf  ; Clear the structure
            Mov cf.lStructSize, SizeOf cf  ; Store size of structure
            Mov Eax, hWin              ; Get application's handle
            Mov cf.hwndOwner, Eax      ; Store it in the structure
            Mov cf.lpLogFont, Offset lfnt  ; Store logfont pointer
            Mov cf.Flags, CF_SCREENFONTS Or CF_EFFECTS Or CF_INITTOLOGFONTSTRUCT   ; Set flags as masks
            Mov Eax, rgb               ; Get foreground color
            Mov cf.rgbColors, Eax      ; Store it in the structure
            inv ChooseFont, Addr cf    ; Display the Choose Font dialog box
            .If Eax                     ; If successful ...
              inv DeleteObject, hFont  ; Delete brush
              inv CreateFontIndirect, Offset lfnt  ; Create font
              Mov hFont, Eax           ; Store the font
              Mov Eax, cf.rgbColors    ; Get textcolor
              Mov rgb, Eax             ; Store it
              Mov Eax, cf.iPointSize   ; Get PointSize*10
              Mov PointSize, Eax       ; Save it
              inv ShowFont             ; Display it in the Statusbar
              inv SetFormat, hREd      ; Set tabstops, etc.
            .EndIf                      ; End of conditional
            inv SetFocus, hREd         ; Set focus to the edit window
          .ElseIf Eax == IDM_ASCII        ; Roxanne
        Push 0
        Push Offset AsciiDlg
        Push hWnd
        Push IDD_ASCII
        Push hInstance
        Call CreateDialogParam
        Mov hAscii, Eax
        inv CreateWindowEx, WS_EX_CLIENTEDGE, Addr EditPT, 0,
                WS_CHILD Or WS_VISIBLE Or ES_CENTER, 39, 32, 22, 20, hAscii, IDM_ASCII, hInstance, 0
        Mov hAsciibox, Eax
        inv SetFocus, Eax
        inv SetWindowLong, hAsciibox, GWL_WNDPROC, AsciiProc
        Mov lpAsciibox, Eax
          .ElseIf Eax == IDM_HELP_ABOUT   ; Help?
            inv CreateDialogParam, hInstance, Addr AboutName, hWnd, Offset AboutDlgProc, NULL
            Mov hwndDlg, Eax
            inv SetFocus, hREd         ; Set focus to the edit window
          .EndIf                        ; End of conditional
        .ElseIf Eax == WM_NOTIFY          ; Notify?
          Mov Edx, lParam              ; Get subcommand
          Mov Eax, (NMHDR Ptr [Edx]).code  ; Save it
          .If Eax == TTN_NEEDTEXT         ; Notification message used to retrieve text
;          Toolbar tooltip
            Mov Edx, (NMHDR Ptr [Edx]).idFrom  ; Save it
            inv LoadString, hInstance, Edx, Addr buffer, SizeOf buffer ; Get the message
            Lea Eax, buffer            ; Initialize the buffer pointer
            Mov Edx, lParam            ; Get subcommand
            Mov (TOOLTIPTEXT Ptr [Edx]).lpszText, Eax  ; Display tooltip
          .ElseIf wParam == IDC_RED       ; RichEdit Control?
;           Auto horizontal scroll text into view
            inv GetCaretPos, Addr pt   ; Store Caret Position
            inv SendMessage, hREd, EM_GETRECT, 0, Addr rect    ; Get window coordinates
            Mov Eax, rect.right        ; save the position of the right edge
            Sub Eax, pt.x              ; Minus the width of the control
            .If Eax < 20                  ; If less than 20 pixels
              Inc rect.left            ; Add one to the left edge value
              Inc rect.top             ; Add one to the top edge value
              Sub rect.right, 70       ; Subtract 70 from the right edge
              inv SendMessage, hREd, EM_SETRECT, 0, Addr rect  ; Set the window borders
              inv SendMessage, hREd, EM_SCROLLCARET, 0, 0  ; Scroll the caret onto the control
              Add rect.right, 70       ; Restore the right edge to what it was originally
              inv SendMessage, hREd, EM_SETRECT, 0, Addr rect  ; Set the window borders
            .EndIf                      ; End of conditional
          .EndIf                        ; End of conditional
        .ElseIf Eax == WM_SETFOCUS      ; Set focus request?
          inv SetFocus, hREd        ; Set focus to the edit control
        .ElseIf Eax == WM_SIZE          ; If the window has changed size ...
          Mov Eax, fView               ; Initialize the control flag
          And Eax, 1                   ; Toolbar = 1
          .If Eax                       ; If Toolbar ...
;           Resize toolbar
            inv GetDlgItem, hWin, IDC_TBR  ; Get handle of the Toolbar
            Mov hCtl, Eax              ; Save it
            inv MoveWindow, hCtl, 0, 0, 0, 0, TRUE ; Change the position and dimensions of the specified window
;           Get height of toolbar
            inv GetWindowRect, hCtl, Addr rect ; Get dimension of the Toolbar
            Mov Eax, rect.bottom       ; Get value of the bottom of the window
            Sub Eax, rect.top          ; Get value of the top of the window
          .EndIf                        ; End of conditional
          Push Eax                      ; Save mask value
          Mov Eax, fView               ; Get new mask value
          And Eax, 2                   ; Statusbar?
          .If Eax                       ; If yes
;           Resize and partition the Statusbar
            inv GetDlgItem, hWin, IDC_SBR    ; Get handle of the Statusbar
            Mov hCtl, Eax              ; Save handle of the Statusbar
            Mov Eax, rect.right        ; Right edge of control ...
            Sub Eax, rect.left         ; Minus the left edge equals width of Statusbar
            Shr Eax, 2                 ; /4 equals width of each partition
            Mov Ecx, Eax               ; Save partition width
            Mov sbParts, Eax           ; Set right edge of Partition #1
            Add Eax, Ecx               ; Get right edge of Partition #2
            Mov [sbParts + 4], Eax       ; Store it in the Partition table
            Add Eax, Ecx               ; Get right edge of Partition #3
            Mov [sbParts + 8], Eax       ; Store it in the Partition table
            Mov [sbParts + 12], -1       ; Partition #4 extends to the end
            inv SendMessage, hCtl, SB_SETPARTS, 4, Addr sbParts    ; Partition the Statusbar
            inv MoveWindow, hCtl, 0, 0, 0, 0, TRUE ; Display the Statusbar
;           Get height of the statusbar
            inv GetWindowRect, hCtl, Addr rect ; Get dimensions of the Statusbar
            Mov Eax, rect.bottom       ; Get value of the bottom of the Statusbar
            Sub Eax, rect.top          ; Minus the top
          .EndIf                        ; End of conditional
          Push Eax                      ; Save Statusbar height
;         Get size of windows client area
          inv GetClientRect, hWin, Addr rect   ; Get dimensions of the edit control
;         Subtract height of statusbar from bottom
          Pop Eax                      ; Restore Statusbar height
          Sub rect.bottom, Eax         ; Get bottom of the Edit Control
;         Add height of toolbar to top  ; Add height of the control
          Pop Eax                      ; Restore Toolbar height
          Add rect.top, Eax            ; Get top of the Edit Control
;         Get new height of RichEdit window
          Mov Eax, rect.bottom         ; Get value of the bottom of the Statusbar
          Sub Eax, rect.top            ; Minus the top
          Mov ht, Eax                  ; Save the height
;         Resize RichEdit window
          inv MoveWindow, hREd, 0, rect.top, rect.right, ht, TRUE  ; Change the position and dimensions of the specified window
        .ElseIf Eax == WM_CLOSE           ; Close?
          inv WantToSave               ; Check state of current document, if any
          .If !Eax                      ; If all is okay
            inv SavToRegistry          ; Store any changes in the Registry
            inv DestroyWindow, hWin    ; Close down the window
          .EndIf                        ; End of conditional
        .ElseIf Eax == WM_DESTROY         ; Destroy the window
          inv SavToRegistry            ; Store any changes in the Registry
          inv DeleteObject, hFont      ; Delete the font
          inv PostQuitMessage, NULL    ; Tell Windows that this thread has made a request to terminate (quit)
        .ElseIf Eax == WM_CONTEXTMENU     ; Notifies a window that the user clicked the right mouse button (right clicked) in the window.
          Mov Eax, wParam              ; Get message
          .If Eax == hREd                 ; If Edit Control
            Mov Eax, lParam            ; Get subcommand
            And Eax, 0FFFFH            ; Just the LSWord
            Mov pt.x, Eax              ; Save 'x' coordinate
            Mov Eax, lParam            ; Get subcommand
            Shr Eax, 16                ; Just the MSWord
            Mov pt.y, Eax              ; Save 'y' coordinate
            inv GetMenu, hWin          ; Get menu handle
            inv GetSubMenu, Eax, 1     ; Retrieves the handle of the drop-down menu or submenu activated by the specified menu item.
            inv TrackPopupMenu, Eax, TPM_LEFTALIGN Or TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWin, 0 ; Displays a shortcut menu at the specified location
            Xor Eax, Eax               ; Errorlevel==0
            Ret                         ; Return
          .EndIf                        ; End of conditional
        .Else                           ; Else ...
          .If bypass == 1               ; Is a file waiting to be opened?
            Mov bypass, 0              ; Clear the 'File Open' flag
            inv LoadFile, Addr Dummy   ; Go open the file
            inv SetFocus, hREd         ; Set focus to the edit window
          .EndIf                        ; End of conditional
          inv DefWindowProc, hWin, uMsg, wParam, lParam    ; Deletes a logical pen, brush, font, bitmap, region, or palette
          Ret                           ; Return to caller
        .EndIf                          ; End of conditional
        Xor Eax, Eax                   ; Errorlevel==0
        Ret                             ; Return to caller
;---------------------------------------;
WndProc EndP
;
;
StreamInProc Proc hFile:DWord, pBuffer:DWord, NumBytes:DWord, pBytesRead:DWord
;---------------------------------------;
        inv ReadFile, hFile, pBuffer, NumBytes, pBytesRead, 0  ; Read In the file
        Xor Eax, 1                     ; Set Errorlevel
        Ret                             ; Return
;---------------------------------------;
StreamInProc EndP
;
;
StreamOutProc Proc hFile:DWord, pBuffer:DWord, NumBytes:DWord, pBytesWritten:DWord
;---------------------------------------
        inv WriteFile, hFile, pBuffer, NumBytes, pBytesWritten, 0  ; Write In the file
        Xor Eax, 1                     ; Set Errorlevel
        Ret                             ; Return
;---------------------------------------;
StreamOutProc EndP
;
;
SetWinCaption Proc
;---------------------------------------
;       Build and display the Window's Caption
        inv RtlZeroMemory, Addr szTitle, SizeOf szTitle ; Clear the Title
        inv lstrcpy, Addr szTitle, Offset AppName  ; Start with the name of this application
        inv lstrcat, Addr szTitle, Offset Prefix   ; Add a hyphen and a left bracket
        inv lstrcat, Addr szTitle, Offset FileName ; Add the Filename w/Path
        .If Modified == 1                           ; If the document is modified...
          inv lstrcat, Addr szTitle, Offset Ending1 ; Add an asterisk and a right bracket
        .Else                                       ; Or...
          inv lstrcat, Addr szTitle, Offset Ending2 ; Add a right bracket
        .EndIf                                      ; End of conditional
        inv SetWindowText, hWnd, Addr szTitle      ; Display the message on the TitleBar
        Ret                             ; Return  to caller
;---------------------------------------;
SetWinCaption EndP
;
;
SaveFile Proc lpFileName:DWord
;---------------------------------------;
        Local hFile:DWord             ; Handle of curremt document
        Local editstream:EDITSTREAM   ; Contains information about a data stream used with a rich edit control
;
        inv CreateFile, lpFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0  ; Create the file context
        .If Eax != INVALID_HANDLE_VALUE ; If handle is valid
          Mov hFile, Eax               ; Save the handle
;         Stream the text to the file
          Mov editstream.dwCookie, Eax ; Store the handle
          Mov editstream.pfnCallback, Offset StreamOutProc
          inv SendMessage, hREd, EM_STREAMOUT, SF_TEXT, Addr editstream    ; Contains information about a data stream used with a rich edit control
          inv CloseHandle, hFile       ; Close the file
;         Set the modify state to false
          inv SendMessage, hREd, EM_SETMODIFY, FALSE, 0    ; Set document state to 'not modified'
          Mov Modified, 0              ; Reset the 'Document Modified' flag
          Mov Flag, 0                  ; Reset the Enable/Disable flag
          inv SetWinCaption            ; Show the Window's Caption
          Mov Eax, FALSE               ; Set Errorlevel
        .Else                           ; Or
          inv MessageBox, hWnd, Offset SaveFileFail, Offset AppName, MB_OK ; Bitch about the failed Save
          Mov Eax, TRUE                ; Set Errorlevel
        .EndIf                          ; End of conditional
        Ret                             ; Return  to caller
;---------------------------------------;
SaveFile EndP
;
;
SaveEditAs Proc
;---------------------------------------;
        Local ofn:OPENFILENAME        ; Structure
        Local buffer[MAX_PATH]:Byte   ; Temporary buffer
;
        inv RtlZeroMemory, Addr ofn, SizeOf ofn    ; Zero out the ofn structure
;       Setup the ofn struct
        Mov ofn.lStructSize, SizeOf ofn    ; Store size of structure
        Push hWnd                       ; Save handle of window
        Pop ofn.hwndOwner              ; Restore it into the structure
        Push hInstance                  ; Save instance of this application
        Pop ofn.hInstance              ; Restore it into the structure
        Mov ofn.lpstrFilter, NULL      ; Clear the filter mask
        Mov buffer[0], 0               ; Clear the buffer
        Lea Eax, buffer                ; Get location of the buffer
        Mov ofn.lpstrFile, Eax         ; Store location in the structure
        Mov ofn.nMaxFile, SizeOf buffer    ; Store buffer size in the structure
        Mov ofn.Flags, OFN_FILEMUSTEXIST Or OFN_HIDEREADONLY Or OFN_PATHMUSTEXIST Or OFN_OVERWRITEPROMPT   ; Store flags in the structure
        Mov ofn.lpstrDefExt, NULL      ; No default extension
        inv GetSaveFileName, Addr ofn  ; Show save as dialog box
        .If Eax                         ; If getting a name was successful ...
          inv SaveFile, Addr buffer    ; Save the file
          .If !Eax                      ; If successful ...
;           The file was saved
            Mov Modified, 0            ; Set file status as 'not modified'
            Mov Flag, 0                ; Clear the 'Set Caption' flag
            inv lstrcpy, Offset FileName, Addr buffer
            inv SetWinCaption          ; Update the caption
            Mov Eax, FALSE             ; Set Errorlevel
          .EndIf                        ; End of conditional
        .Else                           ; Or ...
          Mov Eax, TRUE                ; Set Errorlevel
        .EndIf                          ; End of conditional
        Ret                             ; Return
;---------------------------------------
SaveEditAs EndP
;
;
SaveEdit Proc
;---------------------------------------
        inv lstrcmp, Offset FileName, Addr NewFile ; Check if filename is (Untitled)
        .If Eax                             ; If the file has a name ...
          inv SaveFile, Offset FileName    ; Save the file using the existing name
        .Else                           ; Else ...
          inv SaveEditAs               ; Select a filename
        .EndIf                          ; End of conditional
        Ret                             ; Return
;---------------------------------------;
SaveEdit EndP
;
;
WantToSave Proc
;---------------------------------------;
        Local buffer[512]:Byte        ; Temporary buffer
        Local buffer1[2]:Byte         ; Temporary buffer
;
        inv SendMessage, hREd, EM_GETMODIFY, 0, 0  ; Get document state
        .If Eax                         ; If document has been modified
          inv lstrcpy, Addr buffer, Offset WannaSave   ; Build the user prompt
          inv lstrcat, Addr buffer, Offset FileName    ; Add filename to the user prompt
          Mov Ax, '?'                                  ; End it with a question mark
          Mov Word Ptr buffer1, Ax                     ; Store it
          inv lstrcat, Addr buffer, Addr buffer1       ; Combine buffers
          inv MessageBox, hWnd, Addr buffer, Offset AppName, MB_YESNOCANCEL Or MB_ICONQUESTION ; Beg the question
          .If Eax == IDYES                ; If the user says 'Yes' ...
            inv SaveEdit               ; Save the file
          .ElseIf Eax == IDNO             ; If the user says 'No'
            Mov Eax, FALSE             ; Set Errorlevel
          .Else                         ; else ...
            Mov Eax, TRUE              ; Set Errorlevel
          .EndIf                        ; End of conditional
        .EndIf                          ; End of conditional
        Ret                             ; Return
;---------------------------------------;
WantToSave EndP
;
;
LoadFile Proc lpFileName:DWord
;---------------------------------------;
        Local hFile:DWord             ; Handle of curremt document
        Local editstream:EDITSTREAM   ; Contains information about a data stream used with a rich edit control
        Local chrg:CHARRANGE          ; Structure
;
;       Open the file
        inv CreateFile, lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0   ; Create the file
        .If Eax != INVALID_HANDLE_VALUE   ; If handle is valid ...
          Mov hFile, Eax               ; Save it
          inv lstrcpy, Offset FileName, lpFileName ; Copy buffer to FileName
;         Stream the text into the richedit control
          Push hFile                    ; Save handle
          Pop editstream.dwCookie      ; Retrieve handle into the structure
          Mov editstream.pfnCallback, Offset StreamInProc  ; Store address of 'get data' routine in structure
          inv SendMessage, hREd, EM_STREAMIN, SF_TEXT, Addr editstream ; Load the file
          inv CloseHandle, hFile       ; Close the file
          inv SendMessage, hREd, EM_SETMODIFY, FALSE, 0    ; Set 'file modified' flag to 0
          Mov chrg.cpMin, 0             ; File start = 0
          Mov chrg.cpMax, 0             ; File ends  = 0
          inv SendMessage, hREd, EM_EXSETSEL, 0, Addr chrg ; Select all of the text in the control
          inv SetWinCaption            ; Display the Window's Caption
          Mov Eax, FALSE               ; Set errorlevel [to 'no errors'
          inv AppendToMenu             ; Add filename and path to the MRU
        .Else                           ; If handle is invalid
          inv MessageBox, hWnd, Offset OpenFileFail, Offset AppName, MB_OK Or MB_ICONERROR ; Display error message
          Mov Eax, TRUE                ; Set errorlevel
        .EndIf                          ; End of conditional
        Ret                             ; Bye
;---------------------------------------;
LoadFile EndP
;
;
OpenEdit Proc
;---------------------------------------;
        Local ofn:OPENFILENAME        ; Structure
        Local buffer[MAX_PATH]:Byte   ; Temporary buffer
;
        inv RtlZeroMemory, Addr ofn, SizeOf ofn    ; Zero out the ofn structure
;       Setup the ofn struct
        Mov ofn.lStructSize, SizeOf ofn    ; Store the size of the structure
        Push hWnd                       ; Save window handle
        Pop ofn.hwndOwner              ; Retrieve it into the structure
        Push hInstance                  ; Save instance of this application
        Pop ofn.hInstance              ; Retrieve it into the structure
        Mov ofn.lpstrFilter, NULL      ; Clear the filter mask
        Mov buffer[0], 0               ; Clear the buffer
        Lea Eax, buffer                ; Get location of the temporary buffer
        Mov ofn.lpstrFile, Eax         ; Store it in the structure
        Mov ofn.nMaxFile, SizeOf buffer    ; Store the size of the buffer
        Mov ofn.lpstrDefExt, NULL      ; No default extension
        Mov ofn.Flags, OFN_FILEMUSTEXIST Or OFN_HIDEREADONLY Or OFN_PATHMUSTEXIST  ; Set attribute masks
        inv GetOpenFileName, Addr ofn  ; Show the Open dialog
        .If Eax                         ; If filename is valid ...
          inv LoadFile, Addr buffer    ; Load the file
          Mov Modified, 0              ; Set file to 'not modified'
          Mov Flag, 0                  ; Clear the Caption flag
          inv lstrcpy, Offset PathName, Addr buffer    ; Get filename
          inv SetWinCaption            ; Add it to the caption
        .EndIf                          ; End of conditional
        Ret                             ; Return
;---------------------------------------;
OpenEdit EndP
;
;
; ______________________________________
;|                                      |
;| The Find Procedure uses:             |
;|      FR_DOWN         equ 00000001h   |
;|                                      |
;| The FindDlgProc Procedure uses:      |
;|      FR_DOWN         equ 00000001h   |
;|      FR_WHOLEWORD    equ 00000002h   |
;|      FR_MATCHCASE    equ 00000004h   |
;|______________________________________|
;|                                      |
;| These three constant type equates    |
;| are declared in the windows.inc file |
;| and are used as flag values by these |
;| two procedures to control search     |
;| parameters.  They operate on the bit |
;| level and strings are tested using   |
;| the AND instruction.                 |
;|                                      |
;|                        Editor's Note |
;|______________________________________|
;
Find Proc frType:DWord
;---------------------------------------;
        inv SendMessage, hREd, EM_EXGETSEL, 0, Offset ft.chrg  ; Get current selection
;       Setup find parameters in case of previous pass
        Mov Eax, fr                    ; Get direction flag
        And Eax, FR_DOWN                ; Test if direction is 'down'
        .If Eax                         ; If yes ...
          .If fres != -1                  ; 'Resume' Flag
            Inc ft.chrg.cpMin          ; Update the buffer pointer
          .EndIf                        ; End of conditional
          Mov ft.chrg.cpMax, -1        ; End of text in the control
        .Else                           ; Else
          Mov ft.chrg.cpMax, 0         ; 0 means control is empty
        .EndIf                          ; End of conditional
        Mov ft.lpstrText, Offset findbuff  ; Store address of text to find in the structure
Loop1:  inv SendMessage, hREd, EM_FINDTEXTEX, frType, Offset ft    ; Do the find
        Mov fres, Eax                  ; 'Resume' Flag
        .If Eax != -1                     ; If the search was successful ...
          inv SendMessage, hREd, EM_EXSETSEL, 0, Offset ft.chrgText    ; Mark the found text
        .Else                           ; Or ...
          Mov Eax, fr                  ; Get Find/Replace flags
          And Eax, FR_DOWN             ; Test the direction of the search
          .If Eax                       ; If searching backward ...
            inv lstrcpyn, Offset TopBot, Offset Top, 6 ; ADD the proper string to the message
          .Else                         ; If searching forward...
            inv lstrcpyn, Offset TopBot, Offset Bot, 6 ; ADD the proper string to the message
          .EndIf                        ; End of conditional
          inv MessageBox, NULL, Offset FindEnd, Offset szFR, MB_YESNO Or \
               MB_ICONQUESTION Or MB_TASKMODAL  ; Display the message prompt
          Cmp Eax, IDNO                ; If 'Restart=no'
          Je Done                     ; Return to main Message loop
          Mov Eax, fr                  ; Get Find/Replace flags
          And Eax, FR_DOWN             ; Test the direction of the search
          .If Eax                       ; If searching backward ...
            inv SendMessage, hREd, EM_SETSEL, 0, 0 ; Get selected text
            Mov ft.chrg.cpMin, 0       ; Start position
            Mov ft.chrg.cpMax, -1      ; End position
          .Else                         ; If searching forward ...
            inv SendMessage, hREd, WM_GETTEXTLENGTH, 0, 0  ; Get text length
            Mov ft.chrg.cpMin, Eax     ; Store it as current position
            Mov ft.chrg.cpMax, 0       ; Clear max position
          .EndIf                        ; End of conditional
          Jmp Loop1                    ; Go search again
        .EndIf                          ; End of conditional
Done:   Ret                             ; Return
;---------------------------------------;
Find EndP
;
;
FindDlgProc Proc hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
;---------------------------------------;
        Local hCtl:DWord              ; Temporary handle storage
;
        Mov Eax, uMsg                  ; Get message
        .If Eax == WM_INITDIALOG          ; Initialize
          Mov Eax, hWin                ; Get handle of the window
          Mov hFind, Eax               ; Save it
          .If lParam                    ; If there is a Message in the queue
            Mov Eax, BN_CLICKED        ; Get 'Button clicked' value
            Shl Eax, 16                ; Just the LSWord is used
            Or Eax, IDC_BTN_REPLACE   ; Test if it was the 'Replace' Button
            inv PostMessage, hWin, WM_COMMAND, Eax, 0  ; Send the result as a 'message'
          .EndIf                        ; End of conditional
;         Put the text into the edit boxes
          inv SendDlgItemMessage, hWin, IDC_FINDTEXT, EM_LIMITTEXT, 255, 0 ; Set maximum text size
          inv SendDlgItemMessage, hWin, IDC_FINDTEXT, WM_SETTEXT, 0, Offset findbuff   ; Insert text to find
          inv SendDlgItemMessage, hWin, IDC_REPLACETEXT, EM_LIMITTEXT, 255, 0  ; Set maximum text size
          inv SendDlgItemMessage, hWin, IDC_REPLACETEXT, WM_SETTEXT, 0, Offset replacebuff ; Insert text to replace
;         Set check boxes
          Mov Eax, fr                  ; Get flags
          And Eax, FR_MATCHCASE        ; Test if 'Match Case' is set
          .If Eax                       ; If it is ...
            inv CheckDlgButton, hWin, IDC_CHK_MATCHCASE, BST_CHECKED   ; Check the box
          .EndIf                        ; End of conditional
          Mov Eax, fr                  ; Get flags
          And Eax, FR_WHOLEWORD        ; Test if 'Whole Word' is set
          .If Eax                       ; If it is ...
            inv CheckDlgButton, hWin, IDC_CHK_WHOLEWORD, BST_CHECKED   ; Check the box
          .EndIf                        ; End of conditional
;         Set find direction
          Mov Eax, fr                  ; Get flags
          And Eax, FR_DOWN             ; Test if 'Search Down' is set
          .If Eax                       ; If it is ...
            Mov Eax, IDC_RBN_DOWN      ; Set the direction to 'Down'
          .Else                         ; Else
            Mov Eax, IDC_RBN_UP        ; Set the direction to 'Up'
          .EndIf                        ; End of conditional
          inv CheckDlgButton, hWin, Eax, BST_CHECKED   ; Check the appropriate button
        .ElseIf Eax == WM_COMMAND         ; Command (message) waiting to be processed?
          Mov Eax, wParam              ; Get message
          Mov Edx, Eax                 ; Store it in the data register
          Shr Edx, 16                  ; Preserve only the LSWord
          And Eax, 0FFFFH              ; Mask out the unused portions
          .If Edx == BN_CLICKED           ; If a button was clicked ...
            .If Eax == IDOK               ; If it was the 'OK' button
              inv Find, fr             ; Find the text
            .ElseIf Eax == IDCANCEL       ; If it was the 'Cancel' button
              inv SendMessage, hWin, WM_CLOSE, NULL, NULL  ; Close the find dialog box
            .ElseIf Eax == IDC_BTN_REPLACE    ; If it was the 'Replace' button
              inv GetDlgItem, hWin, IDC_BTN_REPLACEALL ; Get button handle
              Mov hCtl, Eax            ; Save it
              inv IsWindowEnabled, hCtl    ; Is it enabled?
              .If !Eax                      ; If not ...
                inv EnableWindow, hCtl, TRUE   ; Enable 'Replace all' button
                inv SetWindowText, hWin, Offset Replace    ; Set caption to Replace
                inv GetDlgItem, hWin, IDC_REPLACESTATIC    ; Get handle to the 'Replace' button
                inv ShowWindow, Eax, SW_SHOWNA             ; Show Replace button
                inv GetDlgItem, hWin, IDC_REPLACETEXT      ; Get handle of the 'Replace' text box
                inv ShowWindow, Eax, SW_SHOWNA             ; Show the edit control
              .Else                     ; Or
                .If fres != -1            ; If 'Resume' Flag is set
                  inv SendMessage, hREd, EM_EXGETSEL, 0, Offset ft.chrg    ; Get location of text to be replaced
                  inv SendMessage, hREd, EM_REPLACESEL, TRUE, Offset replacebuff   ; Replace the text
                  Add HowMany, 1       ; Count the transaction
;                  _________________________________________________________________
;                 |                                                                 |
;                 | The value will be converted to decimal from hex and shown in    |
;                 | the Status Bar's 3rd quadrant.  The 3rd quadrant is referred to |
;                 | logically as quadrant number 2 because number 1 is logically 0. |
;                 |_________________________________________________________________|
;
                  Mov ShowMessage[0], 0          ; Clears the buffer used for counting
                  inv GetDlgItem, hWnd, IDC_SBR  ; Get handle of the Statusbar
                  Mov hCtl, Eax                  ; Save handle of the Statusbar
                  inv StrCatA, Addr ShowMessage, Addr CMessagePrefix  ; Write the string into the ShowMessage buffer
                  inv dwtoa, HowMany, Addr HowManyASCIIZ   ; Convert the count value to ASCIIZ
                  inv StrCatA, Addr ShowMessage, Addr HowManyASCIIZ   ; ADD ASCIIZ info to the ShowMessage buffer
                  inv StrCatA, Addr ShowMessage, Addr CMessageSuffix  ; Write the string into the ShowMessage buffer
                  inv SendMessage, hCtl, SB_SETTEXT, 2, Addr ShowMessage  ; Display the current count
                  inv lstrlen, Offset replacebuff  ; Get length of string in the buffer
                  Add Eax, ft.chrg.cpMin   ; Plus offset from document start
                  Mov ft.chrg.cpMax, Eax   ; Store it as the end point of the selection
                  inv SendMessage, hREd, EM_EXSETSEL, 0, Offset ft.chrg   ; Reselect the text
                .EndIf                  ; End of conditional
                inv Find, fr           ; Find text, again
              .EndIf                    ; End of conditional
            .ElseIf Eax == IDC_BTN_REPLACEALL ; If it was the 'Replace All' button
              .If fres == -1              ; If 'Resume' Flag is set
                inv Find, fr           ; Find text, again
              .EndIf                    ; End of conditional
              .While fres != -1           ; If 'Resume' Flag is set
                Mov Eax, BN_CLICKED    ; Get 'Button Clicked' flag
                Shl Eax, 16            ; Only want the LSWord
                Or Eax, IDC_BTN_REPLACE   ; Test for the 'Replace' button
                inv SendMessage, hWin, WM_COMMAND, Eax, 0  ; Pass the result on as a message
              .EndW                     ; End of conditional
            .ElseIf Eax == IDC_RBN_DOWN   ; Search Down?
              Or fr, FR_DOWN          ; Set find direction to Down
              Mov fres, -1             ; Set the 'Resume' Flag
            .ElseIf Eax == IDC_RBN_UP     ; Search Up?
              And fr, -1 Xor FR_DOWN   ; Set find direction to up
              Mov fres, -1             ; Set the 'Resume' Flag
            .ElseIf Eax == IDC_CHK_MATCHCASE  ; Match Case?
              inv IsDlgButtonChecked, hWin, IDC_CHK_MATCHCASE  ; Set Match Case mode
              .If Eax                   ; If yes ...
                Or fr, FR_MATCHCASE   ; Set the flag
              .Else                     ; Else
                And fr, -1 Xor FR_MATCHCASE    ; Reset the flag
              .EndIf                    ; End of conditional
              Mov fres, -1             ; Set the 'Resume' Flag
            .ElseIf Eax == IDC_CHK_WHOLEWORD  ; Whole Word?
              inv IsDlgButtonChecked, hWin, IDC_CHK_WHOLEWORD  ; Set whole word mode
              .If Eax                   ; If yes ...
                Or fr, FR_WHOLEWORD   ; Set the flag
              .Else                     ; Else
                And fr, -1 Xor FR_WHOLEWORD    ; Reset the flag
              .EndIf                    ; End of conditional
              Mov fres, -1             ; Set the 'Resume' flag
            .EndIf                      ; End of conditional
          .ElseIf Edx == EN_CHANGE        ; This message is sent when the user has taken an action that may have altered text in an edit control.
            ; Update text buffers
            .If Eax == IDC_FINDTEXT       ; Request To Find Text?
              inv SendDlgItemMessage, hWin, Eax, WM_GETTEXT, SizeOf findbuff, Offset findbuff
              Mov fres, -1             ; Set the 'Resume' Flag
            .ElseIf Eax == IDC_REPLACETEXT    ; Request To Replace Text?
              inv SendDlgItemMessage, hWin, Eax, WM_GETTEXT, SizeOf replacebuff, Offset replacebuff
              Mov fres, -1             ; Set the 'Resume' Flag
            .EndIf                      ; End of conditional
          .EndIf                        ; End of conditional
        .ElseIf Eax == WM_ACTIVATE        ; This message is sent when a window is being activated or deactivated.
          Mov fres, -1                 ; Set the 'Resume' Flag
        .ElseIf Eax == WM_CLOSE           ; Close Request?
;          _________________________________________________________________
;         |                                                                 |
;         | The value will be converted to decimal from hex and shown in    |
;         | the Status Bar's 3rd quadrant.  The 3rd quadrant is referred to |
;         | logically as quadrant number 2 because number 1 is logically 0. |
;         |_________________________________________________________________|
;
          Mov ShowMessage[0], 0        ; Clears the the buffer used for counting
          Xor Eax, Eax                 ; Prepare to zero the counter for possible recycling
          Mov HowMany, Eax             ; Do it
          inv GetDlgItem, hWnd, IDC_SBR    ; Get handle of the Statusbar
          Mov hCtl, Eax                ; Save handle of the Statusbar
          Mov hFind, 0                 ; Clear the dialog box handle
          inv DestroyWindow, hWin      ; Close the dialog box
          Mov ShowMessage[0], 0        ; Clears the the buffer used for counting
          Xor Eax, Eax                 ; Prepare to zero the counter for possible recycling
          Mov HowMany, Eax             ; Do it
          inv GetDlgItem, hWnd, IDC_SBR    ; Get handle of the Statusbar
          Mov hCtl, Eax                    ; Save handle of the Statusbar
          inv SendMessage, hCtl, SB_SETTEXT, 2, Addr ShowMessage   ; Clear the Display
          inv SetFocus, hREd           ; Set focus to the edit control
        .Else                           ; Else
          Mov Eax, FALSE               ; Set Errorlevel
          Ret                           ; Return
        .EndIf                          ; End of conditional
        Mov Eax, TRUE                  ; Set Errorlevel
        Ret                             ; Return
;---------------------------------------;
FindDlgProc EndP
;
;
DoToolBar Proc hInst:DWord, hToolBar:HWND
;---------------------------------------;
        Local tbab:TBADDBITMAP        ; Bitmap that contains the toolbar button images
;
;       Set toolbar struct size
        inv SendMessage, hToolBar, TB_BUTTONSTRUCTSIZE, SizeOf TBBUTTON, 0 ; Store maximum size
;       Set toolbar bitmap
        Push hInst                      ; Save instance of this application
        Pop tbab.hInst                ; Store it in the structure
        Mov tbab.nID, IDB_TBRBMP       ; Store bitmap in the structure
        inv SendMessage, hToolBar, TB_ADDBITMAP, 15, Addr tbab ; Make the toolbar
;       Set toolbar buttons
        inv SendMessage, hToolBar, TB_ADDBUTTONS, ntbrbtns, Offset tbrbtns ; Add the buttons
        Mov Eax, hToolBar              ; Get the toolbar handle (used as the return code)
        Ret                             ; Return
;---------------------------------------;
DoToolBar EndP
;
;
SetFormat Proc hWin:DWord
;---------------------------------------;
        Local chrg1:CHARRANGE         ; Structure
        Local chrg2:CHARRANGE         ; Structure
        Local pf:PARAFORMAT2          ; Structure
        Local cf:CHARFORMAT           ; Structure
        Local tp:DWord                ; Scratch variable
        Local buffer[16]:Byte         ; Temporary buffer
        Local pt:POINT                ; Pixel point
        Local hDC:HDC                 ; Device context
;
;       Save modification state
        inv SendMessage, hWin, EM_GETMODIFY, 0, 0  ; Get document state
        Push Eax                        ; Save it
;       Save selection
        inv SendMessage, hWin, EM_EXGETSEL, 0, Addr chrg1  ; Get range of possible selection
        inv SendMessage, hWin, EM_HIDESELECTION, TRUE, 0   ; Save it by hiding it
;       Select all text
        Mov chrg2.cpMin, 0             ; Get start of document
        Mov chrg2.cpMax, -1            ; Get end of document
        inv SendMessage, hWin, EM_EXSETSEL, 0, Addr chrg2  ; Select all of the text in the control
;       Set font charset
        Mov cf.cbSize, SizeOf cf       ; Get size of the structure
        Mov cf.dwMask, CFM_CHARSET Or CFM_FACE Or CFM_SIZE Or CFM_COLOR    ; Set the attribute mask
        Mov Al, lfnt.lfCharSet         ; Get current character set
        Mov cf.bCharSet, Al            ; Store it in the structure
        Mov Al, lfnt.lfPitchAndFamily  ; Get character styles
        Mov cf.bPitchAndFamily, Al     ; Store it in the structure

        inv lstrcpyn, Addr cf.szFaceName, Offset lfnt.lfFaceName, LF_FACESIZE
        Mov Eax, lfnt.lfHeight         ; Get height
        Neg Eax                        ; Multiply by -1
        Mov Ecx, 15                    ; Get multiplier
        Mul Ecx                        ; Multiply by 15
        Mov cf.yHeight, Eax            ; Save the result
        Mov Eax, rgb                   ; Get foreground color
        Mov cf.crTextColor, Eax        ; Save it
        inv SendMessage, hWin, EM_SETCHARFORMAT, SCF_SELECTION, Addr cf    ; Set character format
;       Get tab width
        inv GetDC, hWin                ; Retrieves a handle of a device context (DC) for the edit control
        Mov hDC, Eax                   ; Save the DC
        inv SelectObject, hDC, hFont   ; Selects an object into the specified device context
        Push Eax                        ; Save it
        Mov Eax, 'WWWW'                ; Get 4 of the largest character in the set
        Mov DWord Ptr buffer, Eax      ; Put it in the buffer
        inv GetTextExtentPoint32, hDC, Addr buffer, 4, Addr pt ; Computes the width and height of the specified string of text
        Pop Eax                        ; Restore the font
        inv SelectObject, hDC, Eax     ; Reset the device context
        inv ReleaseDC, hWin, hDC       ; Release the device context resources
        Mov Eax, pt.x                  ; Save the x coordinate (size)
        Mov Ecx, TabSize               ; Get current tabsize
        Mul Ecx                        ; Get pixel value
        Mov Ecx, 15                    ; Get multiplier
        Mul Ecx                        ; Multiply by 15
        Shr Eax, 2                     ; Divide by 2
        Mov tp, Eax                    ; Save the resulting tab points (in pixels)
;       Set tab stops
        Mov pf.cbSize, SizeOf pf       ; Get size of the structure
        Mov pf.dwMask, PFM_TABSTOPS    ; Set mask
        Mov pf.cTabCount, MAX_TAB_STOPS    ; Set tab count
        Xor Eax, Eax                   ; Clear the accumulator
        Xor Edx, Edx                   ; Clear the data register
        Mov Ecx, MAX_TAB_STOPS         ; Get tab count
J001:   Add Eax, tp                    ; Plus pixel count
        Mov DWord Ptr pf.rgxTabs[Edx], Eax ; Store tab stop in the structure
        Add Edx, 4                     ; Get next tab stop
        Loop J001                       ; Build complete tab stop table
        inv SendMessage, hWin, EM_SETPARAFORMAT, 0, Addr pf    ; Store this information in the edit control
;       Restore modify state
        Pop Eax                        ; Restore the document state
        inv SendMessage, hWin, EM_SETMODIFY, Eax, 0    ; Reset the edit control to how it was originally
;       Restore selection
        inv SendMessage, hWin, EM_EXSETSEL, 0, Addr chrg1  ; Get positions of any text that was selected
        inv SendMessage, hWin, EM_HIDESELECTION, FALSE, 0  ; Make it visible
        Ret                             ; Return
;---------------------------------------;
SetFormat EndP
;
;
WordWrap Proc
;---------------------------------------;
        .If WWrap == 0                    ; If wordwrap is off
          inv CheckMenuItem, hMenu, IDM_WWRAP, MF_UNCHECKED    ; Clear the check mark
          Push 1                        ; Save new setting
        .Else                           ; or...
          inv CheckMenuItem, hMenu, IDM_WWRAP, MF_CHECKED      ; Set the check mark
          Push 0                        ; Save new setting
        .EndIf                          ; End of conditional
        Pop WWrap                      ; Get WWrap setting
;       If WWrap=0, then no wrap.  If WWrap=1 then wrap occurs at the end of the last
;       word that will fit the control's current width
        inv SendMessage, hREd, EM_SETTARGETDEVICE, 0, WWrap    ; Set line width method
        Ret                                                     ; Return  to caller
;---------------------------------------
WordWrap EndP
;
;
ShowPosition Proc
;---------------------------------------;
        Local hCtl:HWND               ; Handle storage used by different controls
;
        inv SendMessage, hREd, EM_LINEINDEX, -1, 0     ; Offset to start of current line from beginning of file
        Mov FileOff, Eax               ; Save the offset
        inv SendMessage, hREd, EM_EXLINEFROMCHAR, 0, FileOff   ; Get row value (zero based)
        Mov BinRow, Eax                ; Current Row - 1
        Inc BinRow                     ; Current Row
        inv SendMessage, hREd, EM_LINEINDEX, BinRow, 0 ; Get offset to start of next row from beginning of file
        .If Eax == -1                   ; -1 if past EOF
          Mov Eax, 1                   ; If so, then make it a 1
        .EndIf                          ; End of conditional
        Mov BinColumnTotal, Eax        ; Offset to start of next line from beginning of file
        inv SendMessage, hREd, EM_GETLINECOUNT, 0, 0           ; Get total amount of lines in the control
        Mov BinRowTotal, Eax           ; Total amount of lines in editor
;        _______________________________________________________________
;       |                                                               |
;       | Get start and end positions of current selection, if no text  |
;       | is selected in the control, both values will be the same.     |
;       | You can probably see this would also be very useful because   |
;       | it is a slick way of getting the control to reveal what the   |
;       | position of the insertion point within the text control.      |
;       |_______________________________________________________________|
;
        inv SendMessage, hREd, EM_GETSEL, Offset BinColumn, Offset BinColOffset
        Push BinColOffset               ; Save position within the line
        Push FileOff                    ; Save position of line start - 1
        Pop Eax                        ; Now in eax register
        Pop BinColumn                  ; Get position within the line
        Sub BinColumn, Eax             ; Get column position - 1
        Inc BinColumn                  ; Current Column
        .If BinColumnTotal == 1         ; If current line is last line...
          inv SendMessage, hREd, EM_LINEINDEX, -1, 0
          inv SendMessage, hREd, EM_LINELENGTH, Eax, 0
          Add Eax, 1
          Mov BinColumnTotal, Eax       ; and Make it the max value
        .Else                           ; Else
          Push FileOff                  ; Save position of line start - 1
          Pop Eax                      ; Now in eax
          Sub BinColumnTotal, Eax      ; Get column position
        .EndIf                          ; End of conditional
;        _________________________________________________________________
;       |                                                                 |
;       | The value will be converted to decimal from hex and shown in    |
;       | the Status Bar's 3rd quadrant.  The 3rd quadrant is referred to |
;       | logically as quadrant number 2 because number 1 is logically 0. |
;       |_________________________________________________________________|
;
        Mov ShowRow[0], 0              ; Clears the the buffer
        inv GetDlgItem, hWnd, IDC_SBR  ; Get handle of the Statusbar
        Mov hCtl, Eax                  ; Save handle of the Statusbar
        inv StrCatA, Addr ShowRow, Addr RowMsg    ; Write the string into the ShowRow message
        inv dwtoa, BinRow, Addr Row    ; Convert double word Row value to ASCII
        inv StrCatA, Addr ShowRow, Addr Row       ; ADD Row to the ShowRow buffer
        inv StrCatA, Addr ShowRow, Addr OfMsg     ; ADD ' of ' message to the ShowRow message
        inv dwtoa, BinRowTotal, Addr RowTotal      ; Convert double word Total Row value to ASCII
        inv StrCatA, Addr ShowRow, Addr RowTotal  ; Add RowTotal to ShowRow message
        Mov ShowColumn[0], 0           ; Clears the the buffer
        inv StrCatA, Addr ShowColumn, Addr ColumnMsg  ; Write the string into the ShowColumn message
        inv dwtoa, BinColumn, Addr Column          ; Convert double word Column value to ASCII
        inv StrCatA, Addr ShowColumn, Addr Column ; ADD Column to the ShowColumn buffer
        inv StrCatA, Addr ShowColumn, Addr OfMsg  ; ADD ' of ' message to the ShowColumn message
        inv dwtoa, BinColumnTotal, Addr ColumnTotal        ; Convert double word Total Column value to ASCII
        inv StrCatA, Addr ShowColumn, Addr ColumnTotal    ; Add ColumnTotal to ShowColumn message
        inv SendMessage, hCtl, SB_SETTEXT, 0, Addr ShowRow     ; Display the message in the status bar
        inv SendMessage, hCtl, SB_SETTEXT, 1, Addr ShowColumn  ; Display the message in the status bar
        Ret                             ; Return  to caller
;---------------------------------------;
ShowPosition EndP
;
;
; ______________________________________
;|                                      |
;| Display messages in the statusbar.   |
;| Our target is the fourth quadrant    |
;| The message will change every minute |
;|______________________________________|
;
QFour Proc
;---------------------------------------;
        Local hCtl:HWND               ; Handle to the Statusbar will be stored here
;
        inv GetDlgItem, hWnd, IDC_SBR  ; Get handle of the Statusbar
        Mov hCtl, Eax                  ; Save handle of the Statusbar
        Xor fView, 2                   ; Toggle the Statusbar flag bit
        Mov Eax, fView                 ; Get the result
        And Eax, 2                     ; Test the Statusbar bit
        .If Eax                         ; Is Statusbar hidden
          Jmp done                     ; Leave if it is
        .EndIf                          ; End of conditional
        Push Offset sTime               ; Get the local ...
        Call GetLocalTime               ; time from Windows
        .If Counter == 0                ; Initial run?
MOVmw Minute, sTime.wMinute   ; Get Current minute value
          inv SendMessage, hCtl, SB_SETTEXT, 3, Addr Message4  ; Display the message
          Inc Counter                  ; Sync the counter
          Ret                           ; Return  to caller
        .EndIf                          ; End of conditional
        Push Minute                     ; Put current minute on the stack
        Pop Eax                        ; Get current minute
        Cmp Ax, sTime.wMinute          ; Has it changed?
        Je done                       ; Show message for 1 minute
MOVmw Minute, sTime.wMinute     ; Update the current minute value
        Inc Counter                    ; Move to the next message
        .If Counter == 4                ; End Of Messages?
          Mov Byte Ptr Counter, 1      ; Rollback to first message, endlessly repeating
        .EndIf                          ; End of conditional
        .If Counter == 1                ; Show appropriate message
          inv SendMessage, hCtl, SB_SETTEXT, 3, Addr Message4  ; Display the message
        .ElseIf Counter == 2            ; Show appropriate message
          .If Modified == 1             ; If document is modified...
            inv SendMessage, hCtl, SB_SETTEXT, 3, Addr Message2    ; Display the message
          .Else                         ; Next conditional
            inv SendMessage, hCtl, SB_SETTEXT, 3, Addr Message3    ; Display the message
          .EndIf                        ; End of conditional
        .ElseIf Counter == 3            ; Show appropriate message
          inv SendMessage, hCtl, SB_SETTEXT, 3, Addr Message1  ; Display the message
        .EndIf                          ; End of conditional
done:   Ret                             ; Return  to caller
;---------------------------------------;
QFour EndP
;
;
ShowFont Proc
; ______________________________________
;|                                      |
;| Build the complete FontName and size |
;| and display it in the status bar.    |
;|______________________________________|
;
        inv RtlZeroMemory, Addr Stuffing, SizeOf Stuffing  ; Clear the structure variables
        Mov Eax, PointSize             ; Get point size
        Div DecValue                   ; Divide by 10
        inv dwtoa, Eax, Addr ASCIIPointSize    ; Convert it to ASCII
        inv lstrcpy, Addr Stuffing, Addr FontName  ; Build the message
        inv lstrcat, Addr Stuffing, Addr Delimit   ; Build the message
        inv lstrcat, Addr Stuffing, Addr ASCIIPointSize    ; Build the message
        inv lstrcat, Addr Stuffing, Addr EndOfString   ; Finish building the message
        Mov Byte Ptr Counter, 0        ; Force a status bar update
        Ret                             ; Return  to caller
;---------------------------------------
ShowFont EndP
;
;
SetColor Proc
;---------------------------------------;
        Local Chg:DWord                 ; Scratch variable
;
        inv SendMessage, hREd, EM_GETMODIFY, 0, 0  ; Has the edit control been modified
        Mov Chg, Eax                   ; Save the state of the document
        inv RtlZeroMemory, Addr cc, SizeOf cc      ; Zero out the structure
        Mov charF.cbSize, SizeOf charF ; Store size of structure
        inv SendMessage, hREd, EM_GETCHARFORMAT, TRUE, Addr charF  ; Get the current character format
        And charF.dwEffects, 0FFFFFFFH ; Turn off AutoColor
;       Set the CHOOSECOLOR attributes
        Mov cc.lStructSize, SizeOf cc  ; Store size of structure
        Mov Eax, hWnd                  ; Get handle of 'owner'
        Mov cc.hwndOwner, Eax          ; Save it
        Mov Eax, hInstance             ; Get handle of this instance
        Mov cc.hInstance, Eax          ; Save it
        .If SetBgColor != 1             ; If setting Text Color...
          Mov Eax, charF.crTextColor   ; Get current text color
        .Else                           ; or if setting Background Color...
          Mov Eax, charF.crBackColor   ; Get current background color
        .EndIf                          ; End of conditional
        Mov cc.rgbResult, Eax          ; Store the color in  the structure
        Mov cc.lpCustColors, Offset CustClrs   ; Get offset to custom colors
        Mov cc.Flags, CC_FULLOPEN Or CC_RGBINIT    ; Set the flags
        .If FirstRun == 0                 ; 0=Normal, 1=First Run
          inv ChooseColor, Addr cc     ; Show the SetColor Dialog Box
          Cmp Eax, FALSE               ; Cancelled or error occurred?
          Je ColorRet                 ; Jump if error or cancelled
        .Else                           ; Or...
          Mov Eax, BgColor             ; Get BackGround Color
          Mov charF.crBackColor, Eax   ; Save it for future use
          Mov Eax, rgb                 ; Get ForeGround Color
          Mov cc.rgbResult, Eax        ; Fudge it as the selected color
        .EndIf                          ; End of conditional
        Mov Eax, cc.rgbResult          ; Get selected color
        .If SetBgColor != 1             ; 0=ForeGround, 1=BackGround
          Mov charF.crTextColor, Eax   ; Store the new color
          Mov rgb, Eax                 ; Store it in preparation for a registry write
        .Else                           ; Or...
          Mov charF.crBackColor, Eax   ; Store the new color
          Mov BgColor, Eax             ; Save the new background color
          inv SendMessage, hREd, EM_SETBKGNDCOLOR, 0, Eax  ; Set Background Color
          inv SendMessage, hREd, EM_SETCHARFORMAT, SCF_ALL, Addr charF ; Apply to all
        .EndIf                          ; End of conditional
        inv SendMessage, hREd, EM_SETCHARFORMAT, SCF_ALL, Addr charF   ; Set the character format
ColorRet:
        inv SendMessage, hREd, EM_SETMODIFY, Chg, 0  ; Restore previous document state
        Ret                             ; Return  to caller
;---------------------------------------;
SetColor EndP
;
;
ChangeCase Proc
;---------------------------------------
        inv SendMessage, hREd, EM_EXGETSEL, 0, Offset cr   ; Get start and ending positions of highlighted text
        Mov Eax, cr.cpMax              ; Get end position
        Sub Eax, cr.cpMin              ; Minus the start position
        .If Eax < 255                   ; If in range...
          inv SendMessage, hREd, EM_GETSELTEXT, 0, Addr szFlipCase     ; Get selected text
        .EndIf                          ; End of conditional
        Push Edi                        ; Register preservation
        Mov Edi, Offset szFlipCase     ; Pointer to text selection storage buffer
J001:   Mov Al, [Edi]                  ; Get a character
        .If Flag == 3                   ; Invert selected text
          .If Al >= 'A' && Al <= 'Z'    ; If upper case...
            Or Byte Ptr [Edi], 20H    ; Convert it to lower case
          .ElseIf Al >= 'a' && Al <= 'z'  ; If lower case...
            And Byte Ptr [Edi], 5FH    ; Convert it to upper case
          .EndIf                        ; End of conditional
        .ElseIf Flag == 2               ; Convert selected text to lower case
          .If Al >= 'a' && Al <= 'z'    ; If lower case...
            And Byte Ptr [Edi], 5FH    ; Convert it to upper case
          .EndIf                        ; End of conditional
        .ElseIf Flag == 1               ; Convert selected text to upper case
          .If Al >= 'A' && Al <= 'Z'    ; If upper case...
            Or Byte Ptr [Edi], 20H    ; Convert it to lower case
          .EndIf                        ; End of conditional
        .EndIf                          ; End of conditional
        Inc Edi                        ; Update the buffer pointer
        Or Al, Al                     ; Done?
        Jne J001                       ; Continue until ASCIIZ is reached
        Pop Edi                        ; Restore the register
;       Put back the reconditioned text
        inv SendMessage, hREd, EM_REPLACESEL, TRUE, Addr szFlipCase
        Ret                             ; Return to caller
;---------------------------------------
ChangeCase EndP
;
;
; ______________________________________
;|                                      |
;| Enable or disable the items in the   |
;| Edit Menu and Toolbar.               |
;|______________________________________|
;
EnableDisable Proc
;---------------------------------------;
        Local hCtl:HWND               ; Handle storage used by different controls
        Local TWord1:DWord            ; Scratch variable
        Local TWord2:DWord            ; Scratch variable
;
        inv GetDlgItem, hWnd, IDC_TBR  ; Get handle of the toolbar control
        Mov hCtl, Eax                  ; Save the handle
        Mov TWord2, TRUE               ; Set 'true' condition (as default)
        inv SendMessage, hREd, EM_CANUNDO, 0, 0    ; Test if 'can undo' is viable'
        Cmp Eax, TRUE                  ; Anything to undo?
        Jne EdMu1                      ; Jump if no
        Mov TWord1, MF_ENABLED         ; Set 'true' condition
        Jmp EdMu2                      ; Go modify the menu and toolbar
EdMu1:  Mov TWord1, MF_GRAYED          ; Set 'false' condition
        Mov TWord2, FALSE              ; Set 'false' condition
EdMu2:  inv EnableMenuItem, hMenu, 10101, TWord1               ; Undo Menu Selection
        inv SendMessage, hCtl, TB_ENABLEBUTTON, 10101, TWord2  ; Undo Button
        inv SendMessage, hREd, EM_CANREDO, 0, 0    ; Test if the 'undo' function was used?
        Cmp Eax, TRUE                  ; Anything to redo?
        Jne EdMu3                      ; Jump if no
        Mov TWord1, MF_ENABLED         ; Set 'true' condition
        Mov TWord2, TRUE               ; Set 'true' condition
        Jmp EdMu4                      ; Go modify the menu and toolbar
EdMu3:  Mov TWord1, MF_GRAYED          ; Set 'false' condition
        Mov TWord2, FALSE              ; Set 'false' condition
EdMu4:  inv EnableMenuItem, hMenu, 10102, TWord1               ; Redo Menu Selection
        inv SendMessage, hCtl, TB_ENABLEBUTTON, 10102, TWord2  ; Redo Button
        inv IsClipboardFormatAvailable, CF_TEXT    ; Test if Clipboard is empty
        Cmp Eax, TRUE                  ; Is Clipboard empty?
        Jne EdMu5                      ; Jump if no
        Mov TWord1, MF_ENABLED         ; Set 'true' condition
        Mov TWord2, TRUE               ; Set 'true' condition
        Jmp EdMu6                      ; Go modify the menu and toolbar
EdMu5:  Mov TWord1, MF_GRAYED          ; Set 'false' condition
        Mov TWord2, FALSE              ; Set 'false' condition
EdMu6:  inv EnableMenuItem, hMenu, 10106, TWord1               ; Paste Menu Selection
        inv SendMessage, hCtl, TB_ENABLEBUTTON, 10106, TWord2  ; Paste Button
        inv SendMessage, hREd, EM_EXGETSEL, 0, Offset cr   ; Test for 'Selected Text'
        Mov Eax, cr.cpMax              ; Get 'end of highlight'
        Sub Eax, cr.cpMin              ; Subtract the start value
        Cmp Eax, 0                     ; Nothing selected?
        Je EdMu7                      ; Jump if nothing selected
        Mov TWord1, MF_ENABLED         ; Set 'true' condition
        Mov TWord2, TRUE               ; Set 'true' condition
        Jmp EdMu8                      ; Go modify the menu and toolbar
EdMu7:  Mov TWord1, MF_GRAYED          ; Set 'false' condition
        Mov TWord2, FALSE              ; Set 'false' condition
EdMu8:  inv EnableMenuItem, hMenu, 10104, TWord1    ; Cut Menu Selection
        inv EnableMenuItem, hMenu, 10105, TWord1    ; Copy Menu Selection
        inv EnableMenuItem, hMenu, 10103, TWord1    ; Delete Menu Selection
        inv SendMessage, hCtl, TB_ENABLEBUTTON, 10104, TWord2  ; Cut Button
        inv SendMessage, hCtl, TB_ENABLEBUTTON, 10105, TWord2  ; Copy Button
        inv SendMessage, hCtl, TB_ENABLEBUTTON, 10103, TWord2  ; Delete Button
        Mov Modified, 0                ; Default to 'not modified'
        inv SendMessage, hREd, EM_GETMODIFY, 0, 0      ; Get document state
        Cmp Eax, FALSE                 ; Has the document been modified?
        Je bye                        ; Jump if no
        Mov Modified, 1                ; Flag the file as needing to be saved
        .If Flag == 0                     ; Has the Title been displayed?
          inv SetWinCaption            ; Display the Title Bar message, if no
          Mov Flag, 1                  ; Remember that it was displayed, prevents flicker
        .EndIf                          ; End of conditional
bye:    Ret                             ; Return to caller
;---------------------------------------;
EnableDisable EndP
;
;
DlgProc Proc hWndw:HWND, iMsg:DWord, wParam:WPARAM, lParam:LPARAM
;---------------------------------------;
        Local hCtl:HWND               ; Handle storage used by different controls
;
        .If iMsg == WM_INITDIALOG         ; First pass?  Setup?
          inv GetDlgItem, hWndw, IDC_LINENUMBER    ; Get handle for the edit control
          Mov hCtl, Eax                ; Save the handle
          Push Eax                      ; Save the handle on the stack
          inv SetFocus, Eax            ; Set the focus to the edit box
          Pop Eax                      ; Retrieve the handle
          inv SendMessage, Eax, EM_LIMITTEXT, 8, 0 ; Control will have an 8 digit limit
        .ElseIf iMsg == WM_CLOSE          ; If all done ...
          inv EndDialog, hWndw, NULL   ; Close the dialog box
        .ElseIf iMsg == WM_COMMAND        ; If there is a valid command to process ...
          Mov Eax, wParam               ; Get the command
          Mov Edx, Eax                  ; Get a copy of the parameter value
          Shr Edx, 16                   ; Just the LSWord
          .If Dx == BN_CLICKED            ; Was a button clicked?
            .If Eax == IDC_CANCEL         ; Was it the cancel button?
              inv SendMessage, hWndw, WM_CLOSE, NULL, NULL ; Send a close request to WM_CLOSE
            .ElseIf Eax == IDC_OK         ; If it was the okay button
              inv GetDlgItemInt, hWndw, IDC_LINENUMBER, 0, FALSE   ; Get line number
              Mov tempword, Eax        ; Save new number
              inv SendMessage, hWndw, WM_CLOSE, NULL, NULL ; Send a close request to WM_CLOSE
            .EndIf                      ; End of conditional
          .EndIf                        ; End of conditional
        .Else                           ; else ...
          Mov Eax, FALSE                ; Set exit value
          Ret                           ; Return to caller
        .EndIf                          ; End of conditional
        Mov Eax, TRUE                  ; Set exit value
        Ret                             ; Return to caller
;---------------------------------------;
DlgProc EndP
;
;
SpecialProc Proc hWin:DWord, wmsg:DWord, wParam:DWord, lParam:DWord
;---------------------------------------;
        .If wmsg == WM_INITDIALOG       ; If 'Initialize Dialog' request...
          inv SetDlgItemText, hWin, 3007, Addr szButton4   ; Set default button
          Ret                           ; Return  to caller
        .ElseIf wmsg == WM_CLOSE        ; If 'Close Dialog' request...
          inv EndDialog, hWin, 0       ; Close it
          Push 1                        ; Set errorlevel value
          Pop Eax                      ; Get it into the proper register
          Ret                           ; Return  to caller
        .ElseIf wmsg == WM_COMMAND      ; If 'Process Command' request...
          .If wParam == IDC_REPORT      ; If button pressed...
            inv SetDlgItemText, hWin, 3007, Addr szButton4
            Ret                         ; Return  to caller
          .ElseIf wParam == IDC_SHORTS  ; If button pressed...
            inv SetDlgItemText, hWin, 3007, Addr szButton3
            Ret                         ; Return  to caller
          .ElseIf wParam == IDC_NOTES   ; If button pressed...
            inv SetDlgItemText, hWin, 3007, Addr szButton5
            Ret                         ; Return  to caller
          .ElseIf wParam == IDC_ABOUT   ; If button pressed...
            inv SetDlgItemText, hWin, 3007, Addr szButton6
            Ret                         ; Return  to caller
          .ElseIf wParam == IDCANCEL    ; If button pressed...
            inv EndDialog, hWin, 0     ; Close the dialog box
            Push 1                      ; Set errorlevel value
            Pop Eax                    ; Get it into the proper register
            Ret                         ; Return  to caller
          .EndIf                        ; End of conditional
        .EndIf                          ; End of conditional
        Xor Eax, Eax                   ; Errorlevel==0
        Ret                             ; Return  to caller
;---------------------------------------;
SpecialProc EndP
;
;
; ______________________________________
;|                                      |
;| Manage the MRU list in File Menu.    |
;|______________________________________|
;
AppendToMenu Proc
;---------------------------------------;
        inv GetMenu, hWnd              ; Get handle to main menu
        Mov hMenu, Eax                 ; Save the menu handle
        inv GetSubMenu, hMenu, 0       ; Get handle to 1st popup menu
        Mov hSubMenu, Eax              ; Save the submenu handle
        inv GetMenuItemCount, hSubMenu ; Get amount of SubMenu items
        Sub Eax, 1                     ; Point above the Exit selection
        Mov itemcount, Eax             ; Save the index counter
        Inc Partial                    ; Count the separator
        .If Partial > 6                 ; Is the menu full?
          Mov Partial, 6               ; Maximum allowed
        .EndIf                          ; End of conditional
        .If isModified == 1             ; If not the first run
          Mov Eax, Partial             ; How many unused entries?
          Sub itemcount, Eax           ; Fix the index counter
          .While Partial > 0           ; If not all removed
            inv DeleteMenu, hSubMenu, itemcount, MF_BYPOSITION ; Clear the MRU
            Dec Partial                ; Count this removal
          .EndW                         ; Do it 6 times at most
        .EndIf                          ; End of conditional
        Mov isModified, 1              ; Mark for next run
        Cmp PathName[0], 0             ; Did we 'load' or 'save as' a file?
        Je empty                      ; Jump if we did not
        Cmp PathName[0], 'U'           ; Did we 'load' or 'save as' a file?
        Je empty                      ; Jump if we did not
;       Checking for possible duplication
;       --------------------------------;
        Mov amtAdded, 5                ; Maximum entries in menu
        Mov Block, 0                   ; Point to first entry
        .While amtAdded > 0             ; Until all entries are compared
          Mov Esi, Offset PathName     ; Point to string to compare
          Mov Edi, Offset MRUDump      ; Get the Menu buffer pointer
          Add Edi, Block               ; At this offset
Matches:  Mov Al, [Esi]                ; Get a character
          Cmp [Edi], Al                ; Match?
          Jne NoMatch                  ; Jump to next comparison if no
          Inc Edi                      ; Update the buffer pointer
          Inc Esi                      ; Update the buffer pointer
          Cmp Al, 0                    ; ASCIIZ?
          Je CpyDwn                   ; If yes, we found a match
          Jmp Matches                  ; Continue parsing
NoMatch:  Add Block, 256               ; Move to next menu selection
          Dec amtAdded                 ; Count the last comparison
        .EndW                           ; Do it 5 times
        Mov Block, 1024                ; Offset into the buffer
CpyDwn: Cmp Block, 0                   ; Done?
        Je empty                      ; Jump if done
        Mov Edi, Offset MRUDump        ; Point to the buffer
        Add Edi, Block                 ; At this offset
        Mov Esi, Edi                   ; Point to the buffer
        Sub Esi, 256                   ; At this offset
        Mov amtAdded, 256              ; Maximum entry size
        .While amtAdded > 0             ; If not all transferred
          Mov Al, [Esi]                ; Get a menu character
          Mov [Edi], Al                ; Move it to the next line
          Inc Esi                      ; Update the buffer pointer
          Inc Edi                      ; Update the buffer pointer
          Dec amtAdded                 ; Count the transfer
        .EndW                           ; Do it 256 times
        Sub Block, 256                 ; Update the offset pointer
        Cmp Block, 0                   ; All done?
        Jne CpyDwn                     ; Go move next menu item, if not done
        Mov Edi, Offset MRUDump        ; Point to the first MRU menu location
        Mov Esi, Offset PathName       ; Point to the new filename
next1:  Mov Al, [Esi]                  ; Get a character
        Mov [Edi], Al                  ; Store it in the menu buffer
        Inc Esi                        ; Update the buffer pointer
        Inc Edi                        ; Update the buffer pointer
        Cmp Al, 0                      ; Done?
        Jne next1                      ; Continue the copy until ASCIIZ is reached
empty:  Mov Block, 0                   ; Start at the beginning, of course
        Mov Partial, 0                 ; Clear the item counter
        Mov Eax, 1201                  ; values are 1201 - 1205
again:  Mov MenuID, Eax                ; wParam value
        Mov Esi, Offset MRUDump        ; Get Menu entry offset in buffer
        Add Esi, Block                 ; This is the offset to it
        Cmp Byte Ptr [Esi], 0          ; No more Menu Items to add?
        Je SeeYa                      ; Jump if all done
        Add Partial, 1                 ; Count this menu item
        Mov Edi, Offset szMenuEntry    ; Point to the data
copy:   Mov Al, [Esi]                  ; Get a character
        Mov [Edi], Al                  ; Store it in the temporary buffer
        Inc Esi                        ; Update the buffer pointer
        Inc Edi                        ; Update the buffer pointer
        Cmp Al, 0                      ; Done?
        Jne copy                       ; Continue the transfer if not done
        Add Block, 256                 ; Update the buffer offset pointer
        inv AddLineItem                ; Add the item to the menu
        Mov Eax, MenuID                ; wParam value
        Add Eax, 1                     ; Update the wParam value
        Inc itemcount                  ; Update the menu index counter
        Cmp Block, 1280                ; Done?
        Jne again                      ; Continue until all entries are added
SeeYa:  inv AddSeparator               ; Store a separator in the menu
        inv SaveMRUFiles               ; Update the registry
        Ret                             ; Return to caller
;---------------------------------------;
AppendToMenu EndP
;
;
; ______________________________________
;|                                      |
;| szMenuEntry = points to menu entry   |
;|               filename text string   |
;|      MenuID = wParam menu selection  |
;|   itemcount = menu sel. location     |
;|______________________________________|
;
AddLineItem Proc
;---------------------------------------;
        Local miInfo:MENUITEMINFO       ; Structure
;
        Mov miInfo.cbSize, SizeOf MENUITEMINFO ; Get structure size
        Mov miInfo.fMask, MIIM_TYPE Or MIIM_ID ; and type
        Mov miInfo.fType, MFT_STRING   ; Set 'type'
        inv lstrlen, Addr szMenuEntry  ; Get length of new entry
        Mov miInfo.cch, Eax            ; Length of MENUITEM label
        Mov Eax, Offset szMenuEntry    ; Point to new entry
        Mov miInfo.dwTypeData, Eax     ; Store it in the structure
        Mov miInfo.fState, MFS_ENABLED ; Menu is selectable
        Mov Eax, MenuID                ; Get Menu item ID
        Mov miInfo.wID, Eax            ; Store the value to be sent to wParam
        Mov miInfo.hSubMenu, NULL      ; This is a MENUITEM, not a heading
        Mov miInfo.hbmpChecked, NULL   ; Skip the graphics
        Mov miInfo.hbmpUnchecked, NULL ; Skip the graphics
        Mov miInfo.dwItemData, Eax     ; Again with the ID
        inv InsertMenuItem, hSubMenu, itemcount, TRUE, Addr miInfo ; Add item to menu
        inv EnableMenuItem, hSubMenu, itemcount, MF_BYCOMMAND Or MF_ENABLED    ; Make it selectable
        Ret                             ; Return to caller
;---------------------------------------;
AddLineItem EndP
;
;
; ______________________________________
;|                                      |
;| Append a separator to bottom of menu |
;| just above the Exit selection.       |
;| itemcount contains the value of the  |
;| location on entry into this routine. |
;|______________________________________|
;
AddSeparator Proc
;---------------------------------------;
        Local miInfo:MENUITEMINFO       ; Structure
;
        Mov miInfo.cbSize, SizeOf MENUITEMINFO ; Size of structure is stored
        Mov miInfo.fState, 0                   ; Structure data
        Mov miInfo.hSubMenu, 0                 ; Structure data - SubMenu pointer
        Mov miInfo.hbmpChecked, 0              ; Structure data
        Mov miInfo.hbmpUnchecked, 0            ; Structure data
        Mov miInfo.dwItemData, 0               ; Structure data
        Mov miInfo.fType, MFT_SEPARATOR        ; Structure data - Separator
        Mov miInfo.dwTypeData, 0               ; Structure data
        Mov miInfo.cch, 0                      ; Structure data
        Mov miInfo.wID, 0                      ; Structure data
        Mov miInfo.fMask, MIIM_TYPE            ; Structure data
        inv InsertMenuItem, hSubMenu, itemcount, 1, Addr miInfo    ; Insert Separator
        Ret                             ; Return to caller
;---------------------------------------;
AddSeparator EndP
;
;
; ______________________________________
;|                                      |
;| NOTE:  At the first blank entry, the |
;| search will end.  If you delete the  |
;| first item, this routine will report |
;| that there are NO MRU files, EVEN IF |
;| the next 4 entries all have values.  |
;| Those entries will just disappear.   |
;|______________________________________|
;
LoadMRUFiles Proc
;---------------------------------------
inv GetRegKeysz, Addr szMRU_File1, Addr szKeyName, Addr szMRUMessage1, Addr MRUBufLen1 ; Get MRU string data
        inv GetRegKeysz, Addr szMRU_File2, Addr szKeyName, Addr szMRUMessage2, Addr MRUBufLen2 ; Get MRU string data
        inv GetRegKeysz, Addr szMRU_File3, Addr szKeyName, Addr szMRUMessage3, Addr MRUBufLen3 ; Get MRU string data
        inv GetRegKeysz, Addr szMRU_File4, Addr szKeyName, Addr szMRUMessage4, Addr MRUBufLen4 ; Get MRU string data
        inv GetRegKeysz, Addr szMRU_File5, Addr szKeyName, Addr szMRUMessage5, Addr MRUBufLen5 ; Get MRU string data
        Mov Esi, Offset szMRU_File1    ; Point to Registry Menu buffer
        Mov amtAdded, 0                ; Clear the line buffer counter
        Mov Eax, 5                     ; Five possible items
        .While Eax > 0                  ; Until all are tested
          Cmp Byte Ptr [Esi], 0        ; Is the item empty?
          Je done                     ; Look no further if it is
          Add amtAdded, 256            ; increase the transfer size
          Add Esi, 256                 ; Move to the next entry
          Dec Eax                      ; Count this comparison
        .EndW                           ; Do it 5 times
done:   Mov Edi, Offset MRUDump        ; Point to the Menu buffer
        Mov Esi, Offset szMRU_File1    ; Point to Registry Menu buffer
        .While amtAdded > 0             ; Until all bytes are transferred
          Mov Al, [Esi]                ; Get a byte from the Registry buffer
          Mov [Edi], Al                ; Store it in the Menu buffer
          Inc Esi                      ; Update the buffer pointer
          Inc Edi                      ; Update the buffer pointer
          Dec amtAdded                 ; Count the byte
        .EndW                           ; Transfer is complete
        Mov Esi, Offset EndOfDump      ; End of buffer pointer
again:  Cmp Esi, Edi                   ; all erased?
        Je bye                        ; Jump if done
        Mov Byte Ptr [Edi], 0          ; Clear a character
        Inc Edi                        ; Update the buffer pointer
        Jmp again                      ; Continue clearing unused portion of buffer
bye:    Ret                             ; Return to caller
;---------------------------------------;
LoadMRUFiles EndP
;
;
SaveMRUFiles Proc
;---------------------------------------;
        Mov amtAdded, 1280             ; Menu buffer size
        Mov Esi, Offset MRUDump        ; Point to the Menu buffer
        Mov Edi, Offset szMRU_File1    ; Point to the Registry Menu Buffer
        .While amtAdded > 0             ; Until all bytes are transferred
          Mov Al, [Esi]                ; Get a character from the Menu buffer
          Mov [Edi], Al                ; Store it in the Registry buffer
          Inc Esi                      ; Update the buffer pointer
          Inc Edi                      ; Update the buffer pointer
          Dec amtAdded                 ; Count the byte transfer
        .EndW                           ; Transfer is complete
        inv lstrlen, Addr szMRU_File1  ; Get length of string
        Mov szStrLength, Eax           ; Save it
        inv SetRegKeysz, Addr szMRU_File1, Addr szKeyName, Addr szMRUMessage1, szStrLength ; Write the string
        inv lstrlen, Addr szMRU_File2  ; Get length of string
        Mov szStrLength, Eax        ; Save it
        inv SetRegKeysz, Addr szMRU_File2, Addr szKeyName, Addr szMRUMessage2, szStrLength ; Write the string
        inv lstrlen, Addr szMRU_File3  ; Get length of string
        Mov szStrLength, Eax           ; Save it
        inv SetRegKeysz, Addr szMRU_File3, Addr szKeyName, Addr szMRUMessage3, szStrLength ; Write the string
        inv lstrlen, Addr szMRU_File4  ; Get length of string
        Mov szStrLength, Eax        ; Save it
        inv SetRegKeysz, Addr szMRU_File4, Addr szKeyName, Addr szMRUMessage4, szStrLength ; Write the string
        inv lstrlen, Addr szMRU_File5  ; Get length of string
        Mov szStrLength, Eax           ; Save it
        inv SetRegKeysz, Addr szMRU_File5, Addr szKeyName, Addr szMRUMessage5, szStrLength ; Write the string
        Ret                             ; Return to caller
;---------------------------------------;
SaveMRUFiles EndP
;
;
GetRegKeysz Proc lpszBuffer:DWord,
                 lpszKeyName:DWord,
                 lpszValueName:DWord,
                 dwStringLength:DWord
;---------------------------------------;
        Local TType:DWord               ; Scratch variable
        Local pKey:DWord                ; Scratch variable
;
        Mov TType, REG_SZ              ; Set size
        inv RegCreateKeyEx, HKEY_LOCAL_MACHINE, lpszKeyName, NULL, NULL,
             REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, Addr pKey, Addr TType   ; Create key
        .If Eax == ERROR_SUCCESS        ; If successful...
          Mov Eax, REG_DWORD           ; Get key
          Mov TType, Eax               ; Save key
          inv RegQueryValueEx, pKey, lpszValueName,
               NULL, Addr TType, lpszBuffer, dwStringLength ; Get value
          inv RegCloseKey, pKey        ; Close the Registry
        .EndIf                          ; End of conditional
        Ret                             ; Return  to caller
;---------------------------------------;
GetRegKeysz EndP
;
;
SetRegKeysz Proc lpszString:DWord, lpszKeyName:DWord, lpszValueName:DWord, dwStringLength:DWord
;---------------------------------------;
        Local Disp:DWord                ; Scratch variable
        Local pKey:DWord                ; Scratch variable
;
        inv RegCreateKeyEx, HKEY_LOCAL_MACHINE, lpszKeyName, NULL, NULL,
             REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, Addr pKey, Addr Disp    ; Create key
        .If Eax == ERROR_SUCCESS        ; If successful...
          inv RegSetValueEx, pKey, lpszValueName,
               NULL, REG_SZ, lpszString, dwStringLength ; Store the key
          inv RegCloseKey, pKey        ; Close the Registry
        .EndIf                          ; End of conditional
        Ret                             ; Return  to caller
;---------------------------------------;
SetRegKeysz EndP
;
;
GetRegKeyDW Proc lpdwValue:DWord, lpszKeyName:DWord, lpszValueName:DWord
;---------------------------------------;
        Local Temp:DWord                ; Scratch variable
        Local pKey:DWord                ; Scratch variable
        Local DWordSize:DWord           ; Scratch variable
DW_SIZE Equ 4                   ; Scratch variable
;
        Mov DWordSize, DW_SIZE         ; Get size of data
        inv RegCreateKeyEx, HKEY_LOCAL_MACHINE, lpszKeyName, NULL, NULL,
             REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, Addr pKey, Addr Temp    ; Get entry key
        .If Eax == ERROR_SUCCESS        ; If successful
          Mov Eax, REG_DWORD           ; Get the key
          Mov Temp, Eax                ; Save it in the temporary buffer
          inv RegQueryValueEx, pKey, lpszValueName,
               NULL, Addr Temp, lpdwValue, Addr DWordSize   ; Get value
          inv RegCloseKey, pKey        ; Close the Registry
        .EndIf                          ; End of conditional
        Ret                             ; Return  to caller
;---------------------------------------;
GetRegKeyDW EndP
;
;
SetRegKeyDW Proc lpdwValue:DWord, lpszKeyName:DWord, lpszValueName:DWord
;---------------------------------------;
        Local Disp:DWord                ; Scratch variable
        Local pKey:DWord                ; Scratch variable
DW_SIZE Equ 4                   ; Scratch variable
;
        inv RegCreateKeyEx, HKEY_LOCAL_MACHINE, lpszKeyName, NULL, NULL,
             REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, Addr pKey, Addr Disp    ; Create the entry key
        .If Eax == ERROR_SUCCESS        ; If successful...
          inv RegSetValueEx, pKey, lpszValueName,
               NULL, REG_DWORD_LITTLE_ENDIAN, lpdwValue, DW_SIZE    ; Write the data to the registry
          inv RegCloseKey, pKey        ; Close the Registry file
        .EndIf                          ; End of conditional
        Ret                             ; Return to caller
;---------------------------------------;
SetRegKeyDW EndP
;
;
GtFrmRegistry Proc
;---------------------------------------
GetIt:  inv GetRegKeysz, Addr szFontName, Addr szKeyName, Addr szFontMessage, Addr FNBufferLength  ; Read FontName
        inv GetRegKeyDW, Addr szBgColor, Addr szKeyName, Addr szBGCMessage     ; Read Background Color
        inv GetRegKeyDW, Addr szFgColor, Addr szKeyName, Addr szFGCMessage     ; Read Text Color
        inv GetRegKeyDW, Addr szPointSize, Addr szKeyName, Addr szPointMessage ; Read Point Size
        inv GetRegKeyDW, Addr szFontHeight, Addr szKeyName, Addr szFHeightMsg  ; Read Font Height
        inv GetRegKeyDW, Addr szFontWeight, Addr szKeyName, Addr szFWeightMsg  ; Read Font Weight
        .If szBgColor == 0                ; If nothing is in the Registry
          inv SavToRegistry            ; Initialize the Registry
          Jmp GetIt                    ; Go try again, this time you will succeed
        .EndIf                          ; End of conditional
        inv lstrcpy, Addr FontName, Addr szFontName    ; Store FontName
		Move BgColor, szBgColor         ; Store Background Color
        Move rgb, szFgColor             ; Store Text Color
		Move PointSize, szPointSize     ; Store Point Size
		Move FontHeight, szFontHeight   ; Store Font Height
		Move FontWeight, szFontWeight   ; Store Font Weight
        Ret                             ; Return to caller
;---------------------------------------;
GtFrmRegistry EndP
;
;
SavToRegistry Proc
;---------------------------------------
        inv lstrcpy, Addr szFontName, Addr FontName    ; Get FontName
		Move szBgColor, BgColor                         ; Get Background Color
		Move szFgColor, rgb                             ; Get Text Color
		Move szPointSize, PointSize                     ; Get Point Size
		Move szFontHeight, FontHeight                   ; Get Font Height
		Move szFontWeight, FontWeight                   ; Get Font Weight
        inv SetRegKeysz, Addr szFontName, Addr szKeyName, Addr szFontMessage, SizeOf szFontMessage ; Write FontName
        inv SetRegKeyDW, Addr szBgColor, Addr szKeyName, Addr szBGCMessage     ; Write Background Color
        inv SetRegKeyDW, Addr szFgColor, Addr szKeyName, Addr szFGCMessage     ; Write Text Color
        inv SetRegKeyDW, Addr szPointSize, Addr szKeyName, Addr szPointMessage ; Write Point Size
        inv SetRegKeyDW, Addr szFontHeight, Addr szKeyName, Addr szFHeightMsg  ; Write Font Height
        inv SetRegKeyDW, Addr szFontWeight, Addr szKeyName, Addr szFWeightMsg  ; Write Font Weight
        Ret                             ; Return to caller
;---------------------------------------;
SavToRegistry EndP
;
;
PrintProc Proc
;---------------------------------------
        Local Chg:DWord, TextSize
        Local cf:CHOOSEFONT             ; Structure
;
        inv SendMessage, hREd, EM_GETMODIFY, 0, 0
        Mov Chg, Eax
        Push cf.rgbColors
        Mov cf.rgbColors, 0
        inv SendMessage, hREd, EM_SETBKGNDCOLOR, 0, 00FFFFFFH
        Pop cf.rgbColors
        Cmp PrtColor, 1
        Je StartPrt
        inv SendMessage, hREd, EM_EXGETSEL, 0, Offset cr
        inv SendMessage, hREd, EM_SETSEL, -1, 0
        Mov charF.dwMask, CFM_FACE Or CFM_SIZE Or CFM_COLOR
        Mov charF.crTextColor, 0
        inv lstrcpy, Offset charF.szFaceName, Offset FontName
        inv SendMessage, hREd, EM_SETCHARFORMAT, SCF_ALL, Offset charF
        inv SendMessage, hREd, EM_EXSETSEL, 0, Offset cr
StartPrt:
        Mov cnt, 0
        Mov pd.lStructSize, SizeOf pd
        Mov Eax, hWnd
        Mov pd.hwndOwner, Eax
        Mov Eax, hInstance
        Mov pd.hInstance, Eax
        Mov pd.Flags, PD_RETURNDC
        inv PrintDlg, Offset pd
        Cmp Eax, FALSE
        Je PrtRet
        Mov Eax, pd.Flags
        Mov Ebx, Eax
        And Ebx, 000000FFH
        Mov Sel, Ebx
        inv SendMessage, hREd, EM_EXGETSEL, 0, Offset cr
        Mov Eax, cr.cpMax
        .If Eax > cr.cpMin && Sel != 1
		  MsgBox ERROR_NO_SELECTION, szSelect, MB_YESNO Or MB_ICONQUESTION
          Cmp Eax, IDNO
          Je PrtRet
        .EndIf
        Mov doci.cbSize, SizeOf doci
        Mov doci.lpszDocName, Offset pTitle
        Mov doci.lpszOutput, 0
        Mov doci.fwType, 0
        Mov Eax, pd.hDC
        Mov fr_1.hdc, Eax
        Mov fr_1.hdcTarget, Eax  ;0
        inv GetDeviceCaps, fr_1.hdc, LOGPIXELSX    ; Number of pixels per logical inch along the screen width.
        Mov xPerInch, Eax
        inv GetDeviceCaps, fr_1.hdc, LOGPIXELSY    ; Number of pixels per logical inch along the screen height.
        Mov yPerInch, Eax
        Mov Eax, mL                    ; Min is 360
        Mov rect_1.left, Eax
        Mov Eax, mT                    ; Min is 360
        Mov rect_1.top, Eax
        .If PrtHead
          Add rect_1.top, 420          ; 360
        .EndIf
        inv GetDeviceCaps, fr_1.hdc, HORZRES       ; Width, in pixels, of the screen.
        Mov Ecx, 1440
        Mul Ecx
        Div xPerInch
        Mov rect_1.right, Eax
        Mov Eax, mR                    ; Min is 360
        Sub rect_1.right, Eax
        inv GetDeviceCaps, fr_1.hdc, VERTRES       ; Height, in raster lines, of the screen.
        Mov Ecx, 1440
        Mul Ecx
        Div yPerInch
        Mov rect_1.bottom, Eax
        Mov Eax, mB                    ; Min is 302
        Sub rect_1.bottom, Eax
        Mov Ecx, 16
        Mov Edi, Offset fr_1.rcPage
        Mov Esi, Offset rect_1
        Cld
        Rep Movsb
        inv StartDoc, pd.hDC, Offset doci
        inv SendMessage, hREd, EM_EXGETSEL, 0, Offset cr
        Mov Eax, cr.cpMin
        Mov Ebx, cr.cpMax
        .If Ebx > Eax && Sel == 1
          Mov fr_1.chrg.cpMin, Eax
          Mov fr_1.chrg.cpMax, Ebx
          Mov TextSize, Ebx
        .Else
          inv SendMessage, hREd, EM_HIDESELECTION, 1, 0
          Mov cr.cpMin, 0
          Mov cr.cpMax, -1
          inv SendMessage, hREd, EM_EXSETSEL, 0, Offset cr
          inv SendMessage, hREd, EM_EXGETSEL, 0, Offset cr
MOVmd fr_1.chrg.cpMin, cr.cpMin
          Mov fr_1.chrg.cpMax, -1
          MOVmd TextSize, cr.cpMax
          Mov cr.cpMin, 0
          Mov cr.cpMax, 0
          inv SendMessage, hREd, EM_EXSETSEL, 0, Offset cr
          inv SendMessage, hREd, EM_HIDESELECTION, 0, 0
        .EndIf
prtloop:
        inv StartPage, pd.hDC
        Cmp Eax, 0
        Jle prtabort
        Mov Ecx, 16
        Mov Esi, Offset rect_1
        Mov Edi, Offset fr_1.rc        ; Actual print page dimensions
        Cld
        Rep Movsb
        inv SendMessage, hREd, EM_FORMATRANGE, TRUE, Offset fr_1   ; Print page
        Mov fr_1.chrg.cpMin, Eax
        inv EndPage, pd.hDC
        Cmp Eax, 0
        Jle prtabort
        Mov Eax, fr_1.chrg.cpMin
        Cmp Eax, 0
        Jle prtdone
        Cmp Eax, TextSize
        Jl prtloop
prtdone:
        inv SendMessage, hREd, EM_FORMATRANGE, 0, 0
        inv EndDoc, pd.hDC
        inv DeleteDC, pd.hDC
        Jmp PrtRet
prtabort:
        inv AbortDoc, fr_1.hdc
PrtRet:
        .If ExtType != 'r' && ExtType + 1 != 't' && ExtType + 2 != 'f' || RTF == 0
          inv SendMessage, hREd, EM_SETBKGNDCOLOR, 0, BackGC
          MOVmd charF.crTextColor, TextC
          inv lstrcpy, Offset charF.szFaceName, Offset FontName
          inv SendMessage, hREd, EM_SETCHARFORMAT, SCF_ALL, Offset charF
        .EndIf
        inv SendMessage, hREd, EM_SETMODIFY, Chg, 0
        Ret
;---------------------------------------
PrintProc EndP
;
;
DoPageSU Proc
;---------------------------------------
        Mov psd.lStructSize, SizeOf psd
        Push hWnd
        Pop psd.hwndOwner
        Push hInstance
        Pop psd.hInstance
        Mov psd.Flags, PSD_MARGINS Or PSD_INTHOUSANDTHSOFINCHES Or PSD_DISABLEPAPER Or PSD_DISABLEPRINTER
        inv PageSetupDlg, Offset psd
        Cmp Eax, 0
        Jz NSU
        Finit
        Mov Al, Byte Ptr psd.rtMargin[0]
        Mov Ah, Byte Ptr psd.rtMargin[1]
        And Eax, 0000FFFFH
        Mov w1, Eax
        Fld RTwips1000
        Fild w1
        Fmul St(0), St(1)
        Fistp mL
        Mov Al, Byte Ptr psd.rtMargin[4]
        Mov Ah, Byte Ptr psd.rtMargin[5]
        And Eax, 0000FFFFH
        Mov w1, Eax
        Fld RTwips1000
        Fild w1
        Fmul St(0), St(1)
        Fistp mT
        Mov Al, Byte Ptr psd.rtMargin[8]
        Mov Ah, Byte Ptr psd.rtMargin[9]
        And Eax, 0000FFFFH
        Mov w1, Eax
        Fld RTwips1000
        Fild w1
        Fmul St(0), St(1)
        Fistp mR
        Mov Al, Byte Ptr psd.rtMargin[12]
        Mov Ah, Byte Ptr psd.rtMargin[13]
        And Eax, 0000FFFFH
        Mov w1, Eax
        Fld RTwips1000
        Fild w1
        Fmul St(0), St(1)
        Fistp mB
        Sub mL, 360
        Sub mT, 360
        Sub mR, 360
        Sub mB, 302
NSU:    Ret
;---------------------------------------
DoPageSU EndP
; _____________________________
;|                             |
;| Generate error message      |
;|  eax = message # to display |
;|  ebx = Title                |
;|  ecx = MessageBox Flags     |
;|_____________________________|
;
ErrorMsg Proc
;---------------------------------------;
        Push Ecx                        ;
        Push Ebx                        ; Save these for after LoadString call
        Push LengthOf szWork            ; Size of our buffer
        Push Offset szWork              ; Buffer to load string into
        Push Eax                        ; Resource #
        Push hInstance                  ; Instance
        Call LoadString                 ; Load the tip from STRINGTABLE
        Cmp Eax, 0                     ; Did we get a string?
        Jne Error1                     ; Yes, continue
        Lea Eax, szNULL                ; Null string
Error1: Push Offset szWork
        Push 0
        Call MessageBox
        Ret
;-------------------------------------
ErrorMsg EndP
; ________________________________________________
;|                                                |
;| ASCII Box Procedure - ASCII Win is a Sub Class |
;|________________________________________________|
;
AsciiProc Proc hwnd:DWord, wmsg:DWord, wparam:DWord, lparam:DWord
;---------------------------------------
        .If wmsg == WM_CHAR
MOVmd w4, wmsg
          inv BaseAscii, wparam, Offset szBuff, 0, 10, 0, 0, 1
          inv BaseAscii, wparam, Offset Misc, 0, 16, 0, 0, 1
          inv SendMessage, hAsciibox, EM_SETSEL, 0, -1
        .EndIf
        inv CallWindowProc, lpAsciibox, hwnd, wmsg, wparam, lparam
        Ret
;---------------------------------------
AsciiProc EndP
; ________________________
;|                        |
;| ASCII DIALOG PROCEDURE |
;|________________________|
;
AsciiDlg Proc hdlg:DWord, wmsg:DWord, wparam:DWord, lparam:DWord
;---------------------------------------
        Cmp wmsg, WM_COMMAND
        Jne AsciiDone
        Mov Eax, wparam
        Cwde
        .If Eax == IDM_ASCII && w4 == WM_CHAR
          inv SetDlgItemText, hdlg, E1, Offset szBuff
          inv SetDlgItemText, hdlg, E2, Offset Misc
          Jmp AsciiDone
        .EndIf
        Cmp Eax, IDCANCEL
        Jne AsciiDone
        inv EndDialog, hdlg, wparam
        Mov Eax, TRUE
        Jmp AsciiRet
AsciiDone:
        And w4, 0
        Mov Eax, FALSE
AsciiRet:
        Ret
;---------------------------------------
AsciiDlg EndP
; _____________________________________________________________________
;|                                                                     |
;| Converts a 32 bit num value to a Dec, Hex, Oct or Bin ascii string. |
;|_____________________________________________________________________|
;
BaseAscii Proc InPut:DWord, OutPut:DWord, LEN:DWord, Base:DWord, Comma:DWord, Fill:DWord, TermA:DWord
;---------------------------------------
        Local LBuff[32]:Byte
;
        PushAD
        Xor Esi, Esi
        Mov Eax, InPut                 ; Input
        Mov Ebx, OutPut
        Mov Byte Ptr [Ebx], '0'
        .While (Eax)
          Xor Edx, Edx
          Div Base                     ; Base 10, 16, 8, 2
          .If Dl > 9H
            Add Dl, 37H                ; Convert to hex ASCII
          .Else
            Add Dl, 30H                ; Convert to dec ASCII
          .EndIf
          Mov LBuff[Esi], Dl
          Inc Esi
          .If Comma == 1 && Base == 10 && Eax > 0
            .If Esi == 3 || Esi == 7 || Esi == 11
              Mov LBuff[Esi], 2CH      ; Insert commas
              Inc Esi
            .EndIf
          .EndIf
        .EndW
        Xor Edi, Edi
        Mov Ecx, Esi
        .If LEN > Ecx && Fill == 1      ; Zero fill
          Xor Eax, Eax
          .While (Eax < LEN)
            Mov Byte Ptr [Ebx + Eax], '0'
            Inc Eax
          .EndW
          Sub LEN, Ecx
          Add Edi, LEN
        .EndIf
        .While (Ecx)
          Mov Al, Byte Ptr LBuff[Esi - 1]
          Mov Byte Ptr [Ebx + Edi], Al
          Inc Edi
          Dec Esi
          Dec Ecx
        .EndW
        .If TermA
          Mov Byte Ptr [Ebx + Edi], 0H
        .EndIf
        PopAD
        Ret
;---------------------------------------
BaseAscii EndP
;
;
HyperLinkWndProc Proc HWnd:DWord,
                      uMsg:DWord,
                      wParam:DWord,
                      lParam:DWord
;---------------------------------------
        Local tmpFont:LOGFONT
        Local rect:RECT
        Local pt: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 pt
            Invoke  GetWindowRect, HWnd, Addr rect
            Invoke  PtInRect, Addr rect, pt.x, pt.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
          Ret
        .EndIf
        Invoke  CallWindowProc, orgStatic, HWnd, uMsg, wParam, lParam
        Ret
;---------------------------------------
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
          Mov hwndDlg, 0
        .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
            Mov hwndDlg, 0
          .EndIf
          Pop Edx
        .Else
          Mov Eax, FALSE
          Ret
        .EndIf
        Mov Eax, TRUE
        Ret
;---------------------------------------
AboutDlgProc EndP
;
;
        End     start
