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 of that the first visible character is in by sending em_linefromchar message. to obtain the first character of that 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,eax invoke 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 rectangle, by calling createrectrgn. 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 fairly long and complicated. suffice here to say that, when all the comments are hilighted, we replace them with 0s in the buffer so that the words in the comments will not be processed/hilighted later.
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==":" || 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 separator 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)