AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Simple Change to IniRead
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Wish List
View previous topic :: View next topic  
Author Message
Atomhrt



Joined: 02 Sep 2004
Posts: 128
Location: Sunnyvale

PostPosted: Tue Apr 04, 2006 9:02 pm    Post subject: Simple Change to IniRead Reply with quote

I think GetPrivateProfileString is used with IniRead and if we can mod the call to allow for a null Section parameter or a null Key parameter, then the call would return all section names or key names, respectively, from an INI file.

Reference:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getprivateprofilestring.asp

"lpAppName
[in] The name of the section containing the key name. If this parameter is NULL, the GetPrivateProfileString function copies all section names in the file to the supplied buffer.
lpKeyName
[in] The name of the key whose associated string is to be retrieved. If this parameter is NULL, all key names in the section specified by the lpAppName parameter are copied to the buffer specified by the lpReturnedString parameter.".


Chris, can we get this implemented?

I already know about IniKeyGet, but this could be a better option in some cases...
_________________
I am he of whom he speaks!
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Wed Apr 05, 2006 8:33 am    Post subject: Reply with quote

IniKeyGet? What is it? Even Google returned nothing on this word.

BTW, I spotted a typo in the IniRead page: Key | The key name in the in the .ini file.
(stupid BBCode that doesn't allow nesting of color tags...)

I don't know if INI files are so much used, nowadays, that such functionnality is to be implemented. If so, I suppose it could be made on the model of Loop (registry). Otherwise, perhaps a DllCall solution is to be implemented.
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10467

PostPosted: Wed Apr 05, 2006 10:45 am    Post subject: Reply with quote

I'll add this to the to-do list; thanks. If you need it right away, hopefully it can be done with DllCall.
Back to top
View user's profile Send private message Send e-mail
Atomhrt



Joined: 02 Sep 2004
Posts: 128
Location: Sunnyvale

PostPosted: Wed Apr 05, 2006 3:58 pm    Post subject: Reply with quote

PhiLho wrote:
IniKeyGet? What is it? Even Google returned nothing on this word.


Hehe, did you search the Autohotkey site? Very Happy
Info here:
http://www.autohotkey.com/forum/viewtopic.php?t=5016&highlight=inikeyget
_________________
I am he of whom he speaks!
Back to top
View user's profile Send private message
Atomhrt



Joined: 02 Sep 2004
Posts: 128
Location: Sunnyvale

PostPosted: Wed Apr 05, 2006 8:30 pm    Post subject: Reply with quote

I have the basic DllCall created and it works:
VarSetCapacity( buff, 10000 )
i:=10000
numchar:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"Section",Str,"Key",Str,"Default",Str,buff,Int,i,Str,"C:\autokey\scripts\test.ini",Int)
msgbox, % buff

Now the issue is with my suggestion of retrieving all the section or key names. I can get it to work, and the buffer contains all key names, but they are nul char delimited. Any suggestions how I can split the buffer using a nul character as the delimiter?

Note that if you want to pass a section or key param as NULL with this call, use Int,0.
_________________
I am he of whom he speaks!
Back to top
View user's profile Send private message
Atomhrt



Joined: 02 Sep 2004
Posts: 128
Location: Sunnyvale

PostPosted: Wed Apr 05, 2006 10:25 pm    Post subject: Reply with quote

Ok, got it working. I had to convert the binary string to hex, change the nuls to newlines and convert the hex string back to binary. I utilized the Bin2Hex and Hex2Bin functions written by Laszlo (thanks!) with a one line modification of Bin2Hex.

Here is my code:

Code:


VarSetCapacity( buff, 10000 )
i:=10000

; Normal - Return Value of Key
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"Section",Str,"Key",Str,"Default",Str,buff,Int,i,Str,"C:\a.ini",Int) 

msgbox,% "Value: " . buff
 
; Return Key names
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"Section",Int,0,Str,"Default",Str,buff,Int,i,Str,"C:\a.ini",Int)

Bin2Hex(knb,buff,numchars)
StringReplace, knb, knb,-00,0A, All
StringReplace, knb, knb,-,, All
Hex2Bin(knames,knb,numchars)

msgbox,% "Key Names: " . knames

; Return Section names
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Int,0,Int,0,Str,"Default",Str,buff,Int,i,Str,"C:\a.ini",Int)

Bin2Hex(snb,buff,numchars)
StringReplace, snb, snb,-00,0A, All
StringReplace, snb, snb,-,, All
Hex2Bin(snames,snb,numchars)

msgbox,% "Section Names: ". snames

Return

Bin2Hex(ByRef h, ByRef b, n=0)      ; n bytes binary data -> stream of 2-digit
;hex
{         
                         ; n = 0: all (SetCapacity can be larger than used!)
   format = %A_FormatInteger%       ; save original integer format
   SetFormat Integer, Hex           ; for converting bytes to hex

   m := VarSetCapacity(b)
   If (n < 1 or n > m)
       n := m
   Address := &b
   h =
   Loop %n%
   {
      x := *Address                 ; get byte in hex
      StringTrimLeft x, x, 2        ; remove 0x
      x = 0%x%                      ; pad left
      StringRight x, x, 2           ; 2 hex digits
      h = %h%-%x%                   ; modded for null character identification
      Address++
   }
   SetFormat Integer, %format%      ; restore original format
}

Hex2Bin(ByRef b, h, n=0)            ; n hex digit-pairs -> binary data
{                                   ; n = 0: all. (Only ByRef can handle binaries)
   m := Ceil(StrLen(h)/2)
   If (n < 1 or n > m)
       n := m
   Granted := VarSetCapacity(b, n, 33)
   IfLess Granted,%n%, {
      ErrorLevel = Mem=%Granted%
      Return
   }
   StringLeft b, b, n
   Address := &b
   Loop %n%
   {
      StringLeft  x, h, 2
      StringTrimLeft h, h, 2
      x = 0x%x%
      DllCall("RtlFillMemory", "UInt", Address, "UInt", 1, "UChar", x)
      Address++
   }
}


I threw this all together rather quickly so it may have an issue or three.
_________________
I am he of whom he speaks!
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4012
Location: Pittsburgh

PostPosted: Wed Apr 05, 2006 11:41 pm    Post subject: Reply with quote

Try CharReplace(buff,0,13,numchars) with this function
Code:
CharReplace(ByRef Buf, Ch1, Ch2, Len=0) {
   m := VarSetCapacity(Buf)
   If (Len < 1 or Len > m)
       Len = %m%
   Loop %Len%
      If (*(&Buf+A_Index-1) = Ch1)
         DllCall("RtlFillMemory", UInt,&Buf+A_Index-1, UInt,1, UInt,Ch2)
}

Edit: fixed typo: 1st param at call must be the buffer name.


Last edited by Laszlo on Thu Apr 06, 2006 3:47 am; edited 1 time in total
Back to top
View user's profile Send private message
Atomhrt



Joined: 02 Sep 2004
Posts: 128
Location: Sunnyvale

PostPosted: Thu Apr 06, 2006 1:01 am    Post subject: Reply with quote

I tried it with CharReplace(buff,0,13,numchars) and it seemed to choke when it got to the first nul character in the string. In other words, it returned the first key name and then a garbage char, then nothing... Does it work for you? If so, please post INI and example code. Thx
_________________
I am he of whom he speaks!
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4012
Location: Pittsburgh

PostPosted: Thu Apr 06, 2006 3:42 am    Post subject: Reply with quote

Sorry, the 1st parameter has to be "buff", of course, as you noticed. It works for me (Win XP, SP2, AHK 1.0.43.04):
Code:
i = 10000
VarSetCapacity( buff, i )

; Return Key names
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"HotKeys"
   ,Int,0,Str,"???",Str,buff,Int,i,Str,"c:\t\AutoHotKey\SKey.ini",Int)
CharReplace(buff, 0, 13, numchars)
MsgBox %buff%

CharReplace(ByRef Buf, Ch1, Ch2, Len=0) { ; In Buf all char Ch1 is replaced with Ch2 (NUL:0->`n:13)
   m := VarSetCapacity(Buf)
   If (Len < 1 or Len > m)
       Len = %m%
   Loop %Len%
      If (*(&Buf+A_Index-1) = Ch1)
         DllCall("RtlFillMemory", UInt,&Buf+A_Index-1, UInt,1, UInt,Ch2)
}
My ini file looks like
Code:
[ProcessDefaults]
ANSI =Mew32.exe,sbrowser.exe,pdexplo.exe
Unicode =WinWord.exe,PowerPnt.exe,WordPad.exe,Notepad.exe,IEXPLORE.EXE,nlnotes.exe,WINWORD.EXE
OFF =MathKernel.exe,Matlab.exe,Calc.exe

[HotKeys]
ForwardKey  = CapsLock
BackwardKey = CapsLock & LShift
SymbolUpKey = CapsLock & Tab
SymbolDnKey = CapsLock & q
ReplaceKey  = CapsLock & r
GuiWindKey  = !CapsLock

[ANSIcodeRings]
...and the MsgBox shows
Code:
---------------------------
w.ahk
---------------------------
ForwardKey
BackwardKey
SymbolUpKey
SymbolDnKey
ReplaceKey
GuiWindKey
---------------------------
OK   
---------------------------
Back to top
View user's profile Send private message
corrupt



Joined: 29 Dec 2004
Posts: 2397

PostPosted: Thu Apr 06, 2006 6:36 am    Post subject: Reply with quote

Code:
IniReadEx(IFile, ISect="", IKey="", Delim=124, buffsz=10000)
{
  IfNotExist, %IFile%
    Return, "Error: File not found"
  VarSetCapacity( buff, buffsz )
  If ISect=
    numchar:=DllCall("kernel32.dll\GetPrivateProfileString",Int,0,Int,0,Int,0,Str,buff,Int,buffsz,Str,IFile,Int)
  Else If IKey=
    numchar:=DllCall("kernel32.dll\GetPrivateProfileString",Str,ISect,Int,0,Int,0,Str,buff,Int,buffsz,Str,IFile,Int)
  Else
    numchar:=DllCall("kernel32.dll\GetPrivateProfileString",Str,ISect,Str,IKey,Int,0,Str,buff,Int,buffsz,Str,IFile,Int)   
  If (numchar > 1) {
    Loop {
    ahklen := StrLen(buff)
    If (ahklen < (numchar -1))
      DllCall("RtlFillMemory", UInt,(&buff+ahklen), UInt,1, UChar,Delim)
    Else
      break
    }
  }
  Return, buff
}
Back to top
View user's profile Send private message Visit poster's website
Atomhrt



Joined: 02 Sep 2004
Posts: 128
Location: Sunnyvale

PostPosted: Thu Apr 06, 2006 3:37 pm    Post subject: Reply with quote

This is what I was using: msgbox,% "Key Names: " . buff
...which does not work...
msgbox,Key Names: %buff%
... works fine...
Do we have a bug here?
_________________
I am he of whom he speaks!
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4012
Location: Pittsburgh

PostPosted: Thu Apr 06, 2006 4:36 pm    Post subject: Reply with quote

Add "StringReplace buff, buff, `n, `r`n, All". It looks like in expressions `n is not enough for a new line.
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4012
Location: Pittsburgh

PostPosted: Thu Apr 06, 2006 4:50 pm    Post subject: Reply with quote

You can use the CharChange function below, which is slower, but can replace a char with an arbitrary string.
Code:
i = 10000
VarSetCapacity( buff, i )

; Return Key names
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"HotKeys"
   ,Int,0,Str,"???",Str,buff,Int,i,Str,"c:\t\AutoHotKey\SKey.ini",Int)
msgbox % "Key Names: " CharChange(buff, 0, "`r`n", numchars)

CharChange(ByRef Buf, Ch, Str, Len=0) { ; In Buf all char of code Ch is replaced with Str
   m := VarSetCapacity(Buf)             ; Buf := CharChange(Buf, 0, "`r`n"): Nul -> new line
   If (Len < 1 or Len > m)
       Len = %m%
   Loop %Len%
      If (*(&Buf+A_Index-1) = Ch)
           out = %out%%Str%
      Else out:= out Chr(*(&Buf+A_Index-1))
   Return  out
}


Last edited by Laszlo on Thu Apr 06, 2006 5:08 pm; edited 1 time in total
Back to top
View user's profile Send private message
corrupt



Joined: 29 Dec 2004
Posts: 2397

PostPosted: Thu Apr 06, 2006 5:00 pm    Post subject: Reply with quote

Using the function I posted above:

Code:

MsgBox, % IniReadEx("C:\a.ini", "HotKeys" )


or change the file name, section, etc... for the file you are using...
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4012
Location: Pittsburgh

PostPosted: Thu Apr 06, 2006 5:21 pm    Post subject: Reply with quote

@corrupt: Your specialized version of StringReplace suffers from the same problem: if you set the delimiter character code to 13 (`n), it won't always be recognized as new line. With your default pipe "|" the problem remains hidden, everything is in one line. If some of your key names contain pipe characters, you are out of luck. `n is safer, because it cannot be part of a key name or value.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Wish List All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group