
 ; ------------------------------------------------------------------
 ;
 ; Function InChr(sStr As String, ByVal AscW_Chr As Integer, _
 ;                Optional ByVal lStartPos As Long = 1, _
 ;                Optional ByVal lRightLimit As Long = 0) As Long
 ;
 ; InChr searches for a character in a unicode string and if found
 ; returns the position of the first match as the function result.
 ;
 ; It uses a one based character index (1st character is 1, 2nd is 2 etc)
 ; for both the lStartPos parameter and the returned character position.
 ;
 ; If the optional start position is less than one it defaults to one.
 ;
 ; The optional right limit specifies the one based position in the
 ; string of the last possible match. If omitted/less than one the
 ; string is searched from start pos to string end.
 ;
 ; If the right limit parameter is beyond the length of the string
 ; the string is searched from start pos to string end.
 ; ------------------------------------------------------------------
 ; If the function succeeds, it returns the one based index
 ; of the first character match, or:
 ;  0 = no match found
 ;  0 = zero length main string
 ;  0 = startpos parameter out of range (startpos > len str)
 ; ------------------------------------------------------------------

 .686             ; 32-bit instruction set
 .model flat      ; Protected memory, 4GB limit
 .code            ; Start of code

InChr proc near   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

   push ebp          ; preserve base pointer value
   mov ebp, esp      ; set up pointer to parameters

   string equ [ebp+12]
   find   equ [ebp+16]
   start  equ [ebp+20] ; friendly param names
   limit  equ [ebp+24]
   return equ [ebp+28]

   push esi            ; preserve registers
   push ebx

   mov esi, string   ; copy str descriptor
   mov edx, start    ; copy start pos param
   mov esi,[esi]     ; extract str pointer
   xor eax, eax      ; zero default return

   test esi,esi      ; validate str pointer
   jz _exitp         ; exit null str pointer
   mov ecx,[esi-4]   ; extract str byte length
   mov ebx, limit    ; copy right limit param

   shr ecx, 1        ; convert byte length to chars
   jz _exitp         ; exit if empty string passed

   test ebx, ebx     ; validate optional parameter
   jle _limit        ; opt param less than one (jsz)
   cmp ebx, ecx      ; compare optional limit param
   cmovb ecx,ebx     ; set search right limit pos
  _limit:            ; default search entire string

   dec edx           ; convert start pos to zero base
   cmovs edx,eax     ; default to start at first char
   sub ecx, edx      ; subtract start pos from length
   jle _exitp        ; hit cannot occur > length (jsz)

  _start:
   mov bx, find      ; prep bx for wchar search

  _chr:                 ; walk up str unicode chars
   inc edx              ; offset idx to next wchar
   dec ecx              ; reduce counter by 1 wchar
   js _exitp            ; reached search scope limit
   cmp bx,[esi+edx*2-2] ; compare next char with find
   jne _chr             ; continue search for find char
   mov eax, edx         ; assign result hit position

  _exitp:
   mov ecx, return   ; get address of return value
   mov [ecx],eax     ; store the function result

   pop ebx           ; restore registers
   pop esi
   pop ebp           ; restore base pointer register

   xor eax, eax      ; clear eax to tell VB all is okay
   ret 24            ; cleanup (lpO, p1, p2, p3, p4, rc)

 ; ------------------------------------------------------------------

InChr endp      ; end of procedure
end InChr       ; end of code, indicate entry point

 ; ------------------------------------------------------------------
