in reply to Collecting data in a recursive routine.

I'm not overly familiar with PostgresSQL but wouldn't you do the sorting inside your SQL query? like this:
$all_cats = $dbh->selectall_arrayref("SELECT category_id,name FROM $sq +l{catego +ries} WHERE parent=$parent_cat_id ORDER BY category_id");

That's a minor point however ;-).

Now, onto HTML::Template and how you could possibly produce a 'variable' (array actually) that could later be fed to HTML::Template and used reasonably therein.

I know that HTML::Template allows for nested TMPL_LOOP statements, however, I hardly see them being useful in your case. Instead, you might try doing the following. Create an array structure like this:
@categories = ( { id => <i>insert category_id value here</i>, name => <i>insert name value here</i> level => <i>level (inside a category etc.) </i> }, { ... }, ... );
Notice introduction of the 'level' field? You may use this one in your HTML template to determine how much 'indentation' is required. To set 'level' value properly, you might modify your code to increment a $level variable instead of adding string filled with a bunch of 'spaces' to the $indent variable as it's no longer going to be needed. Basically, try to introduce $level variable in place of your $indent and also change this line:
$indent .= "&nbsp; ...";
to
$level++;
and later in your foreach loop, just push this hash onto your @categories array (this array may be global to start with.. however, it does feel yucky and you might have to change it later :)
foreach my $current_cat (sort { $a->[1] cmp $b->[1] } @{$all_c +ats}) { ($cat{id}, $cat{name}) = @$current_cat; push @main::categories {level=>$level,name=>$cat{name},i +d=>$cat{id}}; &ListCategories($indent, $cat{id}, 'y'); }
This way your Template code is left to decide which way to format the output based on the 'level' value ;-).

See if it works for you and let me know. (I didn't test the code, though).

"There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith