#autoload

local -a match mbegin mend

# Look for glob qualifiers.  Do this first:  if we're really
# in a glob qualifier, we don't actually want to expand
# the earlier part of the path.  We can't expand inside
# parentheses otherwise, so as we test that successfully
# we should be able to commit to glob qualifiers here.
#
# Extra nastiness to be careful about a quoted parenthesis.
# The initial tests look for parentheses with zero or an
# even number of backslashes in front.  We also require that
# there was at least one character before the parenthesis for
# a bare glob qualifier.
# The later test looks for an outstanding quote.
if _have_glob_qual $PREFIX; then
   compset -p ${#match[1]}
   if [[ -o extendedglob ]] && compset -P '\#'; then
     _globflags
   else
     _globquals
   fi
   return
fi

# Utility function for in-path completion. This allows `/u/l/b<TAB>'
# to complete to `/usr/local/bin'.

local linepath realpath donepath prepath testpath exppath skips skipped
local tmp1 tmp2 tmp3 tmp4 i orig eorig pre suf tpre tsuf opre osuf cpre
local pats haspats ignore pfx pfxsfx sopt gopt opt sdirs ignpar cfopt listsfx
local nm=$compstate[nmatches] menu matcher mopts sort mid accex fake
local listfiles listopts tmpdisp origtmp1 Uopt
integer npathcheck
local -a Mopts

typeset -U prepaths exppaths

exppaths=()

# Get the options.

zparseopts -a mopts \
    'P:=pfx' 'S:=pfxsfx' 'q=pfxsfx' 'r:=pfxsfx' 'R:=pfxsfx' \
    'W:=prepaths' 'F:=ignore' 'M+:=matcher' \
    J+: V+: X+: 1 2 n 'f=tmp1' '/=tmp1' 'g+:-=tmp1'

sopt="-${(@j::M)${(@)tmp1#-}#?}"
(( $tmp1[(I)-[/g]*] )) && haspats=yes
(( $tmp1[(I)-g*] )) && gopt=yes
if (( $tmp1[(I)-/] )); then
  pats="${(@)${(@M)tmp1:#-g*}#-g}"
  pats=( '*(-/)' ${${(z):-x $pats}[2,-1]} )
else
  pats="${(@)${(@M)tmp1:#-g*}#-g}"
  pats=( ${${(z):-x $pats}[2,-1]} )
fi
pats=( "${(@)pats:# #}" )

if (( $#pfx )); then
  compset -P "$pfx[2]" || pfxsfx=( "$pfx[@]" "$pfxsfx[@]" )
fi

if (( $#prepaths )); then
  tmp1="${prepaths[2]}"
  if [[ "$tmp1[1]" = '(' ]]; then
    prepaths=( ${^=tmp1[2,-2]%/}/ )
  elif [[ "$tmp1[1]" = '/' ]]; then
    prepaths=( "${tmp1%/}/" )
  else
    prepaths=( ${(P)^tmp1%/}/ )
    (( ! $#prepaths )) && prepaths=( ${tmp1%/}/ )
  fi
  (( ! $#prepaths )) && prepaths=( '' )
else
  prepaths=( '' )
fi

if (( $#ignore )); then
  if [[ "${ignore[2]}" = \(* ]]; then
    ignore=( ${=ignore[2][2,-2]} )
  else
    ignore=( ${(P)ignore[2]} )
  fi
fi

# If we were given no file selection option, we behave as if we were given
# a `-f'.

if [[ "$sopt" = -(f|) ]]; then
  if [[ -z "$gopt" ]]; then
    sopt='-f'
    pats=('*')
  else
    unset sopt
  fi
fi

if (( ! $mopts[(I)-[JVX]] )); then
  local expl

  if [[ -z "$gopt" && "$sopt" = -/ ]]; then
    _description directories expl directory
  else
    _description files expl file
  fi
  tmp1=$expl[(I)-M*]
  if (( tmp1 )); then
    if (( $#matcher )); then
      matcher[2]="$matcher[2] $expl[1+tmp1]"
    else
      matcher=(-M "$expl[1+tmp1]")
    fi
  fi
  mopts=( "$mopts[@]" "$expl[@]" )
fi

# If given no `-F' option, we may want to use $fignore, turned into patterns.

[[ -z "$_comp_no_ignore" && $#ignore -eq 0 &&
   ( -z $gopt || "$pats" = \ #\*\ # ) && -n $FIGNORE ]] && 
    ignore=( "?*${^fignore[@]}" )

if (( $#ignore )); then
  _comp_ignore=( "$_comp_ignore[@]" "$ignore[@]" )
  (( $mopts[(I)-F] )) || mopts=( "$mopts[@]" -F _comp_ignore )
fi

if [[ $#matcher -eq 0 && -o nocaseglob ]]; then
  # If globbing is case insensitive and there's no matcher,
  # do case-insensitive matching.
  matcher=( -M 'm:{a-zA-Z}={A-Za-z}' )
fi

if (( $#matcher )); then
  # Add the current matcher to the options to compadd.
  mopts=( "$mopts[@]" "$matcher[@]" )
fi

if zstyle -s ":completion:${curcontext}:" file-sort tmp1; then
  case "$tmp1" in
  *size*)             sort=oL;;
  *links*)            sort=ol;;
  *(time|date|modi)*) sort=om;;
  *access*)           sort=oa;;
  *(inode|change)*)   sort=oc;;
  *)                  sort=on;;
  esac
  [[ "$tmp1" = *rev* ]] && sort[1]=O
  [[ "$tmp1" = *follow* ]] && sort="-${sort}-"

  if [[ "$sort" = on ]]; then
    sort=
  else
    mopts=( "${(@)mopts/#-J/-V}" )

    tmp2=()
    for tmp1 in "$pats[@]"; do
      if _have_glob_qual "$tmp1" complete; then
	# unbalanced parenthesis is correct: match[1] contains the start,
	# match[5] doesn't contain the end.
	tmp2+=( "${match[1]}${sort}${match[5]})" )
      else
        tmp2+=( "${tmp1}(${sort})" )
      fi
    done
    pats=( "$tmp2[@]" )
  fi
fi

# Check if we have to skip over sequences of slashes. The value of $skips
# is used below to match the pathname components we always have to accept
# immediately.

if zstyle -t ":completion:${curcontext}:paths" squeeze-slashes; then
  skips='((.|..|)/)##'
else
  skips='((.|..)/)##'
fi

zstyle -s ":completion:${curcontext}:paths" special-dirs sdirs
zstyle -t ":completion:${curcontext}:paths" list-suffixes &&
    listsfx=yes

[[ "$pats" = ((|*[[:blank:]])\*(|[[:blank:]]*|\([^[:blank:]]##\))|*\([^[:blank:]]#/[^[:blank:]]#\)*) ]] &&
    sopt=$sopt/

zstyle -a ":completion:${curcontext}:paths" accept-exact accex
zstyle -a ":completion:${curcontext}:" fake-files fake

zstyle -s ":completion:${curcontext}:" ignore-parents ignpar

if [[ -n "$compstate[pattern_match]" ]]; then
  if { [[ -z "$SUFFIX" ]] && _have_glob_qual "$PREFIX" complete } ||
    _have_glob_qual "$SUFFIX" complete; then
    # Copy all glob qualifiers from the line to
    # the patterns used when generating matches
    tmp3=${match[5]}
    if [[ -n "$SUFFIX" ]]; then
      SUFFIX=${match[2]}
    else
      PREFIX=${match[2]}
    fi
    tmp2=()
    for tmp1 in "$pats[@]"; do
      if _have_glob_qual "$tmp1" complete; then
	# unbalanced parenthesis is correct: match[1] contains the start,
	# match[5] doesn't contain the end.
	tmp2+=( "${match[1]}${tmp3}${match[5]})")
      else
	tmp2+=( "${tmp1}(${tmp3})" )
      fi
    done
    pats=( "$tmp2[@]" )
  fi
fi

# We get the prefix and the suffix from the line and save the whole
# original string. Then we see if we will do menu completion.

pre="$PREFIX"
suf="$SUFFIX"
opre="$PREFIX"
osuf="$SUFFIX"
orig="${PREFIX}${SUFFIX}"
eorig="$orig"

[[ $compstate[insert] = (*menu|[0-9]*) || -n "$_comp_correct" ||
   ( -n "$compstate[pattern_match]" &&
     "${orig#\~}" != (|*[^\\])[][*?#~^\|\<\>]* ) ]] && menu=yes
if [[ -n "$_comp_correct" ]]; then
    cfopt=-
    Uopt=-U
else
    Mopts=(-M "r:|/=* r:|=*")
fi

# Now let's have a closer look at the string to complete.

if [[ "$pre" = [^][*?#^\|\<\>\\]#(\`[^\`]#\`|\$)*/* && "$compstate[quote]" != \' ]]; then

  # If there is a parameter expansion in the word from the line, we try
  # to complete the beast by expanding the prefix and completing anything
  # after the first slash after the parameter expansion.
  # This fails for things like `f/$foo/b/<TAB>' where the first `f' is
  # meant as a partial path.

  linepath="${(M)pre##*\$[^/]##/}"
  eval 'realpath=${(e)~linepath}' 2>/dev/null
  [[ -z "$realpath" || "$realpath" = "$linepath" ]] && return 1
  pre="${pre#${linepath}}"
  i='[^/]'
  i="${#linepath//$i}"
  orig="${orig[1,(in:i:)/][1,-2]}"
  donepath=
  prepaths=( '' )
elif [[ "$pre[1]" = \~ && -z "$compstate[quote]" ]]; then

  # It begins with `~', so remember anything before the first slash to be able
  # to report it to the completion code. Also get an expanded version of it
  # (in `realpath'), so that we can generate the matches. Then remove that
  # prefix from the string to complete, set `donepath' to build the correct
  # paths and make sure that the loop below is run only once with an empty
  # prefix path by setting `prepaths'.

  linepath="${pre[2,-1]%%/*}"
  if [[ -z "$linepath" ]]; then
    realpath="${HOME%/}/"
  elif [[ "$linepath" = ([-+]|)[0-9]## ]]; then
    if [[ "$linepath" != [-+]* ]]; then
      tmp1="$linepath"
    else
      if [[ "$linepath" = -* ]]; then
        tmp1=$(( $#dirstack $linepath ))
      else
        tmp1=$linepath[2,-1]
      fi
      [[ -o pushdminus ]] && tmp1=$(( $#dirstack - $tmp1 ))
    fi
    if (( ! tmp1 )); then
      realpath=$PWD/
    elif [[ tmp1 -le $#dirstack ]]; then
      realpath=$dirstack[tmp1]/
    else
      _message 'not enough directory stack entries'
      return 1
    fi
  elif [[ "$linepath" = [-+] ]]; then
    realpath=${~:-\~$linepath}/
  else
    eval "realpath=~${linepath}/" 2>/dev/null
    if [[ -z "$realpath" ]]; then
      _message "unknown user \`$linepath'"
      return 1
    fi
  fi
  linepath="~${linepath}/"
  [[ "$realpath" = "$linepath" ]] && return 1
  pre="${pre#*/}"
  orig="${orig#*/}"
  donepath=
  prepaths=( '' )
else
  # If the string does not start with a `~' we don't remove a prefix from the
  # string.

  linepath=
  realpath=

  if zstyle -s ":completion:${curcontext}:" preserve-prefix tmp1 &&
     [[ -n "$tmp1" && "$pre" = (#b)(${~tmp1})* ]]; then

    pre="$pre[${#match[1]}+1,-1]"
    orig="$orig[${#match[1]}+1,-1]"
    donepath="$match[1]"
    prepaths=( '' )

  elif [[ "$pre[1]" = / ]]; then
    # If it is a absolute path name, we remove the first slash and put it in
    # `donepath' meaning that we treat it as the path that was already handled.
    # Also, we don't use the paths from `-W'.

    pre="$pre[2,-1]"
    orig="$orig[2,-1]"
    donepath='/'
    prepaths=( '' )
  else
    # The common case, we just use the string as it is, unless it begins with
    # `./' or `../' in which case we don't use the paths from `-W'.
    
    [[ "$pre" = (.|..)/* ]] && prepaths=( '' )
    donepath=
  fi
fi

# Now we generate the matches. First we loop over all prefix paths given
# with the `-W' option.

for prepath in "$prepaths[@]"; do

  # Get local copies of the prefix, suffix, and the prefix path to use
  # in the following loop, which walks through the pathname components
  # in the string from the line.

  skipped=
  cpre=

  if zstyle -t ":completion:${curcontext}:paths" accept-exact-dirs &&
    [[ $pre = (#b)(*)/([^/]#) ]]; then
    # We've been told that we can accept an exact directory
    # prefix immediately.  Try this with the longest path prefix
    # first:  this saves stats in the simple case and may get around
    # automount behaviour if early components don't yet exist.
    tmp1=$match[1]
    tpre=$match[2]
    while true; do
      if [[ -d $donepath$tmp1 ]]; then
	donepath=$donepath$tmp1/
	pre=$tpre
	break
      elif [[ $tmp1 = (#b)(*)/([^/]#) ]]; then
	tmp1=$match[1]
	tpre=$match[2]/$tpre
      else
	break
      fi
    done
  fi

  tpre="$pre"
  tsuf="$suf"
  testpath="$donepath"

  tmp2="${(M)tpre##${~skips}}"
  tpre="${tpre#$tmp2}"

  tmp1=( "$prepath$realpath$donepath$tmp2" )

  # count of attemps for pws non-canonical hack
  (( npathcheck = 0 ))
  while true; do

    origtmp1=("${tmp1[@]}")
    # Get the prefix and suffix for matching.

    if [[ "$tpre" = */* ]]; then
      PREFIX="${tpre%%/*}"
      SUFFIX=
    else
      PREFIX="${tpre}"
      SUFFIX="${tsuf%%/*}"
    fi

    # Force auto-mounting. There might be a better way...
    # Commented out in the hope that `pws non-canonical hack'
    # down below does this for us.  Can be uncommented if it
    # doesn't.

    # : ${^tmp1}/${PREFIX}${SUFFIX}/.(/)

    # Get the matching files by globbing.

    tmp2=( "$tmp1[@]" )

    if [[ "$tpre$tsuf" = */* ]]; then
      compfiles -P$cfopt tmp1 accex "$skipped" "$_matcher $matcher[2]" "$sdirs" fake
    elif [[ "$sopt" = *[/f]* ]]; then
      compfiles -p$cfopt tmp1 accex "$skipped" "$_matcher $matcher[2]" "$sdirs" fake "$pats[@]"
    else
      compfiles -p$cfopt tmp1 accex "$skipped" "$_matcher $matcher[2]" '' fake "$pats[@]"
    fi
    tmp1=( $~tmp1 ) 2> /dev/null

    if [[ -n "$PREFIX$SUFFIX" ]]; then
      # See which of them match what's on the line.

      # pws non-canonical hack which seems to work so far...
      # if we didn't match by globbing, check that there is
      # something to match by explicit name.  This is for
      # `clever' filing systems where names pop into existence
      # when referenced.
      #
      # As suggested by Bart, to make sure the "compfiles" checks
      # still work we repeat the tests above if we successfully
      # find something that might need adding, but we make sure
      # we only do this once for completion of each path segment.
      if (( ! $#tmp1 && npathcheck == 0 )); then
	(( npathcheck = 1 ))
	for tmp3 in "$tmp2[@]"; do
	  if [[ -n $tmp3 && $tmp3 != */ ]]; then
	    tmp3+=/
	  fi
	  if [[ -e "$tmp3${(Q)PREFIX}${(Q)SUFFIX}" ]] then
	    (( npathcheck = 2 ))
	  fi
	done
	if (( npathcheck == 2 )); then
	  # repeat loop with same arguments
	  tmp1=("$origtmp1[@]")
	  continue
	fi
      fi

      if (( ! $#tmp1 )); then
        tmp2=( ${^${tmp2:#/}}/$PREFIX$SUFFIX )
      elif [[ "$tmp1[1]" = */* ]]; then
        if [[ -n "$_comp_correct" ]]; then
          tmp2=( "$tmp1[@]" )
          builtin compadd -D tmp1 "$matcher[@]" - "${(@)tmp1:t}"

          if [[ $#tmp1 -eq 0 ]]; then
            tmp1=( "$tmp2[@]" )
	    compadd -D tmp1 "$matcher[@]" - "${(@)tmp2:t}"
          fi
        else
          tmp2=( "$tmp1[@]" )
          compadd -D tmp1 "$matcher[@]" - "${(@)tmp1:t}"
        fi
      else
        tmp2=( '' )
        compadd -D tmp1 "$matcher[@]" -a tmp1
      fi

      # If no file matches, save the expanded path and continue with
      # the outer loop.

      if (( ! $#tmp1 )); then
 	if [[ "$tmp2[1]" = */* ]]; then
	  tmp2=( "${(@)tmp2#${prepath}${realpath}}" )
	  if [[ "$tmp2[1]" = */* ]]; then
	    tmp2=( "${(@)tmp2:h}" )
	    compquote tmp2
	    if [[ "$tmp2" = */ ]]; then
	      exppaths=( "$exppaths[@]" ${^tmp2}${tpre}${tsuf} )
	    else
	      exppaths=( "$exppaths[@]" ${^tmp2}/${tpre}${tsuf} )
	    fi
          elif [[ ${tpre}${tsuf} = */* ]]; then
	    exppaths=( "$exppaths[@]" ${tpre}${tsuf} )

	    ### this once was in an `else' (not `elif')
	  fi
        fi
        continue 2
      fi
    elif (( ! $#tmp1 )); then
      # A little extra hack: if we were completing `foo/<TAB>' and `foo'
      # contains no files, this will normally produce no matches and other
      # completers might think that's it's their time now. But if the next
      # completer is _correct or something like that, this will result in
      # an attempt to correct a valid directory name. So we just add the
      # original string in such a case so that the command line doesn't 
      # change but other completers still think there are matches.
      # We do this only if we weren't given a `-g' or `-/' option because
      # otherwise this would keep `_files' from completing all filenames
      # if none of the patterns match.

      if [[ -z "$tpre$tsuf" && -n "$pre$suf" ]]; then
	pfxsfx=(-S '' "$pfxsfx[@]")
	### Don't remember what the break was good for. We explicitly
	### execute this only when there are no matches in the directory,
	### so why continue?
	###
        ### tmp1=( "$tmp2[@]" )
	### break
      elif [[ -n "$haspats" && -z "$tpre$tsuf$suf" && "$pre" = */ ]]; then
	PREFIX="${opre}"
	SUFFIX="${osuf}"
        compadd -nQS '' - "$linepath$donepath$orig"
        tmp4=-
      fi
      continue 2
    fi

    if [[ -n "$ignpar" && -z "$_comp_no_ignore" &&
          "$tpre$tsuf" != */* && $#tmp1 -ne 0 &&
          ( "$ignpar" != *dir* || "$pats" = '*(-/)' ) &&
          ( "$ignpar" != *..* || "$tmp1[1]" = *../* ) ]]; then

      compfiles -i tmp1 _comp_ignore "$ignpar" "$prepath$realpath$donepath"

      (( $#_comp_ignore && $mopts[(I)-F] )) ||
          mopts=( "$mopts[@]" -F _comp_ignore )
    fi

    # Step over to the next component, if any.

    if [[ "$tpre" = */* ]]; then
      tpre="${tpre#*/}"
    elif [[ "$tsuf" = */* ]]; then
      tpre="${tsuf#*/}"
      tsuf=
    else
      break
    fi

    # There are more components, so skip over the next components and make a
    # slash be added.

    tmp1=( ${tmp1//(#b)([][()|*?^#~<>\\=])/\\${match[1]}} )
    tmp2="${(M)tpre##((.|..|)/)##}"
    if [[ -n "$tmp2" ]]; then
      skipped="/$tmp2"
      tpre="${tpre#$tmp2}"
    else
      skipped=/
    fi
    (( npathcheck = 0 ))
  done

  # The next loop searches the first ambiguous component.

  tmp3="$pre$suf"
  tpre="$pre"
  tsuf="$suf"
  [[ -n "${prepath}${realpath}${testpath}" ]] &&
      tmp1=( "${(@)tmp1#${prepath}${realpath}${testpath}}" )

  while true; do

    # First we check if some of the files match the original string
    # for this component. If there are some we remove all other
    # names. This avoids having `foo' complete to `foo' and `foobar'.
    # The return value is non-zero if the component is ambiguous.

    compfiles -r tmp1 "${(Q)tmp3}"
    tmp4=$?

    if [[ "$tpre" = */* ]]; then
      tmp2="${cpre}${tpre%%/*}"
      PREFIX="${linepath}${donepath}${tmp2}"
      SUFFIX="/${tpre#*/}${tsuf#*/}"
    else
      tmp2="${cpre}${tpre}"
      PREFIX="${linepath}${donepath}${tmp2}"
      SUFFIX="${tsuf}"
    fi

    # This once tested `|| [[ -n "$compstate[pattern_match]" &&
    # "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]' but it should now be smart
    # enough to handle multiple components with patterns.

    if (( tmp4 )); then
      # It is. For menu completion we now add the possible completions
      # for this component with the unambiguous prefix we have built
      # and the rest of the string from the line as the suffix.
      # For normal completion we add the rests of the filenames
      # collected as the suffixes to make the completion code expand
      # it as far as possible.

      tmp2="$testpath"
      if [[ -n "$linepath" ]]; then
        compquote -p tmp2 tmp1
      elif [[ -n "$tmp2" ]]; then
        compquote -p tmp1
        compquote tmp2
      else
        compquote tmp1 tmp2
      fi

      if [[ -z "$_comp_correct" &&
            "$compstate[pattern_match]" = \*  && -n "$listsfx" &&
            "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then
        PREFIX="$opre"
        SUFFIX="$osuf"
      fi

      # This once tested `-n $menu ||' but our menu-completion expert says
      # that's not what we want.

      if [[ -z "$compstate[insert]" ]] ||
         { ! zstyle -t ":completion:${curcontext}:paths" expand suffix &&
           [[ -z "$listsfx" &&
              ( -n "$_comp_correct" ||
                -z "$compstate[pattern_match]" || "$SUFFIX" != */* ||
                "${SUFFIX#*/}" = (|*[^\\])[][*?#~^\|\<\>]* ) ]] }; then
	# We have not been told to insert the match, so we are
	# listing, or something.
        (( tmp4 )) && zstyle -t ":completion:${curcontext}:paths" ambiguous &&
            compstate[to_end]=
        if [[ "$tmp3" = */* ]]; then
	  if [[ -z "$listsfx" || "$tmp3" != */?* ]]; then
	    # I think this means we are expanding some directory
	    # back up the path.
	    tmp1=("${(@)tmp1%%/*}")
	    _list_files tmp1 "$prepath$realpath$testpath"
	    compadd $Uopt -Qf "$mopts[@]" \
                    -p "${Uopt:+$IPREFIX}$linepath$tmp2" \
	            -s "/${tmp3#*/}${Uopt:+$ISUFFIX}" \
	            -W "$prepath$realpath$testpath" \
		    "$pfxsfx[@]" $Mopts \
		    $listopts \
	            -a tmp1
          else
	    # Same with a non-empty suffix
	    tmp1=("${(@)^tmp1%%/*}/${tmp3#*/}")
	    _list_files tmp1 "$prepath$realpath$testpath"
	    compadd $Uopt -Qf "$mopts[@]" \
                    -p "${Uopt:+$IPREFIX}$linepath$tmp2" \
	            -s "${Uopt:+$ISUFFIX}" \
	            -W "$prepath$realpath$testpath" \
		    "$pfxsfx[@]" $Mopts \
	            $listopts \
		    -a tmp1
          fi
	else
	  _list_files tmp1 "$prepath$realpath$testpath"
	  compadd $Uopt -Qf "$mopts[@]" -p "${Uopt:+$IPREFIX}$linepath$tmp2" \
	          -s "${Uopt:+$ISUFFIX}" \
	          -W "$prepath$realpath$testpath" \
		   "$pfxsfx[@]" $Mopts \
	           $listopts \
		   -a tmp1
	fi
      else
	# We are inserting the match into the command line.
        if [[ "$tmp3" = */* ]]; then
	  tmp4=( $Uopt -Qf "$mopts[@]" -p "${Uopt:+$IPREFIX}$linepath$tmp2"
	         -W "$prepath$realpath$testpath"
	         "$pfxsfx[@]" $Mopts )
	  if [[ -z "$listsfx" ]]; then
            for i in "$tmp1[@]"; do
	      tmpdisp=("$i")
	      _list_files tmpdisp "$prepath$realpath$testpath"
	      compadd "$tmp4[@]" -s "${Uopt:+$ISUFFIX}" $listopts - "$tmpdisp"
	    done
          else
            [[ -n "$compstate[pattern_match]" ]] && SUFFIX="${SUFFIX:s./.*/}*"

            for i in "$tmp1[@]"; do
	      _list_files i "$prepath$realpath$testpath"
	      compadd "$tmp4[@]" $listopts - "$i"
	    done
          fi
        else
	  _list_files tmp1 "$prepath$realpath$testpath"
	  compadd $Uopt -Qf "$mopts[@]" -p "${Uopt:+$IPREFIX}$linepath$tmp2" \
	          -s "${Uopt:+$ISUFFIX}" \
                  -W "$prepath$realpath$testpath" \
		  "$pfxsfx[@]" $Mopts \
                  $listopts \
		  -a tmp1
        fi
      fi
      tmp4=-
      break
    fi

    # If we have checked all components, we stop now and add the 
    # strings collected after the loop.

    if [[ "$tmp3" != */* ]]; then
      tmp4=
      break
    fi

    # Otherwise we add the unambiguous component to `testpath' and
    # take it from the filenames.

    testpath="${testpath}${tmp1[1]%%/*}/"

    tmp3="${tmp3#*/}"

    if [[ "$tpre" = */* ]]; then
      if [[ -z "$_comp_correct" && -n "$compstate[pattern_match]" &&
            "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then
        cpre="${cpre}${tmp1[1]%%/*}/"
      else
        cpre="${cpre}${tpre%%/*}/"
      fi
      tpre="${tpre#*/}"
    elif [[ "$tsuf" = */* ]]; then
      [[ "$tsuf" != /* ]] && mid="$testpath"
      if [[ -z "$_comp_correct" && -n "$compstate[pattern_match]" &&
            "$tmp2" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then
        cpre="${cpre}${tmp1[1]%%/*}/"
      else
        cpre="${cpre}${tpre}/"
      fi
      tpre="${tsuf#*/}"
      tsuf=
    else
      tpre=
      tsuf=
    fi

    tmp1=( "${(@)tmp1#*/}" )
  done

  if [[ -z "$tmp4" ]]; then
    if [[ "$mid" = */ ]]; then
      PREFIX="${opre}"
      SUFFIX="${osuf}"

      tmp4="${testpath#${mid}}"
      tmp3="${mid%/*/}"
      tmp2="${${mid%/}##*/}"
      if [[ -n "$linepath" ]]; then
        compquote -p tmp3
      else
        compquote tmp3
      fi
      compquote tmp4 tmp2 tmp1
      for i in "$tmp1[@]"; do
	_list_files tmp2 "$prepath$realpath${mid%/*/}"
        compadd $Uopt -Qf "$mopts[@]" -p "${Uopt:+$IPREFIX}$linepath$tmp3/" \
	        -s "/$tmp4$i${Uopt:+$ISUFFIX}" \
                -W "$prepath$realpath${mid%/*/}/" \
	        "$pfxsfx[@]" $Mopts $listopts - "$tmp2"
      done
    else
      if [[ "$osuf" = */* ]]; then
        PREFIX="${opre}${osuf}"
        SUFFIX=
      else
        PREFIX="${opre}"
        SUFFIX="${osuf}"
      fi
      tmp4="$testpath"
      if [[ -n "$linepath" ]]; then
        compquote -p tmp4 tmp1
      elif [[ -n "$tmp4" ]]; then
        compquote -p tmp1
        compquote tmp4
      else
        compquote tmp4 tmp1
      fi
      if [[ -z "$_comp_correct" && -n "$compstate[pattern_match]" &&
            "${PREFIX#\~}$SUFFIX" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then
	tmp1=("$linepath$tmp4${(@)^tmp1}")
	_list_files tmp1 "$prepath$realpath"
        compadd -Qf -W "$prepath$realpath" "$pfxsfx[@]" "$mopts[@]" \
                -M "r:|/=* r:|=*" $listopts -a tmp1
      else
	# Not a pattern match
	_list_files tmp1 "$prepath$realpath$testpath"
        compadd $Uopt -Qf -p "${Uopt:+$IPREFIX}$linepath$tmp4" \
	        -s "${Uopt:+$ISUFFIX}" \
	        -W "$prepath$realpath$testpath" \
	        "$pfxsfx[@]" "$mopts[@]" $Mopts $listopts -a tmp1
      fi
    fi
  fi
done

# If we are configured to expand paths as far as possible and we collected
# expanded paths that are different from the string on the line, we add
# them as possible matches. Do that only if we are currently trying the
# last entry in the matcher-list style, otherwise other match specs might
# make the suffix that didn't match this time match in one of the following
# attempts.

if [[ _matcher_num -eq ${#_matchers} ]] &&
   zstyle -t ":completion:${curcontext}:paths" expand prefix &&
   [[ nm -eq compstate[nmatches] && $#exppaths -ne 0 &&
      "$linepath$exppaths" != "$eorig" ]]; then
  PREFIX="${opre}"
  SUFFIX="${osuf}"
  compadd -Q "$mopts[@]" -S '' -M "r:|/=* r:|=*" -p "$linepath" -a exppaths
fi

[[ nm -ne compstate[nmatches] ]]
