Now see what y'all did? You made me waste time trying to beat the MS code

Didn't quite make it but I did speed up my routine while making it unicode compatible.
Code: Select all
Structure CHAR
c.c
EndStructure
Procedure.s ShortenPath(File.s, MaxLength.l)
;
Protected HoldValue.l
;
Protected *HoldChar.CHAR = @File
; Create a pointer to the string in order to store characters.
While *HoldChar\c <> '\' And *HoldChar\c : *HoldChar + (1 << #PB_COMPILER_UNICODE) : Wend
; Search for the first directory delimiter.
If *HoldChar\c
; Found the first '\' character.
Protected HoldIndex.l
; Create a variable for the index.
HoldIndex = *HoldChar
; Index of the first '\' character.
Else
; No '\' character exists. No directories to compact.
If Len(File) > MaxLength : ProcedureReturn Left(File, MaxLength - 3) + "..." : Else : ProcedureReturn Left(File, MaxLength) : EndIf
; Return the path & filename truncated by the maximum number of characters.
EndIf
;
*HoldChar + (1 << #PB_COMPILER_UNICODE)
; Increment to the next character.
While *HoldChar\c <> '\' And *HoldChar\c : *HoldChar + (1 << #PB_COMPILER_UNICODE) : Wend
; Search for the next directory delimiter.
If *HoldChar\c
; A second '\' character exists.
Protected HoldSecond.l
; Index of the second '\' character.
HoldSecond = *HoldChar
; Store the address of the second '\' character.
Else
; No second '\' character exists. No directories to compact.
If Len(File) > MaxLength : ProcedureReturn Left(File, MaxLength - 3) + "..." : Else : ProcedureReturn Left(File, MaxLength) : EndIf
; Return the path & filename truncated by the maximum number of characters.
EndIf
;
While *HoldChar\c : *HoldChar + (1 << #PB_COMPILER_UNICODE) : Wend
;
Protected HoldLength.l = (*HoldChar - @File) >> #PB_COMPILER_UNICODE
; Get the length of the file.
If HoldLength <= MaxLength : ProcedureReturn File : EndIf
; Return the full path & filename if it's less or equal to the max length allowed.
Protected ReturnString.s = Space(HoldLength)
;
*HoldChar = @ReturnString + ((((HoldIndex - @File) >> #PB_COMPILER_UNICODE) + 4) << #PB_COMPILER_UNICODE)
;
HoldValue = ((HoldIndex - @File) >> #PB_COMPILER_UNICODE) + 1
PokeS(@ReturnString, PeekS(@File, HoldValue), HoldValue)
PokeS(@ReturnString + ((((HoldIndex - @File) >> #PB_COMPILER_UNICODE) + 1) << #PB_COMPILER_UNICODE), "...", 3 << #PB_COMPILER_UNICODE)
HoldValue = HoldLength - ((HoldSecond - @File) >> #PB_COMPILER_UNICODE) + 1
PokeS(*HoldChar, PeekS(HoldSecond, HoldValue), HoldValue)
;
HoldLength = HoldLength - (((HoldSecond - HoldIndex) >> #PB_COMPILER_UNICODE) - 1) + 3
;
HoldIndex = *HoldChar
;
While HoldLength > MaxLength
;
*HoldChar = HoldIndex + (1 << #PB_COMPILER_UNICODE)
;
While *HoldChar\c <> '\' And *HoldChar\c : *HoldChar + (1 << #PB_COMPILER_UNICODE) : Wend
; Search for the next directory delimiter.
If *HoldChar\c
; Another '\' character was located. Directories remain in the string.
HoldValue = HoldLength - ((*HoldChar - @ReturnString) >> #PB_COMPILER_UNICODE) + 1
PokeS(HoldIndex, PeekS(*HoldChar, HoldValue), HoldValue)
;
HoldLength = HoldLength - (((*HoldChar - HoldIndex) >> #PB_COMPILER_UNICODE) - 1) - 1
;
Else
; No more '\' characters exist.
PokeC(@ReturnString + (MaxLength << #PB_COMPILER_UNICODE), 0)
;
If HoldLength > MaxLength
PokeC(@ReturnString + ((MaxLength - 1) << #PB_COMPILER_UNICODE), '.')
PokeC(@ReturnString + ((MaxLength - 2) << #PB_COMPILER_UNICODE), '.')
PokeC(@ReturnString + ((MaxLength - 3) << #PB_COMPILER_UNICODE), '.')
EndIf
; Return the path and filename truncated to maximum allowed length.
ProcedureReturn ReturnString
;
EndIf
;
Wend
;
ProcedureReturn ReturnString
;
EndProcedure
And the changed procedure from MS...
Code: Select all
Procedure.s DisplayShortenedPath(Path.s, MaxLength.l)
;
Protected Result.l
;
Protected ReturnString.s = Space(255)
;
Result = PathCompactPathEx_(@ReturnString, @Path, MaxLength + 1, 0)
;
ProcedureReturn ReturnString
;
EndProcedure
And a little testing routine...
Code: Select all
#NumLoops = 100000
Define.l q, r, s, t, i
Define.s a, b, c, d
Path1.s = "C:\Programs\Projects\Misc\AutocompletePop.pb"
Path2.s = "C:\Programs\Hide\Me\From\View\Projects\Misc\PopAutocomplete\New Microsoft Word Document That Contains a Ridiculously Long File Name.doc"
Path3.s = "C:\Programs\Hide\Me\From\View\Projects\Misc\Pop\Auto\complete\Average Size.doc"
;-
Delay(500)
q = GetTickCount_()
For i = 1 To #NumLoops
a = ShortenPath(Path1, 40)
b = ShortenPath(Path2, 40)
c = ShortenPath(Path3, 40)
Next i
r = GetTickCount_()
s = r - q
Delay(500)
q = GetTickCount_()
For i = 1 To #NumLoops
a = DisplayShortenedPath(Path1, 40)
b = DisplayShortenedPath(Path2, 40)
c = DisplayShortenedPath(Path3, 40)
Next i
r = GetTickCount_()
t = r - q
MessageRequester("", Str(s)+" : "+Str(t))
;-
I used the PathCompactPathEx_() function in this one as it more closely mirrors my own procedure. In that it returns a string without using any GDI stuff.