AutoHotkey Community

It is currently May 27th, 2012, 10:48 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: March 18th, 2008, 8:43 am 
Offline
User avatar

Joined: October 7th, 2006, 8:45 am
Posts: 3330
Location: Simi Valley, CA
Well, sorry, System Monitor and Ian... looks like I beat you to it.

Update:: replaced ControlGetFocus with the workaround supplied in the help docs. This may perform better than the previous version, however it no longer checks the type of control which is currently focused (although the script probably won't detect any changes in the text of a non-edit, non-cbbox control.

I suppose I forgot to clearly state the scope of this script:
Purpose: In a plain text editor, this script is meant to offer a one-touch hotkey that will fill in the estimated remaining letters of a partially typed word under the following conditions: either the word is contained in a list of words that the user has previously completed using this hotkey OR the word is contained in a list of words that the user has recently typed.

This script will never actually send keys without specific action on the user's part (via the specified hotkey).

Intended Use: for programmers who habitually misspell their variable and function names and/or get tired of repeatedly typing in long but very descriptive variable names.

Here's version 2² of my Anti-RSI Script:
Code:
; RSI helper ... [VxE] style! ___ Version 2.0
; Keeps track of the words you type and offers to fill in the rest of a
; recognized word.
; Order of priority is given first to any matches in the VIP list.
; Order of Priority is then based on the last time a matching word was used.

;////////////////////////////////////////////////// Config Section
History_Length = 100 ; how long is our normal history?
; Our VIP history is eternal and infinite !! (BWWAAAHHAHAhahahehehuhuhmeh)
Selector_Hotkey = RShift ; This hotkey becomes available when the script makes a guess
Needle_Min_Length = 3 ; how many letters before the script makes a guess ?
; NOTE: words with a length less than this value+2 will not appear in the history
Keep_History_In_File = MyRSIHelperHistory.txt
Restrict_To_Window = Notepad ; set to "A" for Any Active window
; KNOWN COMPATIBILITY WITH PLAIN-TEXT EDITORS ONLY !!!
Terminal_Chars := "`n`r`t ,." ; These mark effective word breaks
;////////////////////////////////////////////////// End Config

SetTimer, PollCurrentControl, 200
SetWorkingDir, %A_ScriptDir%
SetTitleMatchMode, 2
#SingleInstance Force
If Keep_History_In_File
{
   OnExit, SaveHistory
   IfExist, %Keep_History_In_File%
   {
      FileRead, WordDB, %Keep_History_In_File%
      cdb = MyVIPWords
      Loop, Parse, WordDB, `n, `r
         If InStr(A_LoopField, A_Space) || !A_LoopField
         {
            If A_LoopField = My Word History
               cdb = MyWordHistory
            If InStr( A_LoopField, "History Length =" ) = 1
               History_Length := SubStr( A_LoopField, 17 ) +0
            If InStr( A_LoopField, "Selector Hotkey =" ) = 1
               Selector_Hotkey := SubStr( A_LoopField, 18 )
            If InStr( A_LoopField, "Needle Minimum Length =" ) = 1
               Needle_Min_Length := SubStr( A_LoopField, 25 ) +0
            If InStr( A_LoopField, "Restrict to Window =" ) = 1
               Restrict_To_Window := SubStr( A_LoopField, 21 )
         }
         Else
            %cdb% .= "`n" A_LoopField
   }
}
AutoTrim, on
History_Length = %History_Length%
Selector_Hotkey = %Selector_Hotkey%
Needle_Min_Length = %Needle_Min_Length%
Restrict_To_Window = %Restrict_To_Window%
If Restrict_To_Window = A
   Restrict_To_Window =

; This is the meat of the script. Had to set a sleep on the LButton cuz the script
; was disabling the double click to select a word :(
; Anyways, this script snatches the current edit control's text, scans it for changes
; then builds or clears a needle based on the difference. An ending char following
; a long enough needle causes that needle to become a word in the history.
PollCurrentControl:
IFWinNotActive %Restrict_To_Window%
{
   tooltip
   return
}
;;;;;;;;;;; copied from help docs on "controlgetfocus" command
GuiThreadInfoSize = 48
VarSetCapacity(GuiThreadInfo, GuiThreadInfoSize)
InsertInteger(GuiThreadInfoSize, GuiThreadInfo, 0)
if not DllCall("GetGUIThreadInfo", uint, 0, str, GuiThreadInfo)
    return
CHWND := ExtractInteger(GuiThreadInfo, 12)  ; Retrieve the hwndFocus field from the struct.
;;;;;;;;;;;;;;;;;;;; end of plagarism section :-D ;;;;;;;;;;;;;

If OldFocus != %chwnd%
   oldtex := needle := ""
ControlGetText, testex, , Ahk_Id %chwnd%
testex := StripFormatting(testex) ; handle formatted text
If ( testex != oldtex ) ; On current control text change
{
   Loop, Parse, testex
   {
      If ( SubStr(testex, A_Index, 1) != SubStr(oldtex, A_Index, 1) )
      {
         atex := SubStr( testex, A_Index )
         btex := SubStr( oldtex, A_Index )
         ctex := SubStr( oldtex, 1, A_Index-1)
         If (bPos := InStr(btex, atex)) ; characters have been deleted (bksp / del / cut)
         {
            needle := ""
            break
         }
         If !(bPos := InStr(atex, btex)) ;  characters have been changed (select paste / insert mode )
            Loop, % StrLen( btex )
               If InStr(atext, oldtex := SubStr(btex, A_Index+1))
               {
                  btex := oldtex
                  break
               }
         If (bPos := InStr(atex, btex)) ; characters have been added
         {
            AppChar := SubStr( atex, 1, bPos-1 ) ; retrieve the added chars
            StringReplace, AppChar, AppChar, `r

            bPos := InStr( cTex, A_Space, 0,0 )
            Loop, Parse, Terminal_Chars ; rebuild the needle
               If (bPos < (nPos := InStr( cTex, A_LoopField, 0,0)) || A_Index = 1 )
                  bPos := nPos
            needle := SubStr(cTex, bPos+1) . AppChar

            bPos := InStr( needle, A_Space )
            Loop, Parse, Terminal_Chars
               If (nPos := InStr( needle, A_LoopField )) && (( npos < bpos ) || !bPos)
                  bPos := nPos
            If bPos
            {
               word := SubStr( needle, 1, bPos-1 )
               If (StrLen(Word) > 1 + Needle_Min_Length )
                  MyWordHistory := AddMWHistory( MyWordHistory, Word )
               needle := ""
            }
         }

      break
      }
   }
}
If (StrLen(Needle) >= Needle_Min_Length )
&& ( bPos := InStr( WordDB := MyVIPWords "`n" MyWordHistory "`n", "`n" needle))
{
   ; we have a match, so tooltip out the part that we want to send
   Word := SubStr( WordDB, bPos+1, InStr(WordDB, "`n", 0, bPos+1) - bPos - 1)
   If Word = %needle%
   {
      tooltip
      Hotkey, %Selector_Hotkey%, hklabel, off
      StatusFlag =
   }
   else
   {
      tooltip, % SubStr(Word, StrLen(needle)+1), %A_CaretX%, % A_CaretY - 25
      Hotkey, %Selector_Hotkey%, hklabel, on
      StatusFlag = Matched and pending user action
   }
}
else If StatusFlag
{
   tooltip
   Hotkey, %Selector_Hotkey%, hklabel, off
   StatusFlag =
}
oldtex := testex
OldFocus = %chwnd%
return

; Not much to explain here... explain wouldn't even be in a function
; if it were'nt used exactly the same way in 2 different places
AddMWHistory( db, item )
{
   Stringreplace, db, db, `n%item%`n, `n`n, a
   Stringreplace, db, db, `n`n, `n, a
   Return % "`n" item "`n" db
}

StripFormatting(str)
{
   ; future implementation to handle edit controls in word processing progs and such
   ; currently, things like rich-text tags and M$ Word formatting cannot be handled.
   return % "`n`n`n`n`n`n" str "`n«º»`n«ª»"
}

; The chosen hotkey. Heep in mind that this hotkey is turned off at all times except when this
; script has suggested a word to complete. In that case this hotkey pastes the word.
hklabel:
   MyVIPWords := AddMWHistory( MyVIPWords, Word )
   Send % "{blind}" SubStr(Word, StrLen(needle)+1) . (needle := "")
return

; pretty obvious, no?
saveHistory:
If Keep_History_In_File
{
   FileDelete, %Keep_History_In_File%
   sleep 50
   FileAppend, % "History Length =       `t" History_Length
      . "`nSelector Hotkey =    `t" Selector_Hotkey
      . "`nNeedle Min Length =`t" Needle_Min_Length
      . "`nRestrict To Window =`t" ((Restrict_To_Window) ? (Restrict_To_Window) : ("A"))
      . "`n`nMy VIP Words`n" MyVIPWords
      . "`n`nMy Word History`n" MyWordHistory
      . "" , %Keep_History_In_File%
}
Exitapp
~` & esc::
Exitapp ; The End... and all the little trolls lived happily ever after.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; More stuff copied from the manual
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
    Loop %pSize%  ; Build the integer by adding up its bytes.
        result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
    if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
        return result  ; Signed vs. unsigned doesn't matter in these cases.
    ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
    return -(0xFFFFFFFF - result + 1)
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
    Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
        DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; That's it for now


What's New:
1. Changed how the script handles saving the word list and fixed that bugginess. Saved data has been tested somewhat.
2. Changed the method of needle construction. Now the needle is independent of prior input ( meaning that you can move the caret to a partially completed word, type a char, and the script will use whatever part of that word that is to the left of the caret as the needle).
3. The period of the main loop is a WHOPPING HUGE 200 ms, just to illustrate how this script can handle input at any speed. You can even copy/paste pieces of words and they will be correctly handled by the next needle.
4. I forgot to mention before, but this is very important This script will not work in a formatted text editor!!!!. It works fine in notepad 8)
5. Not exactly new, but, this script will become immediately dormant if a non-edit control is in focus or if a non-matching window becomes active.

_________________
Ternary (a ? b : c) guide     TSV Table Manipulation Library
Post code inside [code][/code] tags!


Last edited by [VxE] on March 22nd, 2008, 10:57 pm, edited 4 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 18th, 2008, 10:58 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
It doesnt seem to work at all for me. It just keeps adding the same thing over and over to MyRSIHelperHistory.txt. Just a garbled mess:

Code:
My VIP Words
My VIP Words
My VIP Words
My VIP Words
My VIP Words


My Word History

My Word History


my word History
my word History
my word History
My VIP Words


My Word History



with loads of unprintable characters (appear as whitespace here). It doesnt load any words. There are many reasons that this program will never work however (unrelated to the current bugs), such as what happens when you type backspaces or delete chars with the mouse and cut, and in non-standard controls that text cannot be retrieved from.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 19th, 2008, 4:14 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
The concept is nice.

If we power the script with Cheetah2.dll, we can seek words from a huge dictionary of words..

:)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 20th, 2008, 2:16 am 
Offline

Joined: July 15th, 2007, 1:43 am
Posts: 1320
MASSIVE dictionary file


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 20th, 2008, 2:35 am 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
thanks for the dictionary file. shame this script doesnt work. i shall write one as i will actually be wanting this for a project of mine. i will have to write it around the fact that it can never fully 100% work.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 20th, 2008, 2:58 am 
Offline
User avatar

Joined: October 7th, 2006, 8:45 am
Posts: 3330
Location: Simi Valley, CA
Well, I'm sorry I didn't make this script's intention/purpose clear at first, so I won't blame you, tic, for your comments.

Anyways, I have edited the top post with version 2, on which I have done some changes and more testing. There's also a bunch of new info on compatibility issues and suggested usage.

In a nutshell, this script uses Two Hotkeys, Zero Input Commands, a 200ms delay on the main loop, and never hijacks the clipboard

For archival porpoises, this is the original version:
Code:
; RSI helper ... [VxE] style! ___ Version 0.a
; Keeps track of the words you type and can [EDIT] never was automatic automatically complete words
; that you have recently or frequently typed.
; Order of priority is given first to any matches in the VIP list.
; Order of Priority is then based on the last time that word was used.

History_Length = 100 ; how long is our normal history?
; Our VIP history is eternal and infinite !! (BWWAAAHHAHAhahahehehuhuhmeh)
Needle_Min_Length = 3 ; how many letters before the script makes a guess ?
Keep_History_In_File = C:\MyRSIHelperHistory.txt
Restrict_To_Window = Notepad ; set to "A" for Any Active window

SetTimer, PollCurrentControl, 100
Hotkey, LWin, LWin, off
SetTitleMatchMode, 2
If Keep_History_In_File
{
   OnExit, SaveHistory
   IfExist, %Keep_History_In_File%
   {
      FileRead, MyWordHistory, %Keep_History_In_File%
      StringReplace, MyWordHistory , mywordHistory, `nmy word History`n, `n¿my word History`n
      Loop, Parse, mywordHistory, ¿
         If A_Index = 1
            myvIPWords := A_LoopField
         else
            mywordHistory := A_LoopField
   }
}

; This is the meat of the script. Had to set a sleep on the LButton cuz the script
; was disabling the double click to select a word :(
; Anyways, this script snatches the current edit control's text, scans it for changes
; then builds or clears a needle based on the difference. An ending char following
; a long enough needle causes that needle to become a word in the history.
PollCurrentControl:
If (GetKeyState( "LButton" ))
   Sleep 500
If !(w_id := WinExist(Restrict_To_Window))
   return
ControlGetFocus, ccnn, Ahk_Id %w_id%
If !InStr(ccnn, "Edit") = 1
   return
If OldFocus != %w_id%%ccnn%
   oldtex := needle := ""
ControlGetText, testex, %ccnn%, Ahk_Id %w_id%
If ( StrLen(testex) != StrLen(oldtex) && (oldtex != "") ) ; enter block IFF the text has changed length
{
   Loop, Parse, testex
      If ( SubStr(testex, A_Index, 1) != SubStr(oldtex, A_Index, 1) )
      {
         atex := SubStr(testex, A_Index)
         btex := Pos := SubStr(oldtex, A_Index)
         If ( atex = "" || InStr( btex, atex )) ; user has deleted text
            needle := ""
         Else If ( btex = "" || Pos := InStr(atex, btex)) ; user has added text
         {
            Pos += 1
            If Pos > 1
               Pos -= 2
            AppChar := SubStr( atex, 1, Pos) ; to handle more than 1   
            If (needle != "")
         && SubStr( testex, A_Index - StrLen(needle), StrLen(needle) ) != needle
               needle := ""
            If InStr( "`t `,.?`r`n", SubStr( AppChar, 0, 1 ) ) ; ending chars
            || InStr(AppChars, "`r") || InStr(AppChars, "`n")
            {
               If  ( StrLen(needle) > Needle_Min_Length+2 )
               {
                  MyWordHistory := AddMWHistory( MyWordHistory, Needle )
                  Stringreplace, MyWordHistory, MyWordHistory, `n, `n, UseErrorLevel
                  If ErrorLevel > %History_Length%
                     StringLeft, MyWordHistory, MyWordHistory, % InStr(MyWordHistory, "`n", 0, -1)
               }
               Needle := ""
               AppChar := ""
               break
            }
            Else
               Needle .= AppChar
         }
         break ; because we're done
      }

   ; this next chunk of code is what handles the display of the tooltip and whether or not to
   ; activate the LWin hotkey to let the user decide to use the word

   WordDB := "`n" MyVIPWords "`n" MyWordHistory
   If (StrLen(needle) >= Needle_Min_Length) && ( wPos := InStr(WordDB, "`n" needle))
   {
      Tooltip % (mhwMatch := SubStr( WordDB, 1+wPos, InStr(WordDB, "`n", 0, wPos
      +1) - wPos - 1 )), %A_Caretx%, % A_CaretY - 20
      Hotkey, LWin, LWin, on
   }
   Else
   {
      If mhwMatch
      {
         Hotkey, LWin, LWin, off
         Tooltip
      }
      mhwMatch := ""
   }
}
oldtex := testex
OldFocus = %w_id%%ccnn%
return

; Not much to explain here... it wouldn't even be in a function
; if it were'nt used exactly the same way in 2 different places
AddMWHistory( db, item )
{
   Stringreplace, db, db, `n%item%`n, `n`n, a
   Stringreplace, db, db, `n`n, `n, a
   Return % "`n" item "`n" db
}

; The chosen hotkey. Heep in mind that this hotkey is turned off at all times except when this
; script has suggestes a word to complete. In that case this hotkey pastes the word.
LWin::
   Send % SubStr( mhwMatch, StrLen(needle)+1 )
   MyVIPWords := AddMWHistory( MyVIPWords, mhwMatch )
   needle := mhwMatch := ""
return

; pretty obvious, no?
saveHistory:
If Keep_History_In_File
{
   FileDelete, %Keep_History_In_File%
   sleep 50
   FileAppend, % "My VIP Words`n" MyVIPWords "`n`nMy Word History`n"
   . MyWordHistory , %Keep_History_In_File%
}
Exitapp ; The End... and all the little trolls lived happily ever after.

_________________
Ternary (a ? b : c) guide     TSV Table Manipulation Library
Post code inside [code][/code] tags!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 20th, 2008, 3:34 am 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
This version will now show the tooltip for some words, but when i press the hotkey nothing happens. Am i supposed to do something else as well? And when it displays the words, then it would probably be better to display the whole word and not just the remaining characters. I havent managed to get it to work yet, i must be doing something wrong


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 20th, 2008, 4:02 am 
Offline
User avatar

Joined: October 7th, 2006, 8:45 am
Posts: 3330
Location: Simi Valley, CA
Hmm... just to be sure, you did press the "RAlt" hotkey when a tooltip was showing, right? I changed it from LWin because my right thumb is usually right there.

For basic testing, here's the steps I used:
cancel any other running AHK scripts.
Download the script from the top post and save it as a typical AHK file
run the scrip
open notepad
enter the following: "Happily ever after.{enter}"
then enter: "Hap{ralt} ever aft{ralt}."
then you should be looking at two identical lines of text

After that I did some more tricky testing, like moving the caret to between the two 'p's in "Happily" and typing 'p' :P it ends up as "Happilypily"

As far as putting the whole word in the tooltip, I really can't think of anything more useful than WYSIWIG. :(

_________________
Ternary (a ? b : c) guide     TSV Table Manipulation Library
Post code inside [code][/code] tags!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 20th, 2008, 11:57 pm 
Offline

Joined: March 9th, 2007, 2:47 am
Posts: 509
Location: Unknown
Not working at all for me :(
Not capturing the hotkey or anything


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 21st, 2008, 2:51 am 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
Yes, I did exactly those steps and it sometimes shows the remaining letters of the words im typing, but the hotkey to autocomplete the word never works.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 21st, 2008, 5:26 am 
Offline
User avatar

Joined: October 7th, 2006, 8:45 am
Posts: 3330
Location: Simi Valley, CA
That's very odd indeed and I can't reproduce the errors. Perhaps it's a problem with ControlGetText or maybe another program is hooking the 'alt' key. It may even be a problem with Vista (if you're running that). The hotkey can be easily changed by editing the saved values at the top of the history file (the saved values supersede the defaults in the script itself). If you'd like to try another way to get the entire text of the current control/window, it's up to you...

Like I said, I did test it in Notepad (btw: I'm running XP sp2) and it works for me.

_________________
Ternary (a ? b : c) guide     TSV Table Manipulation Library
Post code inside [code][/code] tags!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 21st, 2008, 3:46 pm 
Offline

Joined: March 9th, 2007, 2:47 am
Posts: 509
Location: Unknown
Im running xp sp2 and using it in notepad. Its kinda weird.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 21st, 2008, 3:53 pm 
Offline

Joined: April 22nd, 2007, 6:33 pm
Posts: 1833
im on 2003 and running in notepad. (2003 runs exactly the same as xp for all purposes relating to ahk so far)


Report this post
Top
 Profile  
Reply with quote  
PostPosted: March 22nd, 2008, 10:56 pm 
Offline
User avatar

Joined: October 7th, 2006, 8:45 am
Posts: 3330
Location: Simi Valley, CA
OK, I have scoured the help docs on the commands ControlGetText and ControlGetFocus and I found something suspicious that may be the problem. So I removed ControlGetFocus and replaced it with the DllCall() workaround found in the help docs and it seems to work (at least, I don't think I added any bugs).

Another thought is that it may help to change the hotkey to RShift, keeping in mind that this hotkey is only active when letters are available in the tooltip (the key does its normal function at other times). This may help since the shift keys never change focus by themselves.

Another thing to mention: In the script is a function called StripFormatting() that doesn't do anything. In future versions (or if someone else would like to) this function may be filled in to remove things like rich text and perhaps M$ Word formatting from the text retrieved from the control

Archive: version that is buggy...
Code:
; RSI helper ... [VxE] style! ___ Version 2.0
; Keeps track of the words you type and offers to fill in the rest of a
; recognized word.
; Order of priority is given first to any matches in the VIP list.
; Order of Priority is then based on the last time a matching word was used.

;////////////////////////////////////////////////// Config Section
History_Length = 100 ; how long is our normal history?
; Our VIP history is eternal and infinite !! (BWWAAAHHAHAhahahehehuhuhmeh)
Selector_Hotkey = RAlt ; This hotkey becomes available when the script makes a guess
Needle_Min_Length = 3 ; how many letters before the script makes a guess ?
; NOTE: words with a length less than this value+2 will not appear in the history
Keep_History_In_File = MyRSIHelperHistory.txt
Restrict_To_Window = Notepad ; set to "A" for Any Active window
; KNOWN COMPATIBILITY WITH PLAIN-TEXT EDITORS ONLY !!!
Terminal_Chars := "`n`r`t ,." ; These mark effective word breaks
;////////////////////////////////////////////////// End Config

SetTimer, PollCurrentControl, 200
SetWorkingDir, %A_ScriptDir%
SetTitleMatchMode, 2
#SingleInstance Force
If Keep_History_In_File
{
   OnExit, SaveHistory
   IfExist, %Keep_History_In_File%
   {
      FileRead, WordDB, %Keep_History_In_File%
      cdb = MyVIPWords
      Loop, Parse, WordDB, `n, `r
         If InStr(A_LoopField, A_Space) || !A_LoopField
         {
            If A_LoopField = My Word History
               cdb = MyWordHistory
            If InStr( A_LoopField, "History Length =" ) = 1
               History_Length := SubStr( A_LoopField, 17 ) +0
            If InStr( A_LoopField, "Selector Hotkey =" ) = 1
               Selector_Hotkey := SubStr( A_LoopField, 18 )
            If InStr( A_LoopField, "Needle Minimum Length =" ) = 1
               Needle_Min_Length := SubStr( A_LoopField, 25 ) +0
            If InStr( A_LoopField, "Restrict to Window =" ) = 1
               Restrict_To_Window := SubStr( A_LoopField, 21 )
         }
         Else
            %cdb% .= "`n" A_LoopField
   }
}
AutoTrim, on
History_Length = %History_Length%
Selector_Hotkey = %Selector_Hotkey%
Needle_Min_Length = %Needle_Min_Length%
Restrict_To_Window = %Restrict_To_Window%
If Restrict_To_Window = A
   Restrict_To_Window =

; This is the meat of the script. Had to set a sleep on the LButton cuz the script
; was disabling the double click to select a word :(
; Anyways, this script snatches the current edit control's text, scans it for changes
; then builds or clears a needle based on the difference. An ending char following
; a long enough needle causes that needle to become a word in the history.
PollCurrentControl:
If (GetKeyState( "LButton" ))
   Sleep 500
If !(w_id := WinActive(Restrict_To_Window))
{
   tooltip
   return
}
ControlGetFocus, ccnn, Ahk_Id %w_id%
If !InStr(ccnn, "Edit") = 1
{
   tooltip
   return
}
If OldFocus != %w_id%%ccnn%
   oldtex := needle := ""
ControlGetText, testex, %ccnn%, Ahk_Id %w_id%
testex := StripFormatting(testex) ; handle formatted text
If ( testex != oldtex ) ; On current control text change
{
   Loop, Parse, testex
   {
      If ( SubStr(testex, A_Index, 1) != SubStr(oldtex, A_Index, 1) )
      {
         atex := SubStr( testex, A_Index )
         btex := SubStr( oldtex, A_Index )
         ctex := SubStr( oldtex, 1, A_Index-1)
         If (bPos := InStr(btex, atex)) ; characters have been deleted (bksp / del / cut)
         {
            needle := ""
            break
         }
         If !(bPos := InStr(atex, btex)) ;  characters have been changed (select paste / insert mode )
            Loop, % StrLen( btex )
               If InStr(atext, oldtex := SubStr(btex, A_Index+1))
               {
                  btex := oldtex
                  break
               }
         If (bPos := InStr(atex, btex)) ; characters have been added
         {
            AppChar := SubStr( atex, 1, bPos-1 ) ; retrieve the added chars
            StringReplace, AppChar, AppChar, `r

            bPos := InStr( cTex, A_Space, 0,0 )
            Loop, Parse, Terminal_Chars ; rebuild the needle
               If (bPos < (nPos := InStr( cTex, A_LoopField, 0,0)) || A_Index = 1 )
                  bPos := nPos
            needle := SubStr(cTex, bPos+1) . AppChar

            bPos := InStr( needle, A_Space )
            Loop, Parse, Terminal_Chars
               If (nPos := InStr( needle, A_LoopField )) && (( npos < bpos ) || !bPos)
                  bPos := nPos
            If bPos
            {
               word := SubStr( needle, 1, bPos-1 )
               If (StrLen(Word) > 1 + Needle_Min_Length )
                  MyWordHistory := AddMWHistory( MyWordHistory, Word )
               needle := ""
            }
         }

      break
      }
   }
}
If (StrLen(Needle) >= Needle_Min_Length )
&& ( bPos := InStr( WordDB := MyVIPWords "`n" MyWordHistory "`n", "`n" needle))
{
   ; we have a match, so tooltip out the part that we want to send
   Word := SubStr( WordDB, bPos+1, InStr(WordDB, "`n", 0, bPos+1) - bPos - 1)
   If Word = %needle%
   {
      tooltip
      Hotkey, %Selector_Hotkey%, hklabel, off
      StatusFlag =
   }
   else
   {
      tooltip, % SubStr(Word, StrLen(needle)+1), %A_CaretX%, % A_CaretY - 25
      Hotkey, %Selector_Hotkey%, hklabel, on
      StatusFlag = Matched and pending user action
   }
}
else If StatusFlag
{
   tooltip
   Hotkey, %Selector_Hotkey%, hklabel, off
   StatusFlag =
}
oldtex := testex
OldFocus = %w_id%%ccnn%
return

; Not much to explain here... explain wouldn't even be in a function
; if it were'nt used exactly the same way in 2 different places
AddMWHistory( db, item )
{
   Stringreplace, db, db, `n%item%`n, `n`n, a
   Stringreplace, db, db, `n`n, `n, a
   Return % "`n" item "`n" db
}

StripFormatting(str)
{
   ; future implementation to handle edit controls in word processing progs and such
   ; currently, things like rich-text tags and M$ Word formatting cannot be handled.
   return % "`n`n`n`n`n`n" str "`n«º»`n«ª»"
}

; The chosen hotkey. Heep in mind that this hotkey is turned off at all times except when this
; script has suggested a word to complete. In that case this hotkey pastes the word.
hklabel:
   MyVIPWords := AddMWHistory( MyVIPWords, Word )
   Send % "{blind}" SubStr(Word, StrLen(needle)+1) . (needle := "")
return

; pretty obvious, no?
saveHistory:
If Keep_History_In_File
{
   FileDelete, %Keep_History_In_File%
   sleep 50
   FileAppend, % "History Length =       `t" History_Length
      . "`nSelector Hotkey =    `t" Selector_Hotkey
      . "`nNeedle Min Length =`t" Needle_Min_Length
      . "`nRestrict To Window =`t" ((Restrict_To_Window) ? (Restrict_To_Window) : ("A"))
      . "`n`nMy VIP Words`n" MyVIPWords
      . "`n`nMy Word History`n" MyWordHistory
      . "" , %Keep_History_In_File%
}
Exitapp
~` & esc::
Exitapp ; The End... and all the little trolls lived happily ever after.

_________________
Ternary (a ? b : c) guide     TSV Table Manipulation Library
Post code inside [code][/code] tags!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 23rd, 2008, 8:12 pm 
Offline

Joined: March 9th, 2007, 2:47 am
Posts: 509
Location: Unknown
Works :D
Although I wish it would work in PsPad :(


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 34 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group