Befunge, 260 250 bytes
"'"::00p09p19p35*::10p29pv
v`*84:~<0p041p031p020p93<
v_0`!#v_^*!p04+g04:p03%4+g03:p02%4+g02:!%g04:+1pp01+%2-1g03p\3+<
>00g:: :09g\`8+0\p::19g`8+1\p20g1-2%+00p10g:::29g\`8+2\p::39g`8^
9g\-\v>29g:39g\->\:50p09g:1
$$1+\:!#@_1-55+,^>
,gg05<:+1\-1_:$#\^#
Experimente online!
A idéia básica é que construamos a espiral na metade inferior do campo de jogo, mantendo o controle das coordenadas mín e máx à medida que avançamos. Depois que todas as entradas foram processadas, iteramos no intervalo de coordenadas e escrevemos o conteúdo que foi salvo.
Explicação detalhada
Observe que os valores dx e dy estão no intervalo de 0 a 3, correspondendo aos deslocamentos relativos -1, 0, 1, 0. A atualização da direção é feita com a adição de 1, módulo 4. A conversão para um deslocamento relativo é feita por subtraindo 1, módulo 2.
"'"::00p09p19p Set x, minx, and maxx to 39.
35*::10p29p39p Set y, miny, and maxy to 15.
020p130p Set dx to 0 (relative offset -1) and dy to 1 (relative offset 0).
140p Set the segment length to 1.
0 Set the index to 0 (on the stack).
-- The main input loop start here --
~ Read a character from stdin.
:48*`_ If it's greater than 32 (i.e. not whitespace or EOL)...
00g: Get the current value of x and make a duplicate.
::09g\`8+0\p If it's less than minx, update minx.
::19g`8+1\p If it's greater than maxx, update maxx.
20g1-2% Calculate (dx-1)%2, which converts dx into the range -1 to 1.
+00p Add that to x and save (leaving the original x on the stack).
10g: Get the currrent value of y and make a duplicate.
::29g\`8+2\p If it's less than miny, update miny.
::39g`8+3\p If it's greater than maxy, update maxy.
30g1-2% Calculate (dy-1)%2, which converts dy into the range -1 to 1.
+10p Add that to y and save (leaving the original y on the stack).
p Store the character we read at the original x,y coordinates.
1+ Increment the index by 1.
:40g%! Mod that with the current segment len; if zero it's time to turn.
:20g+4%20p Add the turn condition to the dx value, thus turning if needed.
:30g+4%30p Similarly add the turn condition to the dy value.
:40g+40p Also add it to the segment length, so it gets longer every turn.
!* Multiply the index by !turn, so it's reset to zero on every turn.
^ Repeat the loop, reading another character.
0`!#v_^ If the char <= 32, we test for EOF and repeat the loop if not.
> If it is EOF, we start the output routine.
29g Initialise the y coordinate with miny.
:39g\- Calculate maxy - miny to use as the height countdown.
-- The outer output loop starts here --
\:50p Swap y to the top and save in a temporary variable.
09g Initialise the x coordinate with minx.
:19g\- Calculate maxx - miny to use as our width countdown.
\ Swap x to the top of the stack.
-- The inner output loop starts here --
:50g Take a copy of x and the y save in the temporary variable.
g, Read the character at those coordinate and write to stdout.
\:_ Swap the width countdown to the top of the stack and break if zero.
1- Otherwise decrement the width countdown.
\1+ Swap the x value back to the top and increment it.
< Repeat the inner loop.
$$ Clear the width countdown and x value from the stack.
1+ Increment the y value.
\ Swap the height countdown to the top of the stack.
:¬#@_ If it's zero, exit.
1- Otherwise decrement it.
55+, Output a line break.
^ Repeat the outer loop.