Here's something I wrote a while back in a not-too-dissimilar context. In your case it won't be perfect, because the bits that prevent BBCode tags from being mangled themselves have nonzero length.
That's one idea to be going on with.
'Nother idea. Assuming this isn't going to be in <pre> blocks where the content doesn't wrap normally anyway, after protecting bits that need protecting, just search for excessively long strings and slip breaks into them every 50 characters or so.
$wrapped_text = preg_replace('/(\S{50,})/e', "chunk_split('$1',50,'<br>')", $text);
is a first guess at the code.