We're Spiralling out of control, Doctor!
JavaScript (ES6) 124 163 177

Edit Totally different way, no need of an array to store visited cells. Using the fact that the side of the spiral increase of 1 after every 2 turns.



// New way
f=(h,w,y,x)=&gt;
  (e=&gt;{
    for(o=[],d=i=t=l=0;l&lt;w*h;i&lt;t?i+=2:[i,d,e]=[1,-e,d,++t])
      o[l]=y*w-w+x,l+=x&gt;0&amp;x&lt;=w&amp;y&gt;0&amp;y&lt;=h,x+=d,y-=e
  })(1)||o


// Golfed
g=(h,w,y,x)=&gt;
  (g=&gt;{
    for(e=n=0;n&lt;h*w;)g[[n%w+1,-~(n/w)]]=++n;
    for(o=[g[[x,y]]],l=d=1;l&lt;n;l+=!!(o[l]=g[[x+=d,y+=e]]))
      g[[x,y]]=0,
      g[[x+e,y-d]]!=0&amp;&amp;([d,e]=[e,-d])
  })([])||o



// Not golfed
u=(h,w,y,x)=&gt;{
  var i,j,dx,dy,kx,ky,o,n,
    g={} // simulate a 2dimensional array using a hashtable with keys in the form 'x,y'

  for(n=i=0; i++&lt;h;) // fill grid (probably better done in a single loop)
    for(j=0; j++&lt;w;)
      g[[j,i]] = ++n;
  o=[g[[x,y]]] // starting point in output
  dx=1, dy=0 // start headed right
  
  for(; !o[w*h-1]; ) // loop until all w*h position are put in output
  {
    g[[x, y]] = 0 // mark current position to avoid reusing
    kx=dy, ky=-dx // try turning left
    if(g[[x+kx, y+ky]] != 0) // check if position marked
    { // found a valid position
      dx=kx, dy=ky // change direction
    }
    x+=dx, y+=dy // move
    k=g[[x, y]] // get current value
    if (k) o.push(k) // put in output list if not 'undefined' (outside grid)
  }
  return o
}

// TEST - In FireFox

out=x=&gt;O.innerHTML+=x+'\n';
[
 [[5,5,3,3],'13 8 7 12 17 18 19 14 9 4 3 2 1 6 11 16 21 22 23 24 25 20 15 10 5'],
 [[2,4,1,2],'2 1 5 6 7 3 8 4']
].forEach(t=&gt;out(t[0] + '\n Result: ' + f(...t[0])+'\n Check:  ' + t[1]))

test=()=&gt;
{
  var r, i=I.value.match(/\d+/g), h=i[0]|0, w=i[1]|0, y=i[2]|0, x=i[3]|0
  if (y&gt;h||x&gt;w) r = 'Invalid input'
  else r = f(h,w,y,x)
  out(i+'\n Reault: ' +r)
}
&lt;pre id=O&gt;&lt;/pre&gt;
Your test:&lt;input id=I&gt;&lt;button onclick="test()"&gt;-&gt;&lt;/button&gt;