A regexp finds the begin/end markers + contents between them and stores them in a dictionary. The NEXT line below the end marker isn't contained in these regions.
When the TEMPLATE contains a begin/end statement for a user code region, the handler checks if there's a matched region in the dictionary. IF so, it emits THAT (which contains begin/end markers) into the output. If NOT, it will simply skip the start statement and emit what's next.
The empty line you see initially is the line with the <[EndUserCodeRegion]> statement on it. The tabs you see are the tabs in front of the statement.
When there IS a region in the existing file (so you generate over an existing file) that statement is skipped, as it isn't necessary to process it, a snippet has been found so the interpreter skips its nonterminal pointer till the next non-terminal after the <[EndUserCodeRegion]> non-terminal. This thus makes it skip the tabs in front of <[EndUserCodeRegion]>.
It's not that easy to fix this, as those tabs belong to the 'text' block seen AFTER the <[UserCodeRegionStart]> statement. This block simply contains the 2 lines with the markers and the tabs in front of the <[EndUserCodeRegion]> statement, that's 1 single token (as it is left untouched, and thus it is seen as literal text to output).
Emitting two tabs is also not an option, because it sometimes should be 3, 1 or other number.
So what could fix it, is to place the <[EndUserCodeRegion]> statements directly behind the end marker and not on the next line. Another could be to append the regexp in the interpreter with a whitespace group which matches the whitespace after the endmarker. ( \s+ )
I'll try the whitespace regexp group. The move of the endstatement in all the templates is too much work for now.
(edit) \s+ matches too much, it grows the file... trying another.
(edit) \r\n[ \t]* solves a lot except the ones which have a dangling tab or whitespace after the endusercoderegion statement. That whitespace is ending up in the initial file, then it matches the regexp, but it is emitted again AFTER the matched user code region as it belongs to the literal text FOLLOWING the <[EndUserCodeRegion]> statement.
i.o.w. the only real fix is to move the <[EndUserCodeRegion]> to right after the end marker, which is a lot of work and I won't do that now. I will file a bugreport for this though so it will be fixed in v3, which will have a different template system.