ICZelion Tut35

zhaozj2021-02-11  230

Tutorial 35: Richedit Control: Syntax Hilighting

Before Reading this Tutorial, Let Me Warn You That's A Complicated Subject: NOT SUITED For a Beginner. This is The last in the richedit control tutorials.

Download The Example.

THEORY

Syntax hilighting is a subject of hot debate for those writing text editors. The best method (in my opinion) is to code a custom edit control and this is the approach taken by lots of commercial softwares. However, for those of us who don ' T Have Time for Coding Such Control, The Next Best Thing Is To Adapt The Existing Control To Make It Suit Our NEED.

Let us take a look at what RichEdit control provides to help us in implementing syntax hilighting I should state at this moment that the following method is not the "correct" path:.. I just want to show you the pitfall that many fall for RichEdit control provides EM_SETCHARFORMAT message that you can use to change the color of the text. At first glance, this message seems to be the perfect solution (I know because I was one of the victim). However, a closer examination will show you several things That Are Undesirable:

EM_SETCHARFORMAT only works for a text currently in selection or all text in the control. If you want to change the text color (hilight) a certain word, you must first select it. EM_SETCHARFORMAT is very slow It has a problem with the caret position in The Richedit Control

WITH The Above Discussion, You Can See That Using EM_SETCHARFORMAT IS A WRONG Choice. I'll show you the "relatively correct" choice.

The method I currently use is "syntax hilighting just-in-time". I'll hilight only the visible portion of text. Thus the speed of the hilighting will not be related to the size of the file at all. No matter how large The File, Only A Small Portion of It Is Visible At One Time.how To Do That? The Answer IS Simple:

subclass the richedit control and handle WM_PAINT message within your own window procedure When it receives WM_PAINT message, it calls the original window procedure of the richedit control to let it update the screen as usual. After that, we overwrite the words to be hilighted with different Color

Of Course, The Road is Not That Easy: There Still A Couple of Minor Things To FIX But The Above Method Works Quite Nice Seatisfactory.

Now let's concentrate on the detail. The subclassing process is simple and does not require much attention. The really complicated part is when we have to find a fast way of searching for the words to be hilighted. This is further complicated by the need not To Hilight Any Word Withnin A Comment Block.

The Method I Use May Not Be The Best But IT Works OK. I'm Sure You CAN Find A Faster Way. Anyway, Here IT IS:

I create a 256 dword array, initialized to 0. Each dword corresponds to a possible ASCII character, named ASMSyntaxArray For example, the 21th dword represents the ascii 20h (space) I use them as a fast lookup table:.. For example, if i have the word "include", i'll extract the first character (i) from the word and look up the dword at the corresponding index. If that dword is 0, i know immediately that there is no words to be hilighted starting with "i". If the dword is non-zero, it contains the pointer to the linked list of the WORDINFO structure which contains the information about the word to be hilighted. I read the words to be hilighted and create a WORDINFO structure for each of Them.WordInfo Struct

Wordlen Dd?; The Length of The Word: Used As a Quick Comparison

PSZWORD DD?; Pointer to the Word

PCOLOR DD?; Point To the Dword That Contains The Color Used to Hilite The Word

NEXTLINK DD?; Point to the next WordInfo Structure

WordInfo Ends

As you can see, I use the length of the word as the second quick comparison. If the first character of the word matches, we next compare its length to the available words. Each dword in ASMSyntaxArray contains a pointer to the head of the associated WORDINFO array. For example, the dword that represents the character "i" will contain the pointer to the linked list of the words that begin with "i". pColor member points to the dword that contains the color value used to hilight the word. Pszword Points to the Word To Be Hilighted, in LowerCase.

.

The word list is stored in a file named "wordfile.txt" and I access it with GetPrivateProfileString APIs. I provide as many as 10 different syntax coloring, starting from C1 to C10. The color array is named ASMColorArray. PColor member of each WORDINFO structure points to one of the dwords in ASMColorArray Thus it is easy to change the syntax coloring on the fly:. you just change the dword in ASMColorArray and all words using that color will use the new color immediately.Example

.386

.Model flat, stdcall

Option CaseMAP: NONE

INCLUDE /MASM32/INCLUDE/Windows.inc

INCLUDE /MASM32/INCLUDE/USER32.INC

INCLUDE /MASM32/INCLUDE/COMDLG32.INC

INCLUDE /MASM32/INCLUDE/gdi32.inc

INCLUDE /MASM32/INCLUDE / WANEL32.INC

INCLUDELIB /MASM32/LIB/GDI32.LIB

INCLUDELIB /MASM32/LIB/COMDLG32.LIB

INCLUDELIB /MASM32/LIB/USER32.LIB

INCLUDELIB /MASM32/LIB/kernel32.lib

Winmain Proto: DWORD,: DWORD,: DWORD,: DWORD

WordInfo Struct

Wordlen Dd?; The Length of The Word: Used As a Quick Comparison

PSZWORD DD?; Pointer to the Word

PCOLOR DD?; Point To the Dword That Contains The Color Used to Hilite The Word

NEXTLINK DD?; Point to the next WordInfo Structure

WordInfo Ends

.const

IDR_MAINMENU EQU 101

IDM_Open EQU 40001

IDM_SAVE EQU 40002

IDM_Close EQU 40003

IDM_SAVEAS EQU 40004

IDM_EXIT EQU 40005

IDM_COPY EQU 40006

IDM_CUT EQU 40007

IDM_PASTE EQU 40008

IDM_DELETE EQU 40009

IDM_SELECTALL EQU 40010

IDM_OPTION EQU 40011

IDM_UNDO EQU 40012

IDM_REDO EQU 40013

IDD_OPTIONDLG EQU 101IDC_BACKCOLORBOX EQU 1000

IDC_TextColorBox EQU 1001

IDR_MAINACCEL EQU 105

IDD_FINDDLG EQU 102

IDD_GOTODLG EQU 103

IDD_REPLACEDLG EQU 104

IDC_FindEdit EQU 1000

IDC_MatchCase EQU 1001

IDC_ReplaceEdit EQU 1001

IDC_WholeWord EQU 1002

IDC_DOWN EQU 1003

IDC_UP EQU 1004

IDC_LINENO EQU 1005

IDM_FIND EQU 40014

IDM_FINDNEXT EQU 40015

IDM_REPLACE EQU 40016

IDM_GOTOLINE EQU 40017

IDM_FINDPREV EQU 40018

Richeditid EQU 300

.DATA

ClassName DB "iczeditclass", 0

Appname DB "iczedit Version 3.0", 0

Richeditdll DB "Riched20.dll", 0

Richeditclass DB "Richedit20a", 0

Norichedit DB "Cannot Find Riched20.dll", 0

Asmfilterstring DB "ASM Source Code (* .asm)", 0, "*. ASM", 0

DB "all files (*. *)", 0, "*. *", 0, 0

OpenFileFail DB "Cannot Open THE FILE", 0

Wannasave DB "The Data IN THE CONTOL IS MODIFIED. WANT TO SAVE IT?", 0

FILEOPENED DD FALSE

BackgroundColor DD 0FFFFFFH; Default to White

TextColor DD 0; Default to Black

WordFileName DB "/wordfile.txt" ,0

Asmsection DB "assembly", 0

C1key DB "C1", 0

C2key DB "C2", 0

C3key DB "C3", 0

C4key DB "C4", 0

C5key DB "C5", 0

C6key DB "C6", 0

C7key DB "C7", 0

C8key DB "C8", 0

C9key DB "C9", 0

C10key DB "C10", 0

Zerostring DB 0

ASMCOLORARRAY DD 0FF0000H, 0805F50H, 0FFH, 666F00H, 44F0H, 5F8754H, 4 DUP (0FF0000H) CommentColor DD 808000H

.DATA?

Hinstance DD?

HRICHEDIT DD?

HWNDRICHEDIT DD?

FILENAME DB 256 DUP (?)

AlternateFileName DB 256 DUP (?)

Customcolors DD 16 DUP (?)

FindBuffer DB 256 DUP (?)

ReplaceBuffer DB 256 DUP (?)

UFLAGS DD?

FindText Findtextex <>

ASMSYNTAXARRAY DD 256 DUP (?)

HSEARCH DD?; Handle to The Search / Replace Dialog Box

Haccel DD?

Hmainheap dd?; Heap Handle

OldWndProc DD?

Richeditversion DD?

.code

Start:

MOV BYTE PTR [Findbuffer], 0

MOV BYTE PTR [ReplaceBuffer], 0

Invoke getModuleHandle, NULL

Mov Hinstance, EAX

Invoke Loadlibrary, AddR Richeditdll

.IF EAX! = 0

Mov HrichEdit, EAX

Invoke getProcessHeap

Mov Hmainheap, EAX

Call FillhiliteInfo

Invoke Winmain, Hinstance, 0, 0, SW_SHOWDEFAULT

Invoke Freelibrary, HrichEdit

.lse

Invoke Messagebox, 0, AddR Norichedit, Addr Appname, MB_OK OR MB_ICONERROR

.endif

Invoke EXITPROCESS, EAX

Winmain Proc Hinst: DWORD, HPREVINST: DWORD, CMDLINE: DWORD, CMDSHOW: DWORD

Local WC: WNDCLASSEX

Local MSG: MSG

Local hwnd: DWORD

Mov wc.cbsize, sizeof wndclassex

Mov wc.style, CS_HREDRAW or CS_VREDRAW

Mov wc.lpfnwndproc, Offset WndProc

Mov wc.cbclsextra, NULL

Mov wc.cbwndextra, null

Push hinst

POP wc.hinstance

Mov wc.hbrbackground, Color_Window 1

Mov wc.lpszMenuname, IDR_MainMenu

MOV wc.lpszclassname, Offset ClassName

Invoke Loadicon, NULL, IDI_APPLICATION

Mov wc.hicon, EAX

Mov wc.hiconsm, EAX

Invoke loadcursor, null, IDC_ARROW

Mov wc.hcursor, EAX

Invoke RegisterClassex, Addr WC

INVOKE CreateWindowEx, NULL, ADDR ClassName, ADDR AppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULLmov hwnd, eax

Invoke ShowWindow, Hwnd, SW_SHOWNORMAL

Invoke UpdateWindow, HWnd

Invoke loadingAccelerators, Hinstance, IDR_MAINACCEL

Mov Haccel, EAX

.While true

Invoke GetMessage, Addr MSG, 0,0,0

.break .if (! EAX)

Invoke isDialogmessage, HSearch, Addr MSG

.IF EAX == false

Invoke TranslateAccelerator, HWnd, Haccel, Addr MSG

.IF EAX == 0

Invoke TranslateMessage, Addr MSG

Invoke DispatchMessage, Addr MSG

.endif

.endif

.endw

Mov Eax, Msg.wParam

RET

Winmain ENDP

StreamInproc Proc Hfile: DWORD, PBUFFER: DWORD, Numbytes: DWORD, PBYTESREAD: DWORD

Invoke Readfile, Hfile, Pbuffer, Numbytes, Pbytesread, 0

XOR Eax, 1

RET

StreaminProc ENDP

StreamoutProc Proc Hfile: DWORD, PBUFFER: DWORD, Numbytes: DWORD, PBYTESWRITEN: DWORD

Invoke Writefile, Hfile, Pbuffer, Numbytes, Pbyteswritten, 0

XOR Eax, 1

RET

StreamoutProc ENDP

CheckModifyState Proc HWND: DWORD

Invoke SendMessage, Hwndrichedit, EM_GETMODIFY, 0, 0

.IF EAX! = 0

Invoke Messagebox, Hwnd, Addr Wannasave, Addr Appname, MB_YESNOCANCEL

.IF eax == iDYES

Invoke SendMessage, Hwnd, WM_Command, IDM_SAVE, 0

.ELSEIF EAX == Idcancel

Mov Eax, False

RET

.endif

.endif

Mov Eax, True

RET

CheckModifyState Endp

SetColor Proc

Local CFM: CharFormat

Invoke SendMessage, Hwndrichedit, EM_SETBKGNDCOLOR, 0, BackgroundColor

Invoke RTLZERMEMORY, AddR CFM, Sizeof CFM

Mov Cfm.cbsize, Sizeof CFM

Mov cfm.dwmask, cfm_color

Push TextColor

POP cfm.crtextColor

Invoke SendMessage, Hwndrichedit, EM_SETCHARFORMAT, SCF_ALL, ADDR CFM

RET

SetColor ENDP

Optionproc Proc HWND: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

Local CLR: Choosecolor.if umsg == WM_INITDIALOG

.ELSEIF uMSG == WM_COMMAND

Mov Eax, WPARAM

SHR EAX, 16

.IF AX == BN_Clicked

Mov Eax, WPARAM

.IF AX == idcancel

Invoke SendMessage, HWnd, WM_Close, 0, 0

.ELSEIF AX == IDC_BACKCOLORBOX

Invoke RTLZERMEMORY, ADDR CLR, SIZEOF CLR

Mov CLR.LSTRUCTSIZE, SIZEOF CLR

Push hwnd

POP CLR.HWNDOWNER

Push hinstance

POP CLR.HINSTANCE

Push Backgroundcolor

POP CLR.RGBRESULT

Mov CLR.LPCustColors, Offset Customcolors

Mov CLR.FLAGS, CC_Anycolor or CC_RGBINIT

Invoke Choosecolor, AddR CLR

.IF EAX! = 0

Push CLR.RGBRESULT

Pop BackgroundColor

Invoke getdlgitem, hwnd, idc_backcolorbox

Invoke InvalidateERECT, EAX, 0, TRUE

.endif

.ELSEIF AX == IDC_TextColorBox

Invoke RTLZERMEMORY, ADDR CLR, SIZEOF CLR

Mov CLR.LSTRUCTSIZE, SIZEOF CLR

Push hwnd

POP CLR.HWNDOWNER

Push hinstance

POP CLR.HINSTANCE

Push TextColor

POP CLR.RGBRESULT

Mov CLR.LPCustColors, Offset Customcolors

Mov CLR.FLAGS, CC_Anycolor or CC_RGBINIT

Invoke Choosecolor, AddR CLR

.IF EAX! = 0

Push CLR.RGBRESULT

Pop TextColor

Invoke getdlgitem, hwnd, idc_textcolorbox

Invoke InvalidateERECT, EAX, 0, TRUE

.endif

.ELSEIF AX == IDOK

Invoke SendMessage, Hwndrichedit, EM_GETMODIFY, 0, 0

Push EAX

Invoke setColor

POP EAX

Invoke SendMessage, Hwndrichedit, EM_SETMODIFY, EAX, 0

Invoke EndDialog, HWND, 0

.endif

.endif

.ELSEIF uMSG == WM_CTLCOLORSTATIC

Invoke getdlgitem, hwnd, idc_backcolorbox

.IF EAX == LPARAM

Invoke Createsolidbrush, BackgroundColor

RET

.lse

Invoke getdlgitem, hwnd, idc_textcolorbox

.IF EAX == LPARAM

Invoke Createsolidbrush, TextColor

RET

.endif

.endif

Mov Eax, False

RET

.ELSEIF uMSG == WM_Close

Invoke EndDialog, HWND, 0

.lse

Mov Eax, False

RET

.endif

Mov Eax, True

RET

OptionProc ENDP

SearchProc Proc Hwnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

.IF uMSG == WM_INITDIALOG

Push hwnd

POP HSEARCH

Invoke CheckRadiobutton, HWnd, IDC_Down, IDC_UP, IDC_DOWN

Invoke Senddlgitemmessage, HWnd, IDC_Findedit, WM_SETTEXT, 0, AddR Findbuffer

.ELSEIF uMSG == WM_COMMAND

Mov Eax, WPARAM

SHR EAX, 16

.IF AX == BN_Clicked

Mov Eax, WPARAM

.IF AX == iDOK

Mov uflags, 0

Invoke SendMessage, Hwndrichedit, EM_EXGETSEL, 0, AddR FindText.chrg

Invoke getdlgitemtext, hwnd, idc_findedit, AddR Findbuffer, Sizeof Findbuffer

.IF EAX! = 0

Invoke isdlgbuttonchecked, hwnd, idc_down

.IF eax == bst_checked

Or uflags, fr_down

Mov Eax, FindText.chrg.cpmin

.IF EAX! = FindText.chrg.cpmax

Push FindText.chrg.cpmax

POP FindText.chrg.cpmin

.endif

MOV Findtext.chrg.cpmax, -1

.lse

MOV Findtext.chrg.cpmax, 0

.endif

Invoke isdlgbuttonchecked, hwnd, idc_matchcase

.IF eax == bst_checked

Or uflags, fr_matchcase

.endif

Invoke isdlgbuttonchecked, hwnd, idc_wholeword

.IF eax == bst_checked

Or uflags, fr_wholeword

.endif

MOV FindText.lpstrText, Offset Findbuffer

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, UFLAGS, AddR Findtext

.IF EAX! = - 1

Invoke SendMessage, HwndrichEdit, EM_EXSETSEL, 0, AddR FindText.chrgtext

.endif

.endif

.ELSEIF AX == IDCANCEL

Invoke SendMessage, HWnd, WM_Close, 0, 0

.lse

Mov Eax, False

RET

.endif

.endif

.ELSEIF uMSG == WM_Close

Mov HSearch, 0

Invoke EndDialog, HWND, 0

.lse

Mov Eax, False

RET

.endif

Mov Eax, True

RET

SearchProc ENDP

ReplaceProc Proc HWND: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

Local setText: SetTextex

.IF uMSG == WM_INITDIALOG

Push hwnd

POP HSEARCH

Invoke setdlgitemtext, hwnd, idc_findedit, addr findbufferinvoke setdlgitemtext, hwnd, idc_replaceedit, addr replacebuffer

.ELSEIF uMSG == WM_COMMAND

Mov Eax, WPARAM

SHR EAX, 16

.IF AX == BN_Clicked

Mov Eax, WPARAM

.IF AX == idcancel

Invoke SendMessage, HWnd, WM_Close, 0, 0

.ELSEIF AX == IDOK

Invoke getdlgitemtext, hwnd, idc_findedit, AddR Findbuffer, Sizeof Findbuffer

Invoke getdlgitemtext, hwnd, idc_replaceEdit, AddR ReplaceBuffer, Sizeof ReplaceBuffer

Mov Findtext.chrg.cpmin, 0

MOV Findtext.chrg.cpmax, -1

MOV FindText.lpstrText, Offset Findbuffer

Mov setText.Flags, ST_SELECTION

MOV setText.codepage, CP_ACP

.While true

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, fr_down, addr findxt

.IF EAX == - 1

.break

.lse

Invoke SendMessage, HwndrichEdit, EM_EXSETSEL, 0, AddR FindText.chrgtext

Invoke SendMessage, Hwndrichedit, EM_SETTEXTEX, ADDR Settext, Addr ReplaceBuffer

.endif

.endw

.endif

.endif

.ELSEIF uMSG == WM_Close

Mov HSearch, 0

Invoke EndDialog, HWND, 0

.lse

Mov Eax, False

RET

.endif

Mov Eax, True

RET

ReplaceProc ENDP

Gotoproc Proc Hwnd: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

LOCAL LINENO: DWORD

Local Chrg: Charrange

.IF uMSG == WM_INITDIALOG

Push hwnd

POP HSEARCH

.ELSEIF uMSG == WM_COMMAND

Mov Eax, WPARAM

SHR EAX, 16

.IF AX == BN_Clicked

Mov Eax, WPARAM

.IF AX == idcancel

Invoke SendMessage, HWnd, WM_Close, 0, 0

.ELSEIF AX == IDOK

Invoke getdlgitemint, hwnd, IDC_LINENO, NULL, FALSE

Mov Lineno, EAX

Invoke SendMessage, Hwndrichedit, EM_GETLINECUNT, 0, 0

.IF EAX> Lineno

Invoke SendMessage, Hwndrichedit, EM_LINEINDEX, LINENO, 0

Invoke SendMessage, Hwndrichedit, EM_SETSEL, EAX, EAX

Invoke setfocus, HWNDRICHEDIT

.endif

.endif

.endif

.ELSEIF uMSG == WM_Closemov HSearch, 0

Invoke EndDialog, HWND, 0

.lse

Mov Eax, False

RET

.endif

Mov Eax, True

RET

Gotoproc ENDP

PrepareEditmenu Proc Hsubmenu: DWORD

Local Chrg: Charrange

Invoke SendMessage, Hwndrichedit, EM_CANPASTE, CF_TEXT, 0

.IF EAX == 0; No Text in the clipboard

Invoke EnableMenuItem, HSubmenu, IDM_Paste, MF_GRAYED

.lse

Invoke EnableMenuItem, HSubmenu, IDM_Paste, MF_ENABLED

.endif

Invoke SendMessage, Hwndrichedit, EM_CANUNDO, 0, 0

.IF EAX == 0

Invoke EnableMenuItem, HSubmenu, IDM_UNDO, MF_GRAYED

.lse

Invoke EnableMenuItem, HSubmenu, IDM_UNDO, MF_ENABLED

.endif

Invoke SendMessage, Hwndrichedit, EM_CANREDO, 0, 0

.IF EAX == 0

Invoke EnableMenuItem, Hsubmenu, IDM_REDO, MF_GRAYED

.lse

Invoke EnableMenuItem, HSubmenu, IDM_REDO, MF_ENABLED

.endif

Invoke SendMessage, Hwndrichedit, EM_EXGETSEL, 0, AddR chrg

Mov Eax, Chrg.cpmin

.IF eax == chrg.cpmax; no current selection

Invoke EnableMenuItem, HSubmenu, IDM_COPY, MF_GRAYED

Invoke EnableMenuItem, HSubmenu, IDM_CUT, MF_GRAYED

Invoke EnablemenuItem, HSubmenu, IDM_DELETE, MF_GRAYED

.lse

Invoke EnableMenuItem, HSubmenu, IDM_COPY, MF_ENABLED

Invoke EnableMenuItem, HSubmenu, IDM_CUT, MF_ENABLED

Invoke EnableMenuItem, HSubmenu, IDM_DELETE, MF_ENABLED

.endif

RET

PrepareEDitMenu ENDP

Parsebuffer Proc Uses Edi ESI HHEAP: DWORD, PBUFFER: DWORD, NSIZE: DWORD, ARRAYOFFSET: DWORD, PARRAY: DWORD

Local buffer [128]: BYTE

Local Inprss: DWORD

Mov Inprogress, False

Lea ESI, Buffer

Mov EDI, PBuffer

Invoke Charlower, EDI

MOV ECX, NSIZE

Searchloop:

OR ECX, ECX

JZ Finished

CMP Byte PTR [EDI], ""

Je endofword

CMP Byte PTR [EDI], 9; TAB

Je endofword

Mov Inprogress, True

Mov Al, Byte Ptr [EDI]

MOV BYTE PTR [ESI], Al

Inc ESI

Skipit:

Inc EDI

Dec ECX

JMP Searchloopendofword:

CMP Inprogress, True

JE WordFound

JMP Skipit

WordFound:

MOV Byte Ptr [ESI], 0

Push ECX

Invoke Heapalloc, Hheap, Heap_Zero_Memory, Sizeof WordInfo

PUSH ESI

Mov ESI, EAX

Assume ESI: PTR WordInfo

Invoke Lstrlen, AddR Buffer

MOV [ESI]. Wordlen, EAX

Push arrayoffset

POP [ESI] .pcolor

INC EAX

Invoke Heapalloc, Hheap, Heap_Zero_Memory, EAX

MOV [ESI] .pszword, EAX

Mov Edx, EAX

Invoke Lstrcpy, EDX, AddR Buffer

Mov Eax, Parray

Movzx EDX, Byte Ptr [Buffer]

SHL EDX, 2; Multiply by 4

Add Eax, EDX

.IF DWORD PTR [EAX] == 0

Mov DWORD PTR [EAX], ESI

.lse

Push DWORD PTR [EAX]

POP [ESI] .NextLink

Mov DWORD PTR [EAX], ESI

.endif

POP ESI

POP ECX

Lea ESI, Buffer

Mov Inprogress, False

JMP Skipit

Finished:

.IF inprogress == true

Invoke Heapalloc, Hheap, Heap_Zero_Memory, Sizeof WordInfo

PUSH ESI

Mov ESI, EAX

Assume ESI: PTR WordInfo

Invoke Lstrlen, AddR Buffer

MOV [ESI]. Wordlen, EAX

Push arrayoffset

POP [ESI] .pcolor

INC EAX

Invoke Heapalloc, Hheap, Heap_Zero_Memory, EAX

MOV [ESI] .pszword, EAX

Mov Edx, EAX

Invoke Lstrcpy, EDX, AddR Buffer

Mov Eax, Parray

Movzx EDX, Byte Ptr [Buffer]

SHL EDX, 2; Multiply by 4

Add Eax, EDX

.IF DWORD PTR [EAX] == 0

Mov DWORD PTR [EAX], ESI

.lse

Push DWORD PTR [EAX]

POP [ESI] .NextLink

Mov DWORD PTR [EAX], ESI

.endif

POP ESI

.endif

RET

ParseBuffer Endp

FillhiliteInfo Proc Uses Edi

Local Buffer [1024]: Byte

Local PTEMP: DWORD

Local Blocksize: DWORD

Invoke RTLZERMEMORY, AddR AsmsyntaxArray, Sizeof AsmsyntaxArray

Invoke GetModuleFileName, Hinstance, Addr Buffer, Sizeof Buffer

Invoke Lstrlen, AddR Buffer

MOV ECX, EAX

Dec ECX

Lea Edi, Buffer

Add Edi, ECX

STD

MOV Al, "/"

Repne scaSB

CLD

Inc EDI

MOV Byte Ptr [EDI], 0

Invoke Lstrcat, AddR Buffer, Addr WordfileNameInvoke GetFileAttributes, AddR Buffer

.IF EAX! = - 1

Mov Blocksize, 1024 * 10

Invoke Heapalloc, Hmainheap, 0, Blocksize

MOV PTEMP, EAX

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C1key, Addr Zerostring, Ptemp, Blocksize, AddR Buffer

.IF EAX! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C2key, Addr Zerostring, Ptemp, Blocksize, AddR Buffer

.IF EAX! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Add EDX, 4

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

@@:

Invoke GetPrivateProfileString, AddR Asmsection, Addr C3key, Addr Zerostring, Ptemp, Blocksize, AddR Buffer

.IF EAX! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Add EDX, 8

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C4key, Addr Zerostring, Ptemp, Blocksize, AddR Buffer

.IF EAX! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Add EDX, 12

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C5key, Addr Zerostring, Ptemp, Blocksize, Addr Buffer

.IF EAX! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Add EDX, 16

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C6key, Addr Zerostring, Ptemp, Blocksize, AddR Buffer

.IF EAX! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Add EDX, 20

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C7key, Addr Zerostring, Ptemp, Blocksize, AddR Buffer

.IF EAX! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Add EDX, 24

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C8key, Addr Zerostring, Ptemp, Blocksize, Addr Buffer

.IF EAX! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Add EDX, 28

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C9key, Addr Zerostring, Ptemp, Blocksize, AddR Buffer.if Eax! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Add EDX, 32

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C10key, Addr Zerostring, Ptemp, Blocksize, AddR Buffer

.IF EAX! = 0

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

Mov Edx, Offset Asmcolorarray

Add Edx, 36

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

.endif

Invoke HeapFree, Hmainheap, 0, Ptemp

.endif

RET

FillhiliteInfo Endp

NEWRICHEDITPROC PROC HWND: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

Local HDC: DWORD

Local Holdfont: DWord

Local Firstchar: DWORD

Local Rect: RECT

Local TxtRange: TextRange

Local Buffer [1024 * 10]: Byte

Local HRGN: DWORD

Local HoldRGN: DWORD

Local RealRect: Rect

Local Pstring: DWORD

Local Buffersize: DWORD

LOCAL PT: POINT

.IF uMSG == WM_PAINT

Push EDI

PUSH ESI

Invoke hidecaret, hwnd

Invoke CallWindowProc, OldWndProc, Hwnd, UMSG, WPARAM, LPARAM

Push EAX

Mov Edi, Offset AsmsyntaxArray

Invoke getdc, hwnd

MOV HDC, EAX

Invoke setbkmode, hdc, transparent

Invoke SendMessage, Hwnd, EM_GETRECT, 0, AddR Rect

Invoke SendMessage, Hwnd, EM_CHARFROMPOS, 0, ADDR RECT

Invoke SendMessage, HWnd, EM_LINEFROMCHAR, EAX, 0

Invoke SendMessage, Hwnd, EM_LINEINDEX, EAX, 0

Mov txtrange.chrg.cpmin, EAX

Mov firstchar, EAX

Invoke SendMessage, Hwnd, Em_Charfrompos, 0, Addr Rect.right

Mov txtrange.chrg.cpmax, Eaxpush Rect.Left

Pop RealRect.Left

Push Rect.Top

POP realRect.top

Push Rect.right

Pop RealRect.Right

Push Rect.Bottom

Pop RealRect.Bottom

Invoke CreateRectrgn, RealRect.Left, RealRect.top, RealRect.right, RealRect.Bottom

Mov HRGN, EAX

Invoke SelectObject, HDC, HRGN

Mov HoldRGN, EAX

Invoke SetTextColor, HDC, CommentColor

Lea Eax, Buffer

Mov txtrange.lpstrText, EAX

Invoke SendMessage, Hwnd, Em_GettextRange, 0, Addr TxtRange

.IF EAX> 0

MOV ESI, ESI ESI == Size of the Text

Mov buffersize, EAX

Push EDI

Push EBX

Lea Edi, Buffer

Mov Edx, EDI; Used as The Reference Point

MOV ECX, ESI

MOV Al, ";"

ScanMore:

Repne scaSB

Je nextskip

JMP Nomorehit

Nextskip:

Dec Edi

Inc ECX

MOV PSTRING, EDI

MOV EBX, EDI

SUB EBX, EDX

Add ebx, Firstchar

Mov txtrange.chrg.cpmin, EBX

Push EAX

MOV Al, 0DH

Repne scaSB

POP EAX

HilittheComment:

.IF ECX> 0

MOV BYTE PTR [EDI-1], 0

.endif

MOV EBX, EDI

SUB EBX, EDX

Add ebx, Firstchar

Mov txtrange.chrg.cpmax, EBX

Pushhad

Mov Edi, PString

Mov ESI, TXTRANGE.CHRG.CPMAX

Sub ESI, TXTRANGE.CHRG.CPMIN; ESI Contains The Length of the Buffer

MOV EAX, ESI

Push EDI

.while eax> 0

.IF BYTE PTR [EDI] == 9

MOV Byte Ptr [EDI], 0

.endif

Inc EDI

Dec EAX

.endw

POP EDI

.While ESI> 0

.IF BYTE PTR [EDI]! = 0

Invoke Lstrlen, EDI

Push EAX

MOV ECX, EDI

Lea Edx, Buffer

SUB ECX, EDX

Add Ecx, Firstchar

.IF richeditversion == 3

Invoke SendMessage, Hwnd, EM_POSFROMCHAR, AddR Rect, ECX

.lse

Invoke SendMessage, HWnd, EM_POSFROMCHAR, ECX, 0

MOV ECX, EAX

And ECX, 0FFFFH

Mov Rect.Left, ECX

SHR EAX, 16

Mov Rect.Top, EAX

.endif

Invoke DrawText, HDC, EDI, -1, Addr Rect, 0

POP EAX

Add Edi, EAX

SUB ESI, EAX

.lse

Inc EDI

Dec ESI

.endif

.endw

MOV ECX, TXTRANGE.CHRG.CPMAXSUB ECX, TXTRANGE.CHRG.CPMIN

Invoke RTLZERMEMORY, PSTRING, ECX

Popad

.IF ECX> 0

JMP Scanmore

.endif

Nomorehit:

POP EBX

POP EDI

Mov ECX, Buffersize

Lea ESI, Buffer

.While ECX> 0

MOV Al, Byte Ptr [ESI]

.IF AL == "" | | Al == 0DH || Al == "/" || Al == "| || Al ==" "|| Al == "-" || Al == "*" || Al == "&" || Al == "<" || Al == "> || Al ==" = "| Al ==" ( "|| Al ==") "|| Al ==" {"|| al =="} "|| Al ==" ["|| Al =="] "| | Al ==" ^ "| | AL == ":" || Al == 9

MOV Byte Ptr [ESI], 0

.endif

Dec ECX

Inc ESI

.endw

Lea ESI, Buffer

Mov ECX, Buffersize

.While ECX> 0

MOV Al, Byte Ptr [ESI]

.IF AL! = 0

Push ECX

Invoke lstrlen, ESI

Push EAX

Mov Edx, ED; EDX Contains the Length of The String

Movzx Eax, Byte Ptr [ESI]

.IF Al> = "a" && al <= "z"

SUB Al, "a"

Add Al, "A"

.endif

SHL EAX, 2

Add Eax, EDI; EDI Contains the Pointer to the WordInfo Pointer Array

.IF DWORD PTR [EAX]! = 0

MOV Eax, DWORD PTR [EAX]

Assume EAX: PTR WordInfo

.while eax! = 0

.IF EDX == [EAX]. Wordlen

Pushhad

Invoke lstrcmpi, [EAX] .pszword, ESI

.IF EAX == 0

Popad

MOV ECX, ESI

Lea Edx, Buffer

SUB ECX, EDX

Add Ecx, Firstchar

Pushhad

.IF richeditversion == 3

Invoke SendMessage, Hwnd, EM_POSFROMCHAR, AddR Rect, ECX

.lse

Invoke SendMessage, HWnd, EM_POSFROMCHAR, ECX, 0

MOV ECX, EAX

And ECX, 0FFFFH

Mov Rect.Left, ECX

SHR EAX, 16

Mov Rect.Top, EAX

.endif

Popad

Mov Edx, [EAX] .pcolor

Invoke SetTextColor, HDC, DWORD PTR [EDX]

Invoke DrawText, HDC, ESI, -1, Addr Rect, 0

.break

.endif

Popad

.endif

Push [eax] .nextlink

POP EAX

.endw

.endif

POP EAX

POP ECX

Add ESI, ESI

SUB ECX, EAX

.lse

Inc ESI

Dec ECX

.endif

.endw

.endif

Invoke SelectObject, HDC, Holdrgn

Invoke deleteObject, hrgn

Invoke SelectObject, HDC, HoldFont

Invoke ReleaseDC, HWND, HDC

Invoke showcaret, hwnd

POP EAX

POP ESI

POP EDI

RET

.ELSEIF uMSG == WM_Close

Invoke SetWindowlong, HWnd, GWL_Wndproc, OldWndproc

.lse

Invoke CallWindowProc, OldWndProc, Hwnd, UMSG, WPARAM, LPARAM

RET

.endif

NewricHEDITPROC ENDP

WNDPROC PROC HWND: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

LOCAL OFN: OpenFileName

Local buffer [256]: Byte

Local EditStream: EditStream

Local Hfile: DWORD

Local HPOPUP: DWORD

LOCAL PT: POINT

Local Chrg: Charrange

.IF uMSG == WM_CREATE

invoke CreateWindowEx, WS_EX_CLIENTEDGE, addr RichEditClass, 0, WS_CHILD or WS_VISIBLE or ES_MULTILINE or WS_VSCROLL or WS_HSCROLL or ES_NOHIDESEL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, RichEditID, hInstance, 0

Mov hwndrichedit, EAX

Invoke SendMessage, Hwndrichedit, EM_SETTYPOGRAPHYOPTIONS, TO_SIMPLINEBREAK, TO_SIMPLINEBREAK

Invoke SendMessage, HwndrichEdit, EM_GETTYPOGRAPHYOPTIONS, 1, 1

.IF EAX == 0; Means this message is not processed

Mov Richeditversion, 2

.lse

Mov Richeditversion, 3

Invoke SendMessage, HwndrichEdit, Em_seteditStyle, SES_EMULATESYSEDIT, SES_EMULATESYSEDIT

.endif

Invoke SetWindowlong, Hwndrichedit, GWL_WndProc, AddR NewRichEditproc

Mov OldWndProc, EAX

Invoke SendMessage, HwndrichEdit, EM_LIMITTEXT, -1, 0

Invoke setColor

Invoke SendMessage, Hwndrichedit, EM_SETMODIFY, FALSE, 0

Invoke sendMessage, hwndrichedit, em_seteventmask, 0, enm_mouseeventsinvoke sendmessage, hwndrichedit, em_emptyundobuffer, 0,0

.ELSEIF uMSG == WM_NOTIFY

PUSH ESI

Mov ESI, LPARAM

Assume ESI: PTR NMHDR

.IF [ESI] .code == en_msgfilter

Assume ESI: PTR MSGFilter

.IF [ESI] .msg == WM_RBUTTONDOWN

Invoke GetMenu, HWND

Invoke GetSubmenu, Eax, 1

MOV HPOPUP, EAX

Invoke PrepareEditmenu, HPOPUP

Mov Edx, [ESI] .lparam

MOV ECX, EDX

And EDX, 0FFFFH

SHR ECX, 16

MOV PT.X, EDX

Mov pt.y, ECX

Invoke Clienttoscreen, Hwnd, Addr Pt

Invoke TRACKPOPUPMENU, HPOPUP, TPM_LEFTALIGN OR TPM_BOTTOMALIGN, PT.X, PT.Y, NULL, HWND, NULL

.endif

.endif

POP ESI

.ELSEIF uMSG == WM_INITMENUPOPUP

Mov Eax, LPARAM

.IF AX == 0; File Menu

.IF fileopened == true; a file is already OPENED

Invoke EnableMenuItem, WPARAM, IDM_OPEN, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_CLOSE, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_SAVE, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_SAVEAS, MF_ENABLED

.lse

Invoke EnableMenuItem, WPARAM, IDM_OPEN, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_CLOSE, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_SAVE, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_SAVEAS, MF_GRAYED

.endif

.ELSEIF AX == 1; Edit Menu

Invoke PrepareEditmenu, WPARAM

.ELSEIF AX == 2; Search Menu Bar

.IF fileopened == TRUE

Invoke EnableMenuItem, WPARAM, IDM_FIND, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_FINDNEXT, MF_ENABED

Invoke EnableMenuItem, WPARAM, IDM_FINDPREV, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_REPLACE, MF_ENABLED

Invoke EnableMenuItem, WPARAM, IDM_GOTOLINE, MF_ENABLED

.lse

Invoke EnableMenuItem, WPARAM, IDM_FIND, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_FINDNEXT, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_FINDPREV, MF_GRAYEDINVOKE ENABLEMENUITEM, WPARAM, IDM_REPLACE, MF_GRAYED

Invoke EnableMenuItem, WPARAM, IDM_GOTOLINE, MF_GRAYED

.endif

.endif

.ELSEIF uMSG == WM_COMMAND

.IF lparam == 0; Menu Commands

Mov Eax, WPARAM

.IF AX == idm_open

Invoke RTLZERMEMORY, ADDR OFN, SIZEOF OFN

Mov ofn.lstructsize, Sizeof off

Push hwnd

POP OFN.HWNDOWNER

Push hinstance

POP OFN.HINSTANCE

Mov off.lpstrfilter, offset asmfilterstring

Mov ofn.lpstrfile, offset filename

MOV BYTE PTR [filename], 0

Mov ofn.nmaxfile, Sizeof FileName

Mov off.flags, OFN_FILEMUSTEXIST or OFN_HIDEREADOSLY OR OFN_PATHMUSTEXIST

Invoke GetopenFileName, Addr OFN

.IF EAX! = 0

Invoke Createfile, Addr FileName, Generic_Read, File_Share_read, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0

.IF EAX! = INVALID_HANDLE_VALUE

Mov Hfile, EAX

Mov EditStream.dwcookie, EAX

Mov EditStream.pfncallback, Offset StreamInproc

Invoke SendMessage, Hwndrichedit, EM_STREAMIN, SF_TEXT, ADDR EditStream

Invoke SendMessage, Hwndrichedit, EM_SETMODIFY, FALSE, 0

Invoke Closehandle, HFile

Mov FileOpened, True

.lse

Invoke Messagebox, Hwnd, Addr OpenFilefail, Addr Appname, MB_OK OR MB_ICONERROR

.endif

.endif

.ELSEIF AX == IDM_Close

Invoke CheckmodifyState, Hwnd

.IF EAX == True

Invoke setWindowText, Hwndrichedit, 0

Mov FileOpened, False

.endif

.ELSEIF AX == IDM_SAVE

Invoke CreateFile, Addr FileName, Generic_Write, File_Share_read, null, crete_always, file_attribute_normal, 0

.IF EAX! = INVALID_HANDLE_VALUE

@@:

Mov Hfile, EAX

Mov EditStream.dwcookie, EAX

Mov EditStream.pfncallback, Offset streamoutproc

Invoke SendMessage, Hwndrichedit, EM_STREAMOUT, SF_TEXT, AddR EditStream

Invoke SendMessage, Hwndrichedit, EM_SETMODIFY, FALSE, 0

Invoke Closehandle, Hfile.ELSE

Invoke Messagebox, Hwnd, Addr OpenFilefail, Addr Appname, MB_OK OR MB_ICONERROR

.endif

.ELSEIF AX == IDM_COPY

Invoke SendMessage, Hwndrichedit, WM_COPY, 0, 0

.ELSEIF AX == IDM_CUT

Invoke SendMessage, Hwndrichedit, WM_CUT, 0, 0

.ELSEIF AX == IDM_PASTE

Invoke SendMessage, Hwndrichedit, WM_Paste, 0,0

.ELSEIF AX == IDM_DELETE

Invoke SendMessage, HwndrichEdit, EM_REPLACESEL, TRUE, 0

.ELSEIF AX == IDM_SELECTALL

Mov chrg.cpmin, 0

Mov chrg.cpmax, -1

Invoke SendMessage, Hwndrichedit, EM_EXSETSEL, 0, AddR chrg

.ELSEIF AX == IDM_UNDO

Invoke SendMessage, Hwndrichedit, EM_UNDO, 0, 0

.ELSEIF AX == IDM_REDO

Invoke SendMessage, Hwndrichedit, EM_REDO, 0, 0

.ELSEIF AX == IDM_OPTION

Invoke Dialogboxparam, Hinstance, IDD_OptionDLG, HWND, Addr Optionproc, 0

.ELSEIF AX == IDM_SAVEAS

Invoke RTLZERMEMORY, ADDR OFN, SIZEOF OFN

Mov ofn.lstructsize, Sizeof off

Push hwnd

POP OFN.HWNDOWNER

Push hinstance

POP OFN.HINSTANCE

Mov off.lpstrfilter, offset asmfilterstring

Mov ofn.lpstrfile, Offset AlternateFileName

MOV BYTE PTR [AlternateFileName], 0

Mov ofn.nmaxfile, Sizeof AlternateFileName

Mov off.flags, OFN_FILEMUSTEXIST or OFN_HIDEREADOSLY OR OFN_PATHMUSTEXIST

Invoke GetsaveFileName, AddR OFN

.IF EAX! = 0

Invoke createfile, addr alternatefilename, generic_write, file_share_read, null, create_always, file_attribute_normal, 0

.IF EAX! = INVALID_HANDLE_VALUE

JMP @B

.endif

.endif

.ELSEIF AX == IDM_FIND

.IF hSearch == 0

Invoke CreateDialogparam, Hinstance, IDd_Findlg, Hwnd, AddR searchProc, 0

.endif

.ELSEIF AX == IDM_REPLACE

.IF hSearch == 0

Invoke CreateDialogparam, Hinstance, IDD_REPLACEDLG, HWND, AddR ReplaceProc, 0

.endif

.ELSEIF AX == idm_gotoline.if hSearch == 0

Invoke CreateDialogparam, Hinstance, IDD_GOTODLG, HWND, Addr gotoproc, 0

.endif

.ELSEIF AX == IDM_FINDNEXT

Invoke Lstrlen, AddR Findbuffer

.IF EAX! = 0

Invoke SendMessage, Hwndrichedit, EM_EXGETSEL, 0, AddR FindText.chrg

Mov Eax, FindText.chrg.cpmin

.IF EAX! = FindText.chrg.cpmax

Push FindText.chrg.cpmax

POP FindText.chrg.cpmin

.endif

MOV Findtext.chrg.cpmax, -1

MOV FindText.lpstrText, Offset Findbuffer

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, fr_down, addr findxt

.IF EAX! = - 1

Invoke SendMessage, HwndrichEdit, EM_EXSETSEL, 0, AddR FindText.chrgtext

.endif

.endif

.ELSEIF AX == IDM_FINDPREV

Invoke Lstrlen, AddR Findbuffer

.IF EAX! = 0

Invoke SendMessage, Hwndrichedit, EM_EXGETSEL, 0, AddR FindText.chrg

MOV Findtext.chrg.cpmax, 0

MOV FindText.lpstrText, Offset Findbuffer

Invoke SendMessage, Hwndrichedit, EM_FINDTEXTEX, 0, AddR Findtext

.IF EAX! = - 1

Invoke SendMessage, HwndrichEdit, EM_EXSETSEL, 0, AddR FindText.chrgtext

.endif

.endif

.ELSEIF AX == IDM_EXIT

Invoke SendMessage, HWnd, WM_Close, 0, 0

.endif

.endif

.ELSEIF uMSG == WM_Close

Invoke CheckmodifyState, Hwnd

.IF EAX == True

Invoke DestroyWindow, HWnd

.endif

.ELSEIF uMSG == WM_SIZE

Mov Eax, LPARAM

Mov Edx, EAX

And Eax, 0FFFFH

SHR EDX, 16

Invoke MoveWindow, Hwndrichedit, 0,0, Eax, EDX, True

.ELSEIF uMSG == WM_DESTROY

Invoke PostquitMessage, NULL

.lse

Invoke DefWindowProc, Hwnd, UMSG, WPARAM, LPARAM

RET

.endif

XOR EAX, EAX

RET

WNDPROC ENDP

End Start

Analysis:

. This is the content.

FillhiliteInfo Proc Uses Edi

Local Buffer [1024]: Byte

Local PTEMP: DWordLocal Blocksize: DWORD

Invoke RTLZERMEMORY, AddR AsmsyntaxArray, Sizeof AsmsyntaxArray

Initialize asmsyntaxArray to zero.

Invoke GetModuleFileName, Hinstance, Addr Buffer, Sizeof Buffer

Invoke Lstrlen, AddR Buffer

MOV ECX, EAX

Dec ECX

Lea Edi, Buffer

Add Edi, ECX

STD

MOV Al, "/"

Repne scaSB

CLD

Inc EDI

MOV Byte Ptr [EDI], 0

Invoke Lstrcat, AddR Buffer, Addr WordFileName

Construct The Full Path Name of Wordfile.txt: I Assume That's Always in The Same Folder as the program.

Invoke getFileAttributes, AddR buffer

.IF EAX! = - 1

I use this method as a quick way of checking.

Mov Blocksize, 1024 * 10

Invoke Heapalloc, Hmainheap, 0, Blocksize

MOV PTEMP, EAX

Allocate The Memory Block to Store The Words. Default To 10k. The Memory Is Allocated from The Default HEAP.

@@:

Invoke GetPrivateProfileString, Addr Asmsection, Addr C1key, Addr Zerostring, Ptemp, Blocksize, AddR Buffer

.IF EAX! = 0

I Use getprivateprofilestring to retrieve the content of each key in wordfile.txt. The key starts from c1 to c10.

INC EAX

.IF EAX == blocksize; the buffer is to small

Add Blocksize, 1024 * 10

Invoke HeapRealloc, Hmainheap, 0, Ptemp, Blocksize

MOV PTEMP, EAX

JMP @B

.endif

CHECKING WHETHER THE MEMORY BLOCK IS LARGE ENOUGH. IT IS Not, We Increment The size by 10k Until The Block is Large Enough.

Mov Edx, Offset Asmcolorarray

Invoke PaSebuffer, Hmainheap, Ptemp, Eax, Edx, Addr AsmsyntaxArray

Pass The Words, The Memory Block Handle, The Size of The Data Read from Wordfile.txt, The Address of The Color Dword That Will Be Used To Hilight The Words and The Address of AsmsyntaxArray.

Now, let's examine what ParseBuffer does. In essence, this function accepts the buffer containing the words to be hilighted, parses them to individual words and stores each of them in a WORDINFO structure array that can be accessed quickly from ASMSyntaxArray.ParseBuffer proc uses edi ESI HHEAP: DWORD, PBUFFER: DWORD, NSIZE: DWORD, ARRAYOFFSET: DWORD, PARRAY: DWORD

Local buffer [128]: BYTE

Local Inprss: DWORD

Mov Inprogress, False

Inprogress is the flag i use to indeicate WHETER THE SCANNING Process Has Begun. We Haven't Encountered A Non-White Space Character Yet.

Lea ESI, Buffer

Mov EDI, PBuffer

Invoke Charlower, EDI

ESI Points To Our Local Buffer That Will Contain The Word We Have Parsed from The Word List. EDI Points To The Word List String. To Simplify The Search Later, We Convert All Characters To LowerCase.

MOV ECX, NSIZE

Searchloop:

OR ECX, ECX

JZ Finished

CMP Byte PTR [EDI], ""

Je endofword

CMP Byte PTR [EDI], 9; TAB

Je endofword

Scan The Whole Word List in The Buffer, Looking for the White Spaces. If A White SpaceMine WHETER IT MARKS The End or the beginning beginning of a word.

Mov Inprogress, True

Mov Al, Byte Ptr [EDI]

MOV BYTE PTR [ESI], Al

Inc ESI

Skipit:

Inc EDI

Dec ECX

JMP Searchloop

IF the byte under scrutiny is not a white space, we copy it to the buffer to construct a word and then contract.

Endofword:

CMP Inprogress, True

JE WordFound

JMP Skipit

If a white space is found, we check the value in InProgress. If the value is TRUE, we can assume that the white space marks the end of a word and we may proceed to put the word currently in the local buffer (pointed to by ESI) INTO A WordInfo Structure. If The Value IS False, We Continue The Scan Until A Non-White Space Character Is Found.WordFound:

MOV Byte Ptr [ESI], 0

Push ECX

Invoke Heapalloc, Hheap, Heap_Zero_Memory, Sizeof WordInfo

...............................

PUSH ESI

Mov ESI, EAX

Assume ESI: PTR WordInfo

Invoke Lstrlen, AddR Buffer

MOV [ESI]. Wordlen, EAX

We Obtain the Length of The Word in The Local Buffer and Store IT IN The Wordlen Member of The WordInfo Structure, To BE Used As a Quick Comparison.

Push arrayoffset

POP [ESI] .pcolor

Store The Address of The DWord That Contains The Color To Be Used to Hilight The Word in Pcolor Member.

INC EAX

Invoke Heapalloc, Hheap, Heap_Zero_Memory, EAX

MOV [ESI] .pszword, EAX

Mov Edx, EAX

Invoke Lstrcpy, EDX, AddR Buffer

Allocate Memory from The Heap To Store The Word Itself. Right Now, The WordInfo Structure Is Ready To Be Inserted INTO The Appropriate Linked List.

Mov Eax, Parray

Movzx EDX, Byte Ptr [Buffer]

SHL EDX, 2; Multiply by 4

Add Eax, EDX

pArray contains the address of ASMSyntaxArray. We want to move to the dword that has the same index as the value of the first character of the word. So we put the first character of the word in edx then multiply edx by 4 (because each element In AsmsyntaxArray IS 4 BYTES in size) and the address of ask the offset to the address of asmsyntaxarray. we have the address of the corresponding dword in eax..if dword ptr [EAX] == 0

Mov DWORD PTR [EAX], ESI

.lse

Push DWORD PTR [EAX]

POP [ESI] .NextLink

Mov DWORD PTR [EAX], ESI

.endif

Check The Value of The DWord. If it's 0, it..................................

If the value in the dword is not 0, it means there is at least one word that begins with this character in the array. We thus insert this WORDINFO structure to the head of the linked list and update its NextLink member to point to the next Wordinfo structure.

POP ESI

POP ECX

Lea ESI, Buffer

Mov Inprogress, False

JMP Skipit

After the Operation is Complete, We Begin The next scan cycle until the end of buffer is reached.

Invoke SendMessage, Hwndrichedit, EM_SETTYPOGRAPHYOPTIONS, TO_SIMPLINEBREAK, TO_SIMPLINEBREAK

Invoke SendMessage, HwndrichEdit, EM_GETTYPOGRAPHYOPTIONS, 1, 1

.IF EAX == 0; Means this message is not processed

Mov Richeditversion, 2

.lse

Mov Richeditversion, 3

Invoke SendMessage, HwndrichEdit, Em_seteditStyle, SES_EMULATESYSEDIT, SES_EMULATESYSEDIT

.endif

After the richedit control is created, we need to determine the its version. This step is necessary since EM_POSFROMCHAR behaves differently for RichEdit 2.0 and 3.0 and EM_POSFROMCHAR is crucial to our syntax hilighting routine. I have never seen a documented way of checking the version of richedit control thus I have to use a workaround. In this case, I set an option that is specific to version 3.0 and immediately retrieve its value. If I can retrieve the value, I assume that the control version is 3.0.If you use RichEdit control version 3.0, you will notice that updating the font color for a large file takes quite a long time This problem seems to be specific to version 3.0 I found a workaround:.. making the control emulate the behavior of the system edit control by sending Em_seteditstyle Message.

After We can Obtain the Version Information, WE Proceed To Subclass The Richedit Control. We will now Examine The New Window Procedure for the Richedit Control.

NEWRICHEDITPROC PROC HWND: DWORD, UMSG: DWORD, WPARAM: DWORD, LPARAM: DWORD

........

.......

.IF uMSG == WM_PAINT

Push EDI

PUSH ESI

Invoke hidecaret, hwnd

Invoke CallWindowProc, OldWndProc, Hwnd, UMSG, WPARAM, LPARAM

Push EAX

We handle WM_PAINT message. First, we hide the caret so as to avoid some ugly gfx after the hilighting. After that we pass the message to the original richedit procedure to let it update the window. When CallWindowProc returns, the text is updated with its Usual color / backgroundunity to do syntax hilighting.

Mov Edi, Offset AsmsyntaxArray

Invoke getdc, hwnd

MOV HDC, EAX

Invoke setbkmode, hdc, transparent

Store the address of ASMSyntaxArray in edi. Then we obtain the handle to the device context and set the text background mode to transparent so the text that we will write will use the default background color.invoke SendMessage, hWnd, EM_GETRECT, 0, addr rect

Invoke SendMessage, Hwnd, EM_CHARFROMPOS, 0, ADDR RECT

Invoke SendMessage, HWnd, EM_LINEFROMCHAR, EAX, 0

Invoke SendMessage, Hwnd, EM_LINEINDEX, EAX, 0

We want to obtain the visible text so we first have to obtain the formatting rectangle by sending EM_GETRECT message to the richedit control. Now that we have the bounding rectangle, we obtain the nearest character index to the upper left corner of the rectangle with EM_CHARFROMPOS. Once we have the character index (the first visible character in the control), we can start to do syntax hilighting starting from that position. But the effect might not be as good as when we start from the first character of the line that the character Is in. That's why i need to obtain the line number is in by sending em_linefromchar message. To Obtain the first character of then line, i send em_lineindex message.

Mov txtrange.chrg.cpmin, EAX

Mov firstchar, EAX

Invoke SendMessage, Hwnd, Em_Charfrompos, 0, Addr Rect.right

Mov txtrange.chrg.cpmax, EAX

Once we have the first character index, store it for future reference in FirstChar variable. Next we obtain the last visible character index by sending EM_CHARFROMPOS, passing the lower-right corner of the formatting rectangle in lParam.

Push Rect.Left

Pop RealRect.Left

Push Rect.Top

POP realRect.top

Push Rect.right

Pop RealRect.Right

Push Rect.Bottom

Pop RealRect.Bottom

Invoke CreateRectrgn, RealRect.Left, RealRect.top, RealRect.right, RealRect.Bottom

Mov HRGN, EaxInvoke SelectObject, HDC, HRGN

Mov HoldRGN, EAX

While doing syntax hilighting, I noticed an unsightly side-effect of this method: if the richedit control has a margin (you can specify margin by sending EM_SETMARGINS message to the richedit control), DrawText writes over the margin Thus I need to create a. CLIPPING Region, The size of the formatting reccTangle, by calling createrecn. The Output of GDI Functions Will Be Clipped to the "Writable" Area.

Next, we need to hilight the comments first and get them out of our way My method is to search for ";" and hilight the text with the comment color until the carriage return is found I will not analyze the routine here:.. It's .

Mov ECX, Buffersize

Lea ESI, Buffer

.While ECX> 0

MOV Al, Byte Ptr [ESI]

.IF AL == "" | | Al == 0DH || Al == "/" || Al == "| || Al ==" "|| Al == "-" || Al == "*" || Al == "&" || Al == "<" || Al == "> || Al ==" = "| Al ==" ( "|| Al ==") "|| Al ==" {"|| al =="} "|| Al ==" ["|| Al =="] "| | Al ==" ^ "| | AL == ":" || Al == 9

MOV Byte Ptr [ESI], 0

.endif

Dec ECX

Inc ESI

.endw

. Once the comments are out of our way, we separate the words in the buffer by replacing the "separator" characters with 0s With this method, we need not concern about the separator characters while processing the words in the buffer anymore: there is only One Separetor Character, Null.lea ESI, Buffer

Mov ECX, Buffersize

.While ECX> 0

MOV Al, Byte Ptr [ESI]

.IF AL! = 0

Search The Buffer for the First Character That Is Not Null, IE, The First Character of A Word.

Push ECX

Invoke lstrlen, ESI

Push EAX

Mov Edx, EAX

Obtain the length of the word and put it in edx

Movzx Eax, Byte Ptr [ESI]

.IF Al> = "a" && al <= "z"

SUB Al, "a"

Add Al, "A"

.endif

Convert the Character to LowerCase (if it's an uppercase character)

SHL EAX, 2

Add Eax, EDI; EDI Contains the Pointer to the WordInfo Pointer Array

.IF DWORD PTR [EAX]! = 0

After That, We Skip to The Corresponding DWORD IN ASMSYNTAXARRAY and Check WHETER THE VALUE IN THAT IS 0. If IT WORD.

MOV Eax, DWORD PTR [EAX]

Assume EAX: PTR WordInfo

.while eax! = 0

.IF EDX == [EAX]. Wordlen

If the value in the dword is non-zero, it points to the linked list of WORDINFO structures. We process to walk the linked list, comparing the length of the word in our local buffer with the length of the word in the WORDINFO structure. This Is A Quick Test Before We Compare The Words. Should Save Some Clock Cycles.

Pushhad

Invoke lstrcmpi, [EAX] .pszword, ESI

.IF EAX == 0

IF The Length, WE Proceed To Compare The with lstrcmpi.

Popad

MOV ECX, ESI

Lea Edx, Buffer

SUB ECX, EDX

Add Ecx, Firstchar

We construct the character index from the address of the first character of the matching word in the buffer. We first obtain its relative offset from the starting address of the buffer then add the character index of the first visible character to it.pushad

.IF richeditversion == 3

Invoke SendMessage, Hwnd, EM_POSFROMCHAR, AddR Rect, ECX

.lse

Invoke SendMessage, HWnd, EM_POSFROMCHAR, ECX, 0

MOV ECX, EAX

And ECX, 0FFFFH

Mov Rect.Left, ECX

SHR EAX, 16

Mov Rect.Top, EAX

.endif

Popad

Once we know the character index of the first character of the word to be hilighted, we proceed to obtain the coordinate of it by sending EM_POSFROMCHAR message. However, this message is interpreted differently by richedit 2.0 and 3.0. For richedit 2.0, wParam contains the character index and lParam is not used. It returns the coordinate in eax. For richedit 3.0, wParam is the pointer to a POINT structure that will be filled with the coordinate and lParam contains the character index.

As you can see, Passing The Wrong Arguments to EM_POSFROMCHAR CAN WREAK HAVOC To Your System. That's why i since ly to differentiate Between Richedit Control Versions.

Mov Edx, [EAX] .pcolor

Invoke SetTextColor, HDC, DWORD PTR [EDX]

Invoke DrawText, HDC, ESI, -1, Addr Rect, 0

Once We got The Coordinate to Start, We set The text color with the one specified in The WordInfo Structure. And then the new color.

转载请注明原文地址:https://www.9cbs.com/read-4688.html

New Post(0)