;********************************************************************
%include 'C:\PAS\nasm\inc\win32n.inc'
%include 'C:\PAS\nasm\inc\general.mac'
%include 'FastPad.Inc'
; Count of bytes allocated for file name, title and ...
%define MAX_PATH 4096
; Maximum count of windows opened at one time
%define MAX_WIN_COUNT 256
; Import several functions from system dlls
dllimport GetModuleHandle, kernel32.dll, GetModuleHandleA
dllimport ExitProcess, kernel32.dll
dllimport RegisterClassEx, user32.dll, RegisterClassExA
dllimport CreateWindowEx, user32.dll, CreateWindowExA
dllimport ShowWindow, user32.dll
dllimport UpdateWindow, user32.dll
dllimport TranslateMessage, user32.dll
dllimport DispatchMessage, user32.dll, DispatchMessageA
dllimport PostQuitMessage, user32.dll
dllimport GetMessage, user32.dll, GetMessageA
dllimport DefFrameProc, user32.dll, DefFrameProcA
dllimport LoadCursor, user32.dll, LoadCursorA
dllimport FindWindow, user32.dll, FindWindowA
dllimport MessageBox, user32.dll, MessageBoxA
dllimport LoadIcon, user32.dll, LoadIconA
dllimport GetMenu, user32.dll
dllimport GetSubMenu, user32.dll
dllimport SendMessage, user32.dll, SendMessageA
dllimport DefMDIChildProc, user32.dll, DefMDIChildProcA
dllimport LoadAccelerators, user32.dll, LoadAcceleratorsA
dllimport TranslateMDISysAccel, user32.dll
dllimport TranslateAccelerator, user32.dll
dllimport GetProcessHeap, kernel32.dll
dllimport HeapAlloc, kernel32.dll
dllimport HeapFree, kernel32.dll
dllimport SetWindowLong, user32.dll, SetWindowLongA
dllimport GetWindowLong, user32.dll, GetWindowLongA
dllimport SetFocus, user32.dll
dllimport MoveWindow, user32.dll
dllimport GetWindow, user32.dll
dllimport EnumChildWindows, user32.dll
dllimport GetParent, user32.dll
dllimport EnableMenuItem, user32.dll
dllimport IsClipboardFormatAvailable, user32.dll
dllimport GetOpenFileName, comdlg32.dll, GetOpenFileNameA
dllimport GetSaveFileName, comdlg32.dll, GetSaveFileNameA
dllimport SetWindowText, user32.dll, SetWindowTextA
dllimport CreateFontIndirect, gdi32.dll, CreateFontIndirectA
dllimport DeleteObject, gdi32.dll
dllimport CreateFile, kernel32.dll, CreateFileA
dllimport CloseHandle, kernel32.dll
dllimport GetFileSize, kernel32.dll
dllimport ReadFile, kernel32.dll
dllimport WriteFile, kernel32.dll
dllimport GetFileAttributes, kernel32.dll, GetFileAttributesA
dllimport SetFileAttributes, kernel32.dll, SetFileAttributesA
dllimport GetWindowTextLength, user32.dll, GetWindowTextLengthA
dllimport GetWindowText, user32.dll, GetWindowTextA
; Document-specific data
struc DOCDATA
.hWndEdit resd 1
.bNeedSave resd 1
.szFileName resb MAX_PATH
.szTitle resb MAX_PATH
.hFont resd 1
endstruc
; Data section
[section .data class=data use32]
string szAppName,"FastPad" ; Also used for FrameWnd class name
string szDocClass,"FPDoc" ; Class name for child windows
string szMDIClient,"MDICLIENT"
string szEdit,"edit"
string szFilter,"Text files (*.txt)",0,"*.txt",0,\
"INI files (*.ini)",0,"*.ini",0,\
"LOG files (*log)",0,"*.log",0,\
"Batch files (*.bat)",0,"*.bat",0,\
"All files (*.*)",0,"*.*",0
string szExtension,"txt"
string szUntiled,"Untiled.txt"
string szAskForSave,"Save changes?"
string szAbout,"FastPad - simple editor, by Kamil Dudka, mailto: xdudka00@gmail.com"
string szErrDocOpened,"This document is already opened! Press Retry to choose another file."
string szErrLoad,"Could not open document!"
string szErrSave,"Could not save document!"
string szErrAttrRO,"File is read-only!"
string szErrAttrSYS,"File is system-file!"
string szErrDevel,"Ooooops, this fauture is under construction.."
string szErrWinLimit,"Ooooops, too many windows opened.."
string szErrAlloc,"CRITICAL: Out of memory! All data will be lost!"
string szErrLimit,"Out of range!"
string szErrInit,"Error during initialization!"
; Global variables
hInstance dd 0 ; handle instance
hWnd dd 0 ; Main window hWnd
hWndMDI dd 0 ; MDI Client hWnd
hAccel dd 0 ; handle to menu accelerators
iWndCount dd 0 ; count of opened window
msg resb MSG_size ; structure for window message loop
szFileName resb MAX_PATH ; global FileName variable
szTitle resb MAX_PATH ; global Title varible
; Structure for RegisterClassEx function
WndClass:
istruc WNDCLASSEX
at WNDCLASSEX.cbSize, dd WNDCLASSEX_size
at WNDCLASSEX.style, dd CS_VREDRAW + CS_HREDRAW
at WNDCLASSEX.lpfnWndProc, dd AppWndProc
at WNDCLASSEX.cbClsExtra, dd 0
at WNDCLASSEX.cbWndExtra, dd 0
at WNDCLASSEX.hInstance, dd NULL ; Will be rewritten later
at WNDCLASSEX.hIcon, dd NULL ; Will be rewritten later
at WNDCLASSEX.hCursor, dd NULL ; Will be rewritten later
at WNDCLASSEX.hbrBackground, dd COLOR_APPWORKSPACE + 1;
at WNDCLASSEX.lpszMenuName, dd IDR_MENU
at WNDCLASSEX.lpszClassName, dd szAppName
at WNDCLASSEX.hIconSm, dd NULL
iend
; Structure for create MDICLIENT
CRClient:
istruc CLIENTCREATESTRUCT
at CLIENTCREATESTRUCT.hWindowMenu, dd NULL ; Will be rewritten later
at CLIENTCREATESTRUCT.idFirstChild, dd 50000
iend
; Structure for create MDI Child Window
MDICreate:
istruc MDICREATESTRUCT
at MDICREATESTRUCT.szClass, dd szDocClass
at MDICREATESTRUCT.szTitle, dd szTitle ; Can be rewritten later
at MDICREATESTRUCT.hOwner, dd NULL ; Will be rewritten later
at MDICREATESTRUCT.x, dd CW_USEDEFAULT
at MDICREATESTRUCT.y, dd CW_USEDEFAULT
at MDICREATESTRUCT.lx, dd CW_USEDEFAULT
at MDICREATESTRUCT.ly, dd CW_USEDEFAULT
at MDICREATESTRUCT.style, dd 0 ; Will be rewritten later
at MDICREATESTRUCT.lParam, dd 0
iend
; Structure for OpenFile and SaveFile dialogs
OFN:
istruc OPENFILENAME
at OPENFILENAME.lStructSize, dd OPENFILENAME_size
at OPENFILENAME.hWndOwner, dd NULL ; Will be rewritten later
at OPENFILENAME.hInstance, dd NULL
at OPENFILENAME.lpstrFilter, dd szFilter
at OPENFILENAME.lpstrCustomFilter, dd NULL
at OPENFILENAME.nMaxCustFilter, dd 0
at OPENFILENAME.nFilterIndex, dd 0
at OPENFILENAME.lpstrFile, dd szFileName
at OPENFILENAME.nMaxFile, dd MAX_PATH-1
at OPENFILENAME.lpstrFileTitle, dd szTitle
at OPENFILENAME.nMaxFileTitle, dd MAX_PATH-1
at OPENFILENAME.lpstrInitialDir, dd NULL
at OPENFILENAME.lpstrTitle, dd NULL
at OPENFILENAME.Flags, dd 0
at OPENFILENAME.nFileOffset, dw 0
at OPENFILENAME.nFileExtension, dw 0
at OPENFILENAME.lpstrDefExt, dd szExtension
at OPENFILENAME.lCustData, dd 0
at OPENFILENAME.lpfnHook, dd NULL
at OPENFILENAME.lpTemplateName, dd NULL
iend
; Structure for CreateFontIndirect function
LOGF:
istruc LOGFONT
at LOGFONT.lfHeight, dw 16
at LOGFONT.lfWidth, dw 0
at LOGFONT.lfEscapement, dw 0
at LOGFONT.lfOrientation, dw 0
at LOGFONT.lfWeight, dw 0
at LOGFONT.lfItalic, db 0
at LOGFONT.lfUnderline, db 0
at LOGFONT.lfStrikeOut, db 0
at LOGFONT.lfCharSet, db 0
at LOGFONT.lfOutPrecision, db 0
at LOGFONT.lfClipPrecision, db 0
at LOGFONT.lfQuality, db 0
at LOGFONT.lfPitchAndFamily, db 0
at LOGFONT.lfFaceName, db "Courier New",0
iend
; Code section
[section .code class=code use32]
..start:
; Get hInstance for this instance
invoke GetModuleHandle,NULL
mov [hInstance], eax
mov [WndClass + WNDCLASSEX.hInstance], eax
; Check for another instance of FastPad
invoke FindWindow, szAppName, NULL
test eax,eax
jz .ChkAnotherInstance_OK
invoke MessageBox, NULL, szErrDevel, szAppName, MB_ICONERROR
jmp .AbnExit
.ChkAnotherInstance_OK:
; Load Icon And Cursor for main window
invoke LoadIcon, [hInstance], IDI_ICON_EDITOR
mov [WndClass + WNDCLASSEX.hIcon], eax
invoke LoadCursor, NULL, IDC_ARROW
mov [WndClass + WNDCLASSEX.hCursor],eax
; Register main window class
invoke RegisterClassEx,WndClass
test eax, eax
jz near .ErrInit
; Set Icon for document window
invoke LoadIcon, [hInstance], IDI_ICON_DOCUMENT
mov [WndClass + WNDCLASSEX.hIcon], eax
; Register document winodow class
mov [WndClass + WNDCLASSEX.lpszClassName], DWORD szDocClass ; Name of the document class
mov [WndClass + WNDCLASSEX.lpszMenuName], DWORD NULL
mov [WndClass + WNDCLASSEX.lpfnWndProc], DWORD DocWndProc ; Callback procedure
mov [WndClass + WNDCLASSEX.cbWndExtra], DWORD 4 ; Space for pointer to user data
invoke RegisterClassEx, WndClass
test eax, eax
jz near .ErrInit
; Load Menu Accelerators
invoke LoadAccelerators, [hInstance], IDR_MENU_ACCELERATORS
mov [hAccel], eax
; Create window
invoke CreateWindowEx,0,szAppName,szAppName,\
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,\
CW_USEDEFAULT, CW_USEDEFAULT,\
CW_USEDEFAULT, CW_USEDEFAULT,\
NULL, NULL, [hInstance], NULL
test eax, eax
jz near .ErrInit
mov [hWnd], eax ; Save hWnd to global variable
mov [OFN + OPENFILENAME.hWndOwner], eax ; Save hWndOwner for FileName dialogs
; Show and redraw the window
invoke ShowWindow, eax, SW_SHOWDEFAULT
invoke UpdateWindow, [hWnd]
; Window message loop
.MessageLoop:
; Get msg from queue
invoke GetMessage, msg, NULL, 0, 0
test eax, eax
jz near .ExitMsgLoop ; Normal exit
cmp eax,-1
jz near .AbnExit ; Error
; MDI Accelerators
invoke TranslateMDISysAccel, [hWndMDI], msg
test eax, eax
jnz .MessageLoop
; My Accelerators
invoke TranslateAccelerator, [hWnd], [hAccel], msg
test eax, eax
jnz .MessageLoop
; Handle msg
invoke TranslateMessage,msg
invoke DispatchMessage,msg
jmp .MessageLoop
.ExitMsgLoop:
invoke ExitProcess, [msg + MSG.wParam]
; Error during initialization
.ErrInit:
invoke MessageBox, NULL, szErrInit, szAppName, MB_ICONERROR
; Abnormal Exit
.AbnExit:
invoke MessageBox, NULL, szErrAlloc, szAppName, MB_ICONERROR
invoke ExitProcess, 1
; Main window callback procedure
function AppWndProc, AWP_hWnd, AWP_wMsg, AWP_wParam, AWP_lParam
begin
; msg switch
mov eax, DWORD [AWP_wMsg]
cmp eax, WM_INITMENUPOPUP
je near .AWP_InitMenuPopup
cmp eax, WM_COMMAND
je near .AWP_Command
cmp eax, WM_CREATE
je near .AWP_Create
cmp eax, WM_CLOSE
je near .AWP_Close
cmp eax, WM_QUERYENDSESSION
je near .AWP_Close
cmp eax, WM_DESTROY
je near .AWP_Destroy
.AWP_DefWndProc:
; Send unhandled msg to DefWindowProc
invoke DefFrameProc, [AWP_hWnd], [hWndMDI], [AWP_wMsg], [AWP_wParam], [AWP_lParam]
return eax
.AWP_Create:
; Get handle to Window menu
invoke GetMenu, [AWP_hWnd]
invoke GetSubMenu, eax, MENU_WND_POS
mov [CRClient + CLIENTCREATESTRUCT.hWindowMenu], eax
; Create MDICLIENT window
invoke CreateWindowEx, 0, szMDIClient, NULL, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,\
0, 0, 0, 0, [AWP_hWnd], 1, [hInstance], CRClient
mov [hWndMDI], eax
jmp .AWP_Finish
; Initialize global variables
mov [szFileName], byte 0
mov [szTitle], byte 0
.AWP_InitMenuPopup:
; Check for child window
invoke SendMessage, [hWndMDI], WM_MDIGETACTIVE, 0, 0
test eax, eax
jz near .AWPI_Disable ; no child window available
push ebx
mov ebx, eax
invoke EnableMenuItem, [AWP_wParam], IDM_FILE_SAVEAS, MF_ENABLED
invoke EnableMenuItem, [AWP_wParam], IDM_EDIT_SELECTALL, MF_ENABLED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_NEXT, MF_ENABLED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_TILE, MF_ENABLED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_CASCADE, MF_ENABLED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_ARRANGE, MF_ENABLED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_CLOSE, MF_ENABLED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_CLOSEALL, MF_ENABLED
; Send Message to child window
invoke SendMessage, ebx, WM_INITMENUPOPUP, [AWP_wParam], [AWP_lParam]
pop ebx
jmp .AWP_Finish
; No child window available
.AWPI_Disable:
invoke EnableMenuItem, [AWP_wParam], IDM_FILE_SAVE, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_FILE_SAVEAS, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_EDIT_UNDO, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_EDIT_CUT, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_EDIT_COPY, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_EDIT_PASTE, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_EDIT_SELECTALL, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_NEXT, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_CASCADE, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_TILE, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_ARRANGE, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_CLOSE, MF_GRAYED
invoke EnableMenuItem, [AWP_wParam], IDM_WINDOW_CLOSEALL, MF_GRAYED
jmp .AWP_Finish
.AWP_Command:
; menu item switch
mov ax, WORD [AWP_wParam]
cmp ax, IDM_FILE_NEW
jz near .AWPC_FileNew
cmp ax, IDM_FILE_OPEN
jz near .AWPC_FileOpen
cmp ax, IDM_APP_EXIT
jz near .AWPC_AppExit
cmp ax, IDM_WINDOW_NEXT
jz near .AWPC_WindowNext
cmp ax, IDM_WINDOW_CASCADE
jz near .AWPC_WindowCascade
cmp ax, IDM_WINDOW_TILE
jz near .AWPC_WindowTile
cmp ax, IDM_WINDOW_ARRANGE
jz near .AWPC_WindowArrange
cmp ax, IDM_WINDOW_CLOSEALL
jz near .AWPC_WindowCloseAll
cmp ax, IDM_HELP_ABOUT
jz near .AWPC_About
; Send msg to child window
invoke SendMessage, [hWndMDI], WM_MDIGETACTIVE, 0, 0
test eax,eax
jz near .AWP_Finish
invoke SendMessage, eax, WM_COMMAND, [AWP_wParam], [AWP_lParam]
jmp .AWP_DefWndProc
.AWPC_FileNew:
; Set Title and FileName
call strcpy, szFileName, szUntiled, MAX_PATH
call strcpy, szTitle, szUntiled, MAX_PATH
; Create child window
call CreateChild
test eax, eax
jz near .AWP_WinLimit
; Get ptr to docuemnt-specific data
invoke GetWindowLong, eax, 0
push ebx
mov ebx,eax
; Initialize document data
lea eax, [ebx + DOCDATA.szFileName]
call strcpy, eax, szFileName, MAX_PATH
lea eax, [ebx + DOCDATA.szTitle]
call strcpy, eax, szTitle, MAX_PATH
pop ebx
jmp .AWP_Finish
.AWPC_FileOpen
; Initalize structure for OpenFile Dialog
mov [OFN + OPENFILENAME.Flags], DWORD OFN_HIDEREADONLY; | OFN_CREATEPROMPT
; Ask for file name as long as needed
.AWPCFO_Loop:
invoke GetOpenFileName, OFN
test eax, eax
jz near .AWP_Finish ; Cancel
invoke GetWindow, [hWndMDI], GW_CHILD
test eax, eax
jz .AWPCFO_LoopExit ; No child window
invoke EnumChildWindows, [hWndMDI], EPMatchFile, szFileName
test eax, eax
jnz .AWPCFO_LoopExit ; We got unique file name
invoke MessageBox, [AWP_hWnd], szErrDocOpened, szFileName, MB_RETRYCANCEL | MB_ICONERROR
cmp eax, IDCANCEL
jz near .AWP_Finish ; Cancel
jmp .AWPCFO_Loop
.AWPCFO_LoopExit:
; Create new child window
call CreateChild
test eax, eax
jz near .AWP_WinLimit
push eax
; Get pointer to document-specific data
invoke GetWindowLong, eax, 0
push ebx
mov ebx, eax
; Save document-specific data
lea eax, [ebx + DOCDATA.szFileName]
call strcpy, eax, szFileName, MAX_PATH
lea eax, [ebx + DOCDATA.szTitle]
call strcpy, eax, szTitle, MAX_PATH
pop ebx
; Load document text
mov eax, [esp]
call DocLoad, eax
test eax, eax
jnz .AWPCFO_Error
pop eax
jmp .AWP_Finish
.AWPCFO_Error:
invoke MessageBox, [AWP_hWnd], szErrLoad, szFileName, MB_OK | MB_ICONSTOP
; Close document window
pop eax
invoke SendMessage, eax, WM_CLOSE, 0, 0
jmp .AWP_Finish
.AWPC_AppExit:
invoke SendMessage, [AWP_hWnd], WM_CLOSE, 0, 0
jmp .AWP_Finish
.AWPC_WindowNext:
invoke SendMessage, [hWndMDI], WM_MDINEXT, 0, 0
jmp .AWP_Finish
.AWPC_WindowCascade:
invoke SendMessage, [hWndMDI], WM_MDICASCADE, 0, 0
jmp .AWP_Finish
.AWPC_WindowTile:
invoke SendMessage, [hWndMDI], WM_MDITILE, 0, 0
jmp .AWP_Finish
.AWPC_WindowArrange:
invoke SendMessage, [hWndMDI], WM_MDIICONARRANGE, 0, 0
jmp .AWP_Finish
.AWPC_WindowCloseAll:
; Enumerate child windows using my function EPClose (see bellow)
invoke EnumChildWindows, [hWndMDI], EPClose, 0
jmp .AWP_Finish
.AWPC_About:
invoke MessageBox, [AWP_hWnd], szAbout, szAppName, MB_OK | MB_ICONINFORMATION
jmp .AWP_Finish
.AWP_Close:
; We should send WM_QUERYENDSESSION to child windows
invoke SendMessage, [AWP_hWnd], WM_COMMAND, IDM_WINDOW_CLOSEALL, 0
; Is anybody still here?
invoke GetWindow, [hWndMDI], GW_CHILD
test eax, eax
jnz near .AWP_Finish
jmp .AWP_DefWndProc
.AWP_WinLimit:
invoke MessageBox, [AWP_hWnd], szErrWinLimit, szAppName, MB_OK | MB_ICONSTOP
return 0
.AWP_Destroy:
invoke PostQuitMessage,0
.AWP_Finish:
return 0
end ;AppWndProc
; Document windows callback procedure
function DocWndProc,DWP_hWnd,DWP_wMsg,DWP_wParam,DWP_lParam
var DWP_bMaximized, DWP_iSelBeg, DWP_iSelEnd
begin
; msg switch
mov eax,dword [DWP_wMsg]
cmp eax, WM_SETFOCUS
jz near .DWP_SetFocus
cmp eax, WM_SIZE
jz near .DWP_Size
cmp eax, WM_INITMENUPOPUP
jz near .DWP_InitMenuPopup
cmp eax, WM_COMMAND
jz near .DWP_Command
cmp eax, WM_CREATE
jz near .DWP_Create
cmp eax, WM_CLOSE
je near .DWP_Close
cmp eax, WM_QUERYENDSESSION
je near .DWP_Close
cmp eax, WM_DESTROY
jz near .DWP_Destroy
.DWP_DefWndProc:
; Send unhandled msg to DefWindowProc
invoke DefMDIChildProc, [DWP_hWnd], [DWP_wMsg], [DWP_wParam], [DWP_lParam]
return eax
.DWP_Create:
; Alocate space for Document-specific data
invoke GetProcessHeap
invoke HeapAlloc, eax, 0, DOCDATA_size
test eax, eax
jnz .DWP_CreateAllocOK
invoke MessageBox, [hWnd], szErrAlloc, szAppName, MB_OK | MB_ICONSTOP
invoke ExitProcess, 1
.DWP_CreateAllocOK:
push ebx
mov ebx, eax
; Save pointer to "cbWndExtra"
invoke SetWindowLong, [DWP_hWnd], 0, eax
; Create EditBox
invoke CreateWindowEx, 0, szEdit, NULL,\
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER |\
ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,\
0, 0, 0, 0, [DWP_hWnd], ID_EDIT, [hInstance], NULL
; Save document data
mov [ebx + DOCDATA.hWndEdit], eax
mov [ebx + DOCDATA.bNeedSave], DWORD 0
; Terminate string with null character
mov [ebx + DOCDATA.szFileName], BYTE 0
mov [ebx + DOCDATA.szTitle], BYTE 0
; Save hWndEdit to stack
push eax
; Set Font
invoke CreateFontIndirect, LOGF
mov [ebx + DOCDATA.hFont], eax
pop ebx
invoke SendMessage, ebx, WM_SETFONT, eax, 0
; Set limit of EditBox and Set focus
invoke SendMessage, ebx, EM_SETLIMITTEXT, -1, 0
invoke SetFocus, ebx
pop ebx
jmp .DWP_Finish
.DWP_InitMenuPopup:
; Is window maximized?
lea eax, [DWP_bMaximized]
invoke SendMessage, [hWndMDI], WM_MDIGETACTIVE, 0, eax
mov eax, [DWP_bMaximized]
test eax, eax
mov eax, [DWP_lParam]
jz .DWPI_NotMaximized
; Window is maximized ==> we should count the icon on the left
dec eax
.DWPI_NotMaximized:
; Popup Menu switch
test eax,eax
jz .DWPI_File
dec eax
jz .DWPI_Edit
jmp .DWP_DefWndProc
; Init menu Popup "File" - menu item "Save"
.DWPI_File:
invoke GetWindowLong, [DWP_hWnd], 0
mov eax, [eax + DOCDATA.bNeedSave]
test eax, eax
jnz .DWPIF_NeedSave
invoke EnableMenuItem, [DWP_wParam], IDM_FILE_SAVE, MF_GRAYED
jmp .DWP_Finish
.DWPIF_NeedSave:
invoke EnableMenuItem, [DWP_wParam], IDM_FILE_SAVE, MF_ENABLED
jmp .DWP_Finish
; Ini menu Popup "Edit"
.DWPI_Edit:
push ebx
push ecx
invoke GetWindowLong, [DWP_hWnd], 0
mov eax, [eax + DOCDATA.hWndEdit]
push eax
; Test if "undo" is possible - menu item "undo"
invoke SendMessage, eax, EM_CANUNDO, 0, 0
test eax, eax
jnz .DWPIE_CanUndo
invoke EnableMenuItem, [DWP_wParam], IDM_EDIT_UNDO, MF_GRAYED
jmp .DWPIE_TestPaste
.DWPIE_CanUndo:
invoke EnableMenuItem, [DWP_wParam], IDM_EDIT_UNDO, MF_ENABLED
.DWPIE_TestPaste:
; Test if "paste" is possible - menu item "paste"
invoke IsClipboardFormatAvailable, CF_TEXT
test eax, eax
jnz .DWPIE_CanPaste
invoke EnableMenuItem, [DWP_wParam], IDM_EDIT_PASTE, MF_GRAYED
jmp .DWPIE_TestSel
.DWPIE_CanPaste:
invoke EnableMenuItem, [DWP_wParam], IDM_EDIT_PASTE, MF_ENABLED
.DWPIE_TestSel:
; Test if "cut" and "copy" are possible
pop ecx
lea eax, [DWP_iSelBeg]
lea ebx, [DWP_iSelEnd]
invoke SendMessage, ecx, EM_GETSEL, eax, ebx
mov eax, [DWP_iSelBeg]
cmp eax, [DWP_iSelEnd]
jnz .DWPIE_SelAvl
mov ebx, MF_GRAYED
jmp .DWPIE_Finish
.DWPIE_SelAvl:
mov ebx, MF_ENABLED
.DWPIE_Finish:
invoke EnableMenuItem, [DWP_wParam], IDM_EDIT_CUT, ebx
invoke EnableMenuItem, [DWP_wParam], IDM_EDIT_COPY, ebx
pop ecx
pop ebx
jmp .DWP_Finish
.DWP_Command:
; Menu Item switch
mov ax, [DWP_wParam]
cmp ax, IDM_FILE_SAVE
jz near .DWPC_FileSave
cmp ax, IDM_FILE_SAVEAS
jz near .DWPC_FileSaveAs
cmp ax, IDM_EDIT_UNDO
jz near .DWPC_EditUndo
cmp ax, IDM_EDIT_CUT
jz near .DWPC_EditCut
cmp ax, IDM_EDIT_COPY
jz near .DWPC_EditCopy
cmp ax, IDM_EDIT_PASTE
jz near .DWPC_EditPaste
cmp ax, IDM_EDIT_SELECTALL
jz near .DWPC_EditSelectAll
cmp ax, IDM_WINDOW_CLOSE
jz near .DWPC_WindowClose
cmp ax, ID_EDIT ; msg from EditBox
jz near .DWPC_EditBox
jmp .DWP_DefWndProc
.DWPC_FileSave:
; Get ptr to document data
invoke GetWindowLong, [DWP_hWnd], 0
push ebx
mov ebx, eax
; Test wether save existing file or create new
lea eax, [ebx + DOCDATA.szFileName]
call strcmp, eax, szUntiled
test eax, eax
jnz .DWPCFS_NotNew
; Create new file - invoke SaveAs Dialog
invoke SendMessage, [DWP_hWnd], WM_COMMAND, IDM_FILE_SAVEAS, 0
pop ebx
return eax
; Save existing file
.DWPCFS_NotNew:
lea eax, [ebx + DOCDATA.szFileName]
call DocSave, [DWP_hWnd], eax
test eax, eax
jnz .DWPCFS_Error
mov [ebx + DOCDATA.bNeedSave], DWORD 0
pop ebx
return 1
; Error during save
.DWPCFS_Error:
lea eax, [ebx + DOCDATA.szFileName]
invoke MessageBox, [DWP_hWnd], szErrSave, eax, MB_OK
pop ebx
return 0
.DWPC_FileSaveAs:
; Get ptr to document data
invoke GetWindowLong, [DWP_hWnd], 0
push ebx
mov ebx, eax
; Initialize SaveFile Dialog
lea eax, [ebx + DOCDATA.szFileName]
call strcpy, szFileName, eax, MAX_PATH
mov [OFN + OPENFILENAME.Flags], DWORD OFN_OVERWRITEPROMPT
; Invoke SaveFile Dialog
invoke GetSaveFileName, OFN
test eax, eax
jz near .DWPCSFA_Finish ; Cancel
; Save document text
call DocSave, [DWP_hWnd], szFileName
test eax, eax
jnz .DWPCSFA_Error
; Synchronize document-specific data
lea eax, [ebx + DOCDATA.szFileName]
call strcpy, eax, szFileName, MAX_PATH
lea eax, [ebx + DOCDATA.szTitle]
call strcpy, eax, szTitle, MAX_PATH
mov [ebx + DOCDATA.bNeedSave], DWORD 0
; Actualize window title
invoke SetWindowText, [DWP_hWnd], szTitle
pop ebx
return 1
; Error during SaveAs
.DWPCSFA_Error:
invoke MessageBox, [DWP_hWnd], szErrSave, szFileName, MB_OK | MB_ICONERROR
; SaveAs normal exit
.DWPCSFA_Finish:
pop ebx
jmp .DWP_Finish
.DWPC_EditUndo
invoke GetWindowLong, [DWP_hWnd], 0
invoke SendMessage, [eax + DOCDATA.hWndEdit], WM_UNDO, 0, 0
jmp .DWP_Finish
.DWPC_EditCut
invoke GetWindowLong, [DWP_hWnd], 0
invoke SendMessage, [eax + DOCDATA.hWndEdit], WM_CUT, 0, 0
jmp .DWP_Finish
.DWPC_EditCopy
invoke GetWindowLong, [DWP_hWnd], 0
invoke SendMessage, [eax + DOCDATA.hWndEdit], WM_COPY, 0, 0
jmp .DWP_Finish
.DWPC_EditPaste
invoke GetWindowLong, [DWP_hWnd], 0
invoke SendMessage, [eax + DOCDATA.hWndEdit], WM_PASTE, 0, 0
jmp .DWP_Finish
.DWPC_EditSelectAll
invoke GetWindowLong, [DWP_hWnd], 0
invoke SendMessage, [eax + DOCDATA.hWndEdit], EM_SETSEL, 0, -1
jmp .DWP_Finish
.DWPC_WindowClose:
invoke SendMessage, [DWP_hWnd], WM_CLOSE, 0, 0
jmp .DWP_Finish
; Message from EditBox
.DWPC_EditBox:
mov eax, [DWP_lParam]
test eax, eax
jz near .DWP_DefWndProc
; EditBox msg switch
mov ax, [DWP_wParam + 2]
cmp ax, EN_UPDATE
je .DWPCE_Update
cmp ax, EN_ERRSPACE
je .DWPCE_Limit
cmp ax, EN_MAXTEXT
je .DWPCE_Limit
jmp .DWP_DefWndProc
; Update msg from EditBox
.DWPCE_Update:
invoke GetWindowLong, [DWP_hWnd], 0
mov [eax + DOCDATA.bNeedSave], DWORD 1
jmp .DWP_Finish
; Error msg from EditBox
.DWPCE_Limit:
invoke MessageBox, [DWP_hWnd], szErrLimit, szAppName, MB_OK | MB_ICONSTOP
jmp .DWP_Finish
.DWP_SetFocus:
; Set Focus to EditBox
invoke GetWindowLong, [DWP_hWnd], 0
invoke SetFocus, [eax + DOCDATA.hWndEdit]
jmp .DWP_DefWndProc
.DWP_Size:
; Set size of the EditBox
invoke GetWindowLong, [DWP_hWnd], 0
push edx
push 1
xor edx,edx
mov dx, [DWP_lParam + 2]
push edx
xor edx,edx
mov dx, [DWP_lParam]
push edx
invoke MoveWindow, [eax + DOCDATA.hWndEdit], 0, 0
pop edx
jmp .DWP_DefWndProc
; Also WM_QUERYENDSESSION
.DWP_Close:
; Does the document need to be saved?
invoke GetWindowLong, [DWP_hWnd], 0
mov eax, [eax + DOCDATA.bNeedSave]
test eax, eax
jz near .DWP_DefWndProc
; Ask for save...
invoke GetWindowLong, [DWP_hWnd], 0
add eax, DOCDATA.szFileName
invoke MessageBox, [DWP_hWnd], szAskForSave, eax, MB_YESNOCANCEL | MB_ICONQUESTION
cmp eax, IDCANCEL
je near .DWP_Finish
cmp eax, IDYES
je .DWP_CloseSave
jmp .DWP_DefWndProc
.DWP_CloseSave:
; Send "save" command to this wnd
invoke SendMessage, [DWP_hWnd], WM_COMMAND, IDM_FILE_SAVE, 0
test eax, eax
jz near .DWP_Finish
jmp .DWP_DefWndProc
.DWP_Destroy
; Get ptr to document data
invoke GetWindowLong, [DWP_hWnd], 0
push ebx
mov ebx, eax
; Delete font
invoke DeleteObject, [ebx + DOCDATA.hFont]
; Free space for document-specific data
; Nobody should ponit to it now
invoke GetProcessHeap
invoke HeapFree, eax, 0, ebx
dec DWORD [iWndCount]
pop ebx
jmp .DWP_DefWndProc
.DWP_Finish:
return 0
end ;DocWndProc
; Close child windows using WM_QUERYENDSESSION
function EPClose, EPC_hWnd, EPC_lParam
begin
; Restore native window size
invoke GetParent, [EPC_hWnd]
push ebx
mov ebx, eax
invoke SendMessage, ebx, WM_MDIRESTORE, [EPC_hWnd], 0
; Ask child window for exit
invoke SendMessage, [EPC_hWnd], WM_QUERYENDSESSION, 0, 0
test eax, eax
jz .EPC_Finish
; Close the child window
invoke SendMessage, ebx, WM_MDIDESTROY, [EPC_hWnd], 0
.EPC_Finish:
pop ebx
return 1
end
; Create child window
; Several global variables should be set.. Return hWnd of child window..
CreateChild:
; Test for windows count limit
cmp DWORD [iWndCount], MAX_WIN_COUNT
jl .CC_LimitOK
xor eax, eax
ret
.CC_LimitOK:
inc DWORD [iWndCount]
; Is here any child window?
invoke SendMessage, [hWndMDI], WM_MDIGETACTIVE, 0, 0
test eax, eax
jz .CC_FirstChild
; Create new window with normal size
mov [MDICreate + MDICREATESTRUCT.style], DWORD 0
jmp .CC_CreateChild
.CC_FirstChild:
; Create new window maximized (1st window)
mov [MDICreate + MDICREATESTRUCT.style], DWORD WS_MAXIMIZE
.CC_CreateChild
; Create window now
invoke SendMessage, [hWndMDI], WM_MDICREATE, 0, MDICreate
ret
; Look for document with same FileName as lParam
function EPMatchFile, EPMF_hWnd, EPMF_lParam
begin
; Test for valid hWnd
mov eax, [EPMF_hWnd]
test eax, eax
jz near .EPMF_Finish
; Test for WndProc
invoke GetWindowLong, [EPMF_hWnd], GWL_WNDPROC
cmp eax, DocWndProc
jnz .EPMF_Finish
; Get ptr to document data
invoke GetWindowLong, [EPMF_hWnd], 0
; Compare FileName
lea eax, [eax + DOCDATA.szFileName]
call strcmp, eax, [EPMF_lParam]
test eax, eax
jnz .EPMF_Finish
; FileName found
return 0
.EPMF_Finish:
return 1
end
; Load document text
; Several data structures should be initialized
function DocLoad, DL_hWnd
var DL_hFile, DL_iLength, DL_pBuff, DL_cbRead
begin
; Get pointer to document-specific data
invoke GetWindowLong, [DL_hWnd], 0
push ebx
mov ebx, eax
; Open File
lea eax, [ebx + DOCDATA.szFileName]
invoke CreateFile, eax, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM, NULL
cmp eax, INVALID_HANDLE_VALUE
jz near .DL_ErrOpenFile
mov [DL_hFile], eax
; Get file size
invoke GetFileSize, eax, NULL
inc eax ; one byte for zero character
mov [DL_iLength], eax
; Alloc buffer
invoke GetProcessHeap
invoke HeapAlloc, eax, 0, [DL_iLength]
test eax, eax
jz .DL_ErrAlloc
mov [DL_pBuff], eax
; Read data from file
dec DWORD [DL_iLength]
lea eax, [DL_cbRead]
invoke ReadFile, [DL_hFile], [DL_pBuff], [DL_iLength], eax, NULL
; Close File
invoke CloseHandle, [DL_hFile]
; End with zero character
mov eax, [DL_pBuff]
add eax, [DL_iLength]
mov [eax], BYTE 0
; Load text to document window
invoke SetWindowText, [ebx + DOCDATA.hWndEdit], [DL_pBuff]
pop ebx
; Free buffer
invoke GetProcessHeap
invoke HeapFree, eax, 0, [DL_pBuff]
return 0
; Could not open file
.DL_ErrOpenFile:
pop ebx
return -1
; Could not allocate buffer
.DL_ErrAlloc:
invoke CloseHandle, [DL_hFile]
pop ebx
return -1
end ; DocLoad
; Save document text to file DS_szFileName
function DocSave, DS_hWnd, DS_szFileName
var DS_dwFileAttr, DS_hFile, DS_iLength, DS_pBuff, DS_cbWrite
begin
; Get File attributes
invoke GetFileAttributes, [DS_szFileName]
mov [DS_dwFileAttr], eax
inc eax
jnz .DS_FileExist
; New file is being created
mov [DS_dwFileAttr], DWORD FILE_ATTRIBUTE_NORMAL
jmp .DS_AttrOK
.DS_FileExist
; Check if file is ReadOnly
test [DS_dwFileAttr], DWORD FILE_ATTRIBUTE_READONLY
jz .DS_ARO_OK
; File is ReadOnly
invoke MessageBox, [DS_hWnd], szErrAttrRO, [DS_szFileName], MB_OKCANCEL | MB_ICONWARNING | MB_DEFBUTTON2
cmp eax, IDCANCEL
je near .DS_ErrAttr
.DS_ARO_OK:
; Check if file is SystemFile
test [DS_dwFileAttr], DWORD FILE_ATTRIBUTE_SYSTEM
jz .DS_ASYS_OK
; File is system file
invoke MessageBox, [DS_hWnd], szErrAttrSYS, [DS_szFileName], MB_OKCANCEL | MB_ICONWARNING | MB_DEFBUTTON2
cmp eax, IDCANCEL
je near .DS_ErrAttr
.DS_ASYS_OK:
; Temporarry reset attributes to Normal
invoke SetFileAttributes, [DS_szFileName], FILE_ATTRIBUTE_NORMAL
.DS_AttrOK:
; Open or create file
invoke CreateFile, [DS_szFileName], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, [DS_dwFileAttr], NULL
cmp eax, INVALID_HANDLE_VALUE
jz near .DS_ErrOpenFile
mov [DS_hFile], eax
; Get pointer to document-specific data
invoke GetWindowLong, [DS_hWnd], 0
push ebx
mov ebx, eax
; Get Length of document text
invoke GetWindowTextLength, [ebx + DOCDATA.hWndEdit]
inc eax
mov [DS_iLength], eax
; Alloc buffer
invoke GetProcessHeap
invoke HeapAlloc, eax, 0, [DS_iLength]
test eax, eax
jz .DS_ErrAlloc
mov [DS_pBuff], eax
; Get document text
invoke GetWindowText, [ebx + DOCDATA.hWndEdit], [DS_pBuff], [DS_iLength]
dec DWORD [DS_iLength]
; Write text to file
lea eax, [DS_cbWrite]
invoke WriteFile, [DS_hFile], [DS_pBuff], [DS_iLength], eax, NULL
; Close file
invoke CloseHandle, [DS_hFile]
; Free buffer
invoke GetProcessHeap
invoke HeapFree, eax, 0, [DS_pBuff]
; Normal Exit
pop ebx
return 0
; User is worried :-)
.DS_ErrAttr:
return -1
; Could not open file
.DS_ErrOpenFile:
invoke SetFileAttributes, [DS_szFileName], [DS_dwFileAttr]
return -1
; Could not allocate buffer
.DS_ErrAlloc:
invoke CloseHandle, [DL_hFile]
invoke SetFileAttributes, [DS_szFileName], [DS_dwFileAttr]
pop ebx
return -1
end
; strcmp()
function strcmp, strcmp_dest, strcmp_src
begin
push esi
push edi
push edx
mov edi, [strcmp_dest]
mov esi, [strcmp_src]
xor edx, edx
.strcmp_Loop:
xor al,al ; al = 0
; Compare src for zero
cmp al,[esi]
je .strcmp_LoopEnd
; Compare dest for zero
cmp al,[edi]
je .strcmp_LoopEnd
; Compare (src ?? dest)
mov al,[edi]
cmp al,[esi]
jbe .strcmp_NotSrc
; dest > src
inc edx
jmp .strcmp_Finish
.strcmp_NotSrc:
jae .strcmp_NotDest
; dest < src
dec edx
jmp .strcmp_Finish
.strcmp_NotDest:
; Go to next char
inc esi
inc edi
jmp .strcmp_Loop
.strcmp_LoopEnd:
; Compare strlen of src and dest
mov al,[edi]
cmp al,[esi]
jbe .strcmp_NotLen
; dest > src
inc edx
jmp .strcmp_Finish
.strcmp_NotLen:
jae .strcmp_Finish
; src < dec
dec edx
.strcmp_Finish:
; Save return value
mov eax,edx
pop edx
pop edi
pop esi
return eax
end
; strcpy ()
; 1. parameter - dest
; 2. parameter - src
; 3. parameter - size of dest array
; return 0 if copy whole string
function strcpy, strcpy_dest, strcpy_src, strcpy_max
begin
push esi
mov esi, [strcpy_src]
push edi
mov edi, [strcpy_dest]
push ecx
mov ecx, [strcpy_max]
xor eax, eax
.strcpy_Loop:
; copy byte
mov al, [esi]
mov [edi], al
; test for zero
test al, al
jz .strcpy_LoopExit
; increment index registers
inc esi
inc edi
; main loop
loop .strcpy_Loop
.strcpy_LoopExit:
pop ecx
pop edi
pop esi
return eax
end