Werner LEMBERG <[EMAIL PROTECTED]>:
> > I'm going to magically suppose that we have added to this preamble
> > the setting of a numeric register named '3bc' that counts the number
> > of columns containing block entries -- in this case, 1. I don't
> > know how to do that, yet, but bear with me.
>
> I think this has to be done within tbl (on the C++ side, not on the
> macro side).
I came to the same conclusion, and coded it that way last night.
> > Am I hallucinating? This looks really simple.
>
> I think it is.
I still think it is, too, but my attempt to implement it doesn't quite
work -- the actual widths it's emitting are way too small. Patch enclosed
for your review. I'm pretty sure that my C++ logic is right, and that I've
screwed up by misunderstanding how troff works and generating the wrong
macro computation. It could well be some kind of silly units error.
--
<a href="http://www.catb.org/~esr/">Eric S. Raymond</a>
Index: table.cpp
===================================================================
RCS file: /sources/groff/groff/src/preproc/tbl/table.cpp,v
retrieving revision 1.7
diff -u -r1.7 table.cpp
--- table.cpp 26 May 2005 21:02:01 -0000 1.7
+++ table.cpp 8 Feb 2007 22:39:22 -0000
@@ -63,6 +63,9 @@
// this must be one character
#define COMPATIBLE_REG PREFIX "c"
+#define AVAILABLE_REG PREFIX "avail"
+#define COLCOUNT_REG PREFIX "ccount"
+
#define LEADER_REG PREFIX LEADER
#define BLOCK_WIDTH_PREFIX PREFIX "tbw"
@@ -154,7 +157,7 @@
table_entry(const entry_modifier *);
virtual ~table_entry();
virtual int divert(int ncols, const string *mw, int *sep);
- virtual void do_width();
+ virtual void do_width(table *);
virtual void do_depth();
virtual void print() = 0;
virtual void position_vertically() = 0;
@@ -207,7 +210,7 @@
class simple_text_entry : public text_entry {
public:
simple_text_entry(char *s, const entry_modifier *m);
- void do_width();
+ void do_width(table *);
};
class left_text_entry : public simple_text_entry {
@@ -235,14 +238,14 @@
int dot_pos;
public:
numeric_text_entry(char *s, const entry_modifier *m, int pos);
- void do_width();
+ void do_width(table *);
void simple_print(int);
};
class alphabetic_text_entry : public text_entry {
public:
alphabetic_text_entry(char *s, const entry_modifier *m);
- void do_width();
+ void do_width(table *);
void simple_print(int);
void add_tab();
};
@@ -296,7 +299,7 @@
block_entry(char *s, const entry_modifier *m);
~block_entry();
int divert(int ncols, const string *mw, int *sep);
- void do_width();
+ void do_width(table *);
void do_depth();
void position_vertically();
void print() = 0;
@@ -342,7 +345,7 @@
return 0;
}
-void table_entry::do_width()
+void table_entry::do_width(table *tp)
{
}
@@ -477,7 +480,7 @@
{
}
-void simple_text_entry::do_width()
+void simple_text_entry::do_width(table *tp)
{
set_location();
printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR,
@@ -545,7 +548,7 @@
{
}
-void numeric_text_entry::do_width()
+void numeric_text_entry::do_width(table *tp)
{
if (dot_pos != 0) {
set_location();
@@ -589,7 +592,7 @@
{
}
-void alphabetic_text_entry::do_width()
+void alphabetic_text_entry::do_width(table *tp)
{
set_location();
printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR,
@@ -681,10 +684,16 @@
printfs(">?\\n[%1]u", span_width_reg(start_col, end_col));
}
else
- printfs("(u;\\n[%1]>?(\\n[.l]*%2/%3))",
+ // This was the old heuristic -- assign each column with a block entry
+ // 1/(n+1) ofv the line width, where n is the column count.
+ //printfs("(u;\\n[%1]>?(\\n[.l]*%2/%3))",
+ // span_width_reg(start_col, end_col),
+ // as_string(end_col - start_col + 1),
+ // as_string(ncols + 1));
+ printfs("(u;\\n[%1]+(%2/%3))",
span_width_reg(start_col, end_col),
- as_string(end_col - start_col + 1),
- as_string(ncols + 1));
+ AVAILABLE_REG,
+ COLCOUNT_REG);
if (alphabetic)
prints("-2n");
prints("\n");
@@ -712,9 +721,11 @@
location_force_filename = 1;
}
-void block_entry::do_width()
+void block_entry::do_width(table *tp)
{
// do nothing; the action happens in divert
+ for (int i=start_col; i <= end_col; i++)
+ tp->blockflag[i] = (char)1;
}
void block_entry::do_depth()
@@ -1201,7 +1212,7 @@
vrule_list(0), stuff_list(0), span_list(0),
entry_list(0), entry_list_tailp(&entry_list), entry(0),
vline(0), row_is_all_lines(0), left_separation(0), right_separation(0),
- allocated_rows(0)
+ allocated_rows(0), blockflag(0)
{
minimum_width = new string[ncolumns];
column_separation = ncolumns > 1 ? new int[ncolumns - 1] : 0;
@@ -1306,6 +1317,7 @@
allocated_rows = r + 1;
entry = new PPtable_entry[allocated_rows];
vline = new char*[allocated_rows];
+ blockflag = new char[allocated_rows];
}
else {
table_entry ***old_entry = entry;
@@ -1320,6 +1332,10 @@
vline = new char*[allocated_rows];
memcpy(vline, old_vline, sizeof(char*)*old_allocated_rows);
a_delete old_vline;
+ char *old_blockflag = blockflag;
+ blockflag = new char[allocated_rows];
+ memcpy(blockflag, old_blockflag, sizeof(char)*old_allocated_rows);
+ a_delete old_blockflag;
}
}
assert(allocated_rows > r);
@@ -1686,6 +1702,15 @@
}
}
+int table::count_block_columns()
+{
+ int count = 0;
+ for (int i = 0; i < ncolumns; i++)
+ if (blockflag[i])
+ count++;
+ return count;
+}
+
void table::init_output()
{
prints(".nr " COMPATIBLE_REG " \\n(.C\n"
@@ -1912,6 +1937,8 @@
span_left_numeric_width_reg(start_col, end_col),
span_right_numeric_width_reg(start_col, end_col),
span_alphabetic_width_reg(start_col, end_col));
+ printfs(".nr %1 -%2\n",
+ AVAILABLE_REG, span_width_reg(start_col, end_col));
}
// Increase the widths of columns so that the width of any spanning entry
@@ -2105,7 +2132,9 @@
table_entry *q;
for (q = entry_list; q; q = q->next)
if (!q->mod->zero_width)
- q->do_width();
+ q->do_width(this);
+ printfs(".nr %1 %2\n", COLCOUNT_REG, as_string(count_block_columns()));
+ printfs(".nr %1 \\n[.ll]\n", AVAILABLE_REG);
for (i = 0; i < ncolumns; i++)
compute_span_width(i, i);
for (p = span_list; p; p = p->next)