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)

Reply via email to