Thanks merlyn, that's just the kind of thing I was aiming for (though I don't need more than one page).
Just for the benefit of other monks, merlyn's column includes this:
sub DEFAULT_FIELD { textfield(shift, "", 60) }
as the way fields are produced unless specifically over-ridden, and the tables are produced like this:
print table({ Border => 1, Cellpadding => 5 },
map { Tr(
th($_->[1]),
td(($_->[2] || \&DEFAULT_FIELD)->($_->[0]))
)} @info
);
where the details of the form are in the @info array.
Update: you know what's occurring to me? The details of the form (arrays of arrays for the most part) could easily be stored in XML -- I'm sure if the column were written today that might have come up.
--
Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.
M-J D