Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[module] HiEdit 4.0.0.4-5


  • Please log in to reply
220 replies to this topic

Poll: Do you want HiEdit internaly (103 member(s) have cast votes)

Do you want HiEdit internaly

  1. Voted Yes (76 votes [61.79%])

    Percentage of vote: 61.79%

  2. No, I like Edit control (31 votes [25.20%])

    Percentage of vote: 25.20%

  3. Other (please explain) (16 votes [13.01%])

    Percentage of vote: 13.01%

Vote Guests cannot vote
majkinetor
  • Moderators
  • 4512 posts
  • Last active: Oct 02 2013 02:33 PM
  • Joined: 24 May 2006
Unfortunately, no.

Normand
  • Members
  • 87 posts
  • Last active: Jul 24 2013 11:08 PM
  • Joined: 21 May 2007
For your information

I have just released the first public version of Vic, the name of a text editor of my own. It is based on HiEdit control.

Thanks a lot to Majkinetor for his AHK Attach, Dlg and Wrapper files.

Read this post for more details.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: Oct 02 2013 02:33 PM
  • Joined: 24 May 2006
Thx Normand.
Added link to your editor on the first page.

jballi
  • Members
  • 1021 posts
  • Last active:
  • Joined: 01 Oct 2005
It's back! The "If the line is only 1 character long" bug when using the HE_GetLine function appears to be occurring again. The workaround written for it doesn't appear to be working anymore. Probably a feature of the latest version of the HiEdit control.

I've made a minor modification to the function to use the HE_GetTextRange function to get that one elusive character when necessary. Please use, modify, and/or ignore.

HE_GetLine(hEdit, idx=-1){
    static EM_GETLINE=0xC4	  ;The return value is the number of characters copied. The return value is zero if the line number specified by the line parameter is greater than the number of lines in the HiEdit control
    if (idx = -1) 
        idx := HE_LineFromChar(hEdit, HE_LineIndex(hEdit))
    len := HE_LineLength(hEdit, idx)
    ifEqual, len, 0, return	 

    ;-- Work-around for the len=1 bug
    if len=1
        {
        cPos:=HE_LineIndex(hEdit,idx)
        return HE_GetTextRange(hEdit,cPos,cPos+1)
        }

    VarSetCapacity(txt,len,0)
    NumPut(len,txt)
    SendMessage, EM_GETLINE, idx, &txt,, ahk_id %hEdit% 
    if ErrorLevel = FAIL  ;-- This test remains as fail-safe 
    {
        Msgbox %A_ThisFunc% failed
        return
    }
    VarSetCapacity(txt, -1)
    return txt
}
Thank you for your consideration.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: Oct 02 2013 02:33 PM
  • Joined: 24 May 2006
Try this one:

HE_GetLine(hEdit, idx=-1){
	static EM_GETLINE=196	  ;The return value is the number of characters copied. The return value is zero if the line number specified by the line parameter is greater than the number of lines in the HiEdit control
	if (idx = -1) 
		idx := HE_LineFromChar(hEdit, HE_LineIndex(hEdit))
	len := HE_LineLength(hEdit, idx)
	ifEqual, len, 0, return	 

	VarSetCapacity(txt, len, 0), NumPut(len = 1 ? 2 : len, txt)
	SendMessage, EM_GETLINE, idx, &txt,, ahk_id %hEdit%
	if ErrorLevel = FAIL
	{
		Msgbox %A_ThisFunc% failed
		return
	}

	VarSetCapacity(txt, -1)
	return SubStr(txt, 0) = "`r" ? SubStr(txt, 1, -1) : txt
}


wasjök
  • Guests
  • Last active:
  • Joined: --
maj you still work on this?

majkinetor
  • Moderators
  • 4512 posts
  • Last active: Oct 02 2013 02:33 PM
  • Joined: 24 May 2006
obviously :)

wasjök
  • Guests
  • Last active:
  • Joined: --
good to read, think i will use it in the nearly future! thank you for wasting time in this.

jballi
  • Members
  • 1021 posts
  • Last active:
  • Joined: 01 Oct 2005

Try this one:

HE_GetLine(hEdit, idx=-1){
	static EM_GETLINE=196	  ;The return value is the number of characters copied. The return value is zero if the line number specified by the line parameter is greater than the number of lines in the HiEdit control
	if (idx = -1) 
		idx := HE_LineFromChar(hEdit, HE_LineIndex(hEdit))
	len := HE_LineLength(hEdit, idx)
	ifEqual, len, 0, return	 

	VarSetCapacity(txt, len, 0), NumPut(len = 1 ? 2 : len, txt)
	SendMessage, EM_GETLINE, idx, &txt,, ahk_id %hEdit%
	if ErrorLevel = FAIL
	{
		Msgbox %A_ThisFunc% failed
		return
	}

	VarSetCapacity(txt, -1)
	return SubStr(txt, 0) = "`r" ? SubStr(txt, 1, -1) : txt
}


No good. The HiEdit control supports data in the DOS format (EOL=CR+LF) or Unix format (EOL=LF). If the data is in the Unix format, this version will return 2 characters instead of 1.

BTW, the HiEdit control can also read the Mac format (EOL=CR) but the data is automatically converted to the Unix format (EOL=LF) when the data hits the control.

jballi
  • Members
  • 1021 posts
  • Last active:
  • Joined: 01 Oct 2005
OK. Here's a version of the HE_GetLine function that works around the Len=1 bug but does not use HE_GetTextRange function and correctly accounts for Unix and DOS file formats.

HE_GetLine(hEdit,idx=-1)
    {
    static EM_GETLINE=0xC4
    if (idx=-1) 
      idx:=HE_LineFromChar(hEdit,HE_LineIndex(hEdit))
    len:=HE_LineLength(hEdit,idx)
    IfEqual,len,0,return

    VarSetCapacity(txt,len=1 ? 2:len,0)
    NumPut(len=1 ? 2:len,txt,0,"Short")
    SendMessage EM_GETLINE,idx,&txt,,ahk_id %hEdit%
    if ErrorLevel=FAIL ;-- Test remains as a fail-safe
        {
        Msgbox %A_ThisFunc% failed
        return
        }
    
    VarSetCapacity(txt,-1)
    return len=1 ? SubStr(txt,1,1):txt
    }

I couldn't get the SendMessage command to fail but the "if ErrorLevel=FAIL" test remains as a fail-safe. Also, the Type="Short" parameter on the NumPut statement was necessary because the command was updating the variable incorrectly on occasion. Only the 1st word of the variable are used to determine the length.

Please let me know if you have any questions or if you find any problems.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: Oct 02 2013 02:33 PM
  • Joined: 24 May 2006
Great.
I uploaded version 4.0.0.4-5 with your function.


Ty.

jballi
  • Members
  • 1021 posts
  • Last active:
  • Joined: 01 Oct 2005
Looks good. Thanks for the update.

jballi
  • Members
  • 1021 posts
  • Last active:
  • Joined: 01 Oct 2005
Here is my first pass at a function to search a HiEdit control using using the AutoHotkey RegExMatch command. It needs the HiEdit library to work. I am not a RegEx expert (not even close) so I'm hoping that a few of you HiEdit/RegEx experts will give a try to confirm that it is works OK. If you find anything more than superficial problems or if you have any questions, please PM me so that we don't trash this excellent thread.

Here's the code (2 functions):
;-------------------------------------------------------------------------------
;
; Function: FindRegEx
;
; Description:
;
;   Find text within the HiEdit control using the AutoHotkey RegExMatch command.
;
;
; Parameters:
;
;   p_Pattern - The regular expression pattern to search for.
;
;   p_Min, p_Max - Zero-based search range within the HiEdit control.
;
;       p_Min is the character index of the first character in the range and
;       p_Max is the character index immediately following the last character
;       in the range. Ex: To search the first 5 characters of the text, set
;       p_Min to 0 and p_Max to 5.  Set p_Max to -1 to search to the end of
;       the text.
;
;       To search backward, the roles and descriptions of the p_Min and p_Max
;       are reversed.  Ex: To search the first 5 characters of the control in
;       reverse, set p_Min to 5 and p_Max to 0.
;
;   p_Flags - Valid flags are as follows:
;
;       Flag        Description
;       ----        -----------
;       Static      [Advanced feature]
;                   Text collected from the HiEdit control remains in memory is
;                   used to satisfy the search request.  The static text remains
;                   in memory until the "Reset" flag is used or until the
;                   "Static" flag is not used.
;
;                   Advantages: Search time is reduced 10 to 60 percent
;                   (or more) depending on the size of the text in the control.
;                   There is no speed increase on the first use of the "Static"
;                   flag.
;
;                   Disadvantages: Any changes in the HiEdit control are not
;                   reflected in the search.
;
;                   Bottom line: Don't use this flag unless performing multiple
;                   search requests on a control that will not be modified
;                   while searching.
;
;                   
;       Reset       [Advanced feature]
;                   Clears the saved text created by the "Static" flag so that
;                   the next use of the "Static" flag will get the text directly
;                   from the HiEdit control.  To clear the saved memory without
;                   performing a search, use the following syntax:
;
;                       HE_FindRegEx("","",0,0,"Reset")
;
;
;   r_RegExOutput - Variable that contains the part of the source text that
;       matched the RegEx pattern.  [Optional]
;
;
; Returns:
;
;   Zero-based character index of the first character of the match or -1 if
;   no match is found.
;
;
; Programming notes:
;
;   Searching using regular expressions (RegEx) can produce results that have a
;   dynamic number of characters.  For this reason, searching for the "next"
;   pattern (forward or backward) may produce different results from developer
;   to developer depending on how the values of p_Min and p_Max are determined.
;
;
HE_FindRegEx(hEdit,p_Pattern,p_Min=0,p_Max=-1,p_Flags="",ByRef r_RegExOut="")
    {
    Static s_Text

    ;-- Initialize
    r_RegExOut:=""
    if InStr(p_Flags,"Reset")
        s_Text:=""

    ;-- Anything to search?
    if StrLen(p_Pattern)=0
        Return -1

    l_MaxLen:=HE_GetTextLength(hEdit)
    if (l_MaxLen=0)
        Return -1

    ;-- Parameters
    if (p_Min<0 or p_Max>l_MaxLen)
        p_Min:=l_MaxLen

    if (p_Max<0 or p_Max>l_MaxLen)
        p_Max:=l_MaxLen

    ;-- Anything to search?
    if (p_Min=p_Max)
        Return -1

    ;-- Get text
    if InStr(p_Flags,"Static")
        {
        if StrLen(s_Text)=0
            s_Text:=HE_GetTextRange(hEdit)

        l_Text:=SubStr(s_Text,(p_Max>p_Min) ? p_Min+1:p_Max+1,(p_Max>p_Min) ? p_Max:p_Min)
        }
     else
        {
        s_Text:=""
        l_Text:=HE_GetTextRange(hEdit,(p_Max>p_Min) ? p_Min:p_Max,(p_Max>p_Min) ? p_Max:p_Min)
        }


    p_Pattern:=RegExReplace(p_Pattern,"^P\)?","",1)   ;-- Remove P or P)
    if (p_Max>p_Min)  ;-- Search forward
        {
        l_FoundPos:=RegExMatch(l_Text,p_Pattern,r_RegExOut,1)-1
        if ErrorLevel
            {
            outputdebug,
               (ltrim join`s
                Function: %A_ThisFunc% - RegExMatch error.
                ErrorLevel=%ErrorLevel%
               )

            l_FoundPos:=-1
            }
        }
     else  ;-- Search backward
        {
        ;-- Programming notes:
        ;
        ;   -   The first search begins from the user-defined minimum position.
        ;       This will establish the true minimum position to begin search
        ;       calculations. If nothing is found, no additional searching is
        ;       necessary.
        ;
        ;   -   The RE_MinPos, RE_MaxPos, and RE_StartPos variables contain
        ;       1-based values.
        ;
        RE_MinPos     :=1
        RE_MaxPos     :=StrLen(l_Text)
        RE_StartPos   :=RE_MinPos
        Saved_FoundPos:=-1
        Saved_RegExOut:=""
        loop
            {
            ;-- Positional search.  Last found match (if any) wins
            l_FoundPos:=RegExMatch(l_Text,p_Pattern,r_RegExOut,RE_StartPos)-1
            if ErrorLevel
                {
                outputdebug,
                   (ltrim join`s
                    Function: %A_ThisFunc% - RegExMatch error.
                    ErrorLevel=%ErrorLevel%
                   )

                l_FoundPos:=-1
                break
                }


            ;-- If found, update saved and RE_MinPos, else update RE_MaxPos
            if (l_FoundPos>-1)
                {
                Saved_FoundPos:=l_FoundPos
                Saved_RegExOut:=r_RegExOut
                RE_MinPos     :=l_FoundPos+2
                }
            else
                RE_MaxPos:=RE_StartPos-1

            ;-- Are we done?
            if (RE_MinPos>RE_MaxPos or RE_MinPos>StrLen(l_Text))
                {
                l_FoundPos:=Saved_FoundPos
                r_RegExOut:=Saved_RegExOut
                break
                }

            ;-- Calculate new start position
            RE_StartPos:=RE_MinPos+Floor((RE_MaxPos-RE_MinPos)/2)
            }
        }

    ;-- Adjust FoundPos
    if (l_FoundPos>-1)
        l_FoundPos += (p_Max>p_Min) ? p_Min:p_Max

    Return l_FoundPos
    }



;--- Experimental
HE_FindRegExReset()
    {
    HE_FindRegEx("","",0,0,"Reset")
    }

...and here is some example code. You'll need to point to a new or existing HiEdit control.

^+F::
InputBox $FindWhat,Find RegEx,RegEx Pattern:,,220,130,,,,,%$FindWhat%
if ErrorLevel
    return

;-- Fall through to next label


^+F3::  ;-- RE Find next
if StrLen($FindWhat)=0
    return

HE_GetSel(hEdit,$StartSelPos,$EndSelPos)
$FoundPos:=HE_FindRegEx(hEdit,$FindWhat,$EndSelPos,-1,"",$RegExOut)
if $FoundPos=-1
    {
    MsgBox Next occurrence not found.  %A_Space%
    return
    }

HE_SetSel(hEdit,$FoundPos,$FoundPos+StrLen($RegExOut))
HE_ScrollCaret(hEdit)
return



^+F2::  ;-- RE Find previous
if StrLen($FindWhat)=0
    return


HE_GetSel(hEdit,$StartSelPos,$EndSelPos)
$FoundPos:=HE_FindRegEx(hEdit,$FindWhat,$StartSelPos,0,"",$RegExOut)
if $FoundPos=-1
    {
    MsgBox Next occurrence not found.  %A_Space%
    return
    }

HE_SetSel(hEdit,$FoundPos,$FoundPos+StrLen($RegExOut))
HE_ScrollCaret(hEdit)
return

Thanks for your help.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: Oct 02 2013 02:33 PM
  • Joined: 24 May 2006
Awesome. I can include this function in future versions if you like.
I tested it and it works fine.

jballi
  • Members
  • 1021 posts
  • Last active:
  • Joined: 01 Oct 2005

Awesome. I can include this function in future versions if you like.
I tested it and it works fine.

Certainly. If you think it will add value, please add it.

I don't really like RegEx. It's very cryptic, at least to me. Every time I need to develop or edit a complex pattern, I have re-learn how it works. OK, I'm starting to get used to it. But and however, no one can deny that it's a powerful tool that gives the developer (and user) the ability to do stuff that would otherwise be very difficult.

One of things you can do with RegEx that would be difficult to do otherwise: Spell Check (using the Spell library of course). When I get some time, I'll post an example using this function and the Spell library.

Thanks.