<h3>Perl, <strike>269 269 262 256 245</strike> 244 chars</h3>
<pre>
sub p{y/xS/+\//;print;y/+\//xS/}$b=<>/2;$a=$b;$_=' x';s/x/ x--/while($a--);s/$/x\n/;until(/^S/){p;s/ [xS]/S /g;s/-x/S|/;s/-/ /g}s/ (?= *S)/-/g;s/S/x/g;p;s/-/ /g;s/x/|/g;p while(--$b);while(!/\|S/){s/ [xS]/S/;s/\|$/x/;p}s/ /-/g;s/\|/x/g;s/S//;p
</pre>
The basic idea is to do everything with regex substitutions. Because two of the characters used (+ and /) are special characters and turn up a lot in the regexes, it's worthwhile using other characters and substituting them to print.
Slightly more legible version:
<pre>
# Subroutine to substitute, print, and unsubstitute as described above
sub p{y/xS/+\//;print;y/+\//xS/}
# Read from stdin and set up the initial line
$b=<>/2;$a=$b;$_=' x';
s/x/ x--/ while($a--);
s/$/x\n/;
# Print the top face
until(/^S/) {
p;
s/ [xS]/S /g; # First time round: left + -> /; subsequent times move / left
s/-x/S|/; # Only relevant first time round the loop
s/-/ /g; # Only relevant first time round the loop
}
# Prepare and print the line containing second horizontal line
s/ (?= *S)/-/g;
s/S/x/g;
p;
# Now print (n-1)/2 identical lines
s/-/ /g;
s/x/|/g;
p while (--$b);
# Bring the right edge in
while (!/\|S/) {
s/ [xS]/S/;
s/\|$/x/;
p
}
# Prepare and print the final line
s/ /-/g;
s/\|/x/g;
s/S//;
p
</pre>
In a sense I'm cheating by using $b as a counter in the intermediate loop - I could instead append whitespace in the loop over $a and then use regex replaces for that loop too - but I'm going to allow that slight deviation from a pure-regex solution.
No doubt some scary person can turn this into a much shorter sed script.