Table::wrap() added.
authorJán Kupec <jkupec@suse.cz>
Tue, 31 Mar 2009 20:51:55 +0000 (22:51 +0200)
committerJán Kupec <jkupec@suse.cz>
Tue, 31 Mar 2009 20:51:55 +0000 (22:51 +0200)
This is to enable controlled wrapping of the table to current
screen width.

src/Table.cc
src/Table.h

index 9e54111..f9c3005 100644 (file)
@@ -53,7 +53,8 @@ void TableRow::dumbDumpTo (ostream &stream) const {
   stream << endl;
 }
 
-void TableRow::dumpTo (ostream &stream, const Table & parent) const {
+void TableRow::dumpTo (ostream &stream, const Table & parent) const
+{
   const char * vline = parent._style != none ? lines[parent._style][0] : "";
 
   unsigned int ssize = 0; // string size in columns
@@ -64,13 +65,38 @@ void TableRow::dumpTo (ostream &stream, const Table & parent) const {
 
   stream.setf (ios::left, ios::adjustfield);
   stream << string(parent._margin, ' ');
-  for (unsigned c = 0; i != e ; ++i, ++c) {
-    if (seen_first) {
+  // current position at currently printed line
+  int curpos = parent._margin;
+  // whether to break the line now in order to wrap it to screen width
+  bool do_wrap = false;
+  for (unsigned c = 0; i != e ; ++i, ++c)
+  {
+    if (seen_first)
+    {
+      do_wrap =
+        // user requested wrapping
+        parent._do_wrap &&
+        // table is wider than screen
+        parent._width > parent._screen_width && (
+        // the next table column would exceed the screen size
+        curpos + parent._max_width[c] + (parent._style != none ? 2 : 3) > parent._screen_width ||
+        // or the user wishes to first break after the previous column
+        parent._force_break_after == c - 1);
+
+      if (do_wrap)
+      {
+        // start printing the next table columns to new line,
+        // indent by 2 console columns
+        stream << endl << string(parent._margin + 2, ' ');
+        curpos = parent._margin + 2; // indent == 2
+      }
+      else
+        // vertical line, padded with spaces
+        stream << ' ' << vline << ' ';
       stream.width (0);
-      // pad vertical line with spaces
-      stream << ' ' << vline << ' ';
     }
-    seen_first = true;
+    else
+      seen_first = true;
 
     // stream.width (widths[c]); // that does not work with multibyte chars
     const string & s = *i;
@@ -83,19 +109,22 @@ void TableRow::dumpTo (ostream &stream, const Table & parent) const {
       stream.width (parent._max_width[c] - ssize);
     }
     stream << "";
+    curpos += parent._max_width[c] + (parent._style != none ? 2 : 3);
   }
   stream << endl;
 }
 
 // ----------------------( Table )---------------------------------------------
 
-Table::Table() :
-  _has_header (false),
-  _max_col (0),
-  _width(0),
-  _style (defaultStyle),
-  _screen_width(get_screen_width()),
-  _margin(0)
+Table::Table()
+  : _has_header (false)
+  , _max_col (0)
+  , _width(0)
+  , _style (defaultStyle)
+  , _screen_width(get_screen_width())
+  , _margin(0)
+  , _force_break_after(-1)
+  , _do_wrap(false)
 {}
 
 void Table::add (const TableRow& tr) {
@@ -192,6 +221,13 @@ void Table::dumpTo (ostream &stream) const {
   }
 }
 
+void Table::wrap(int force_break_after)
+{
+  if (force_break_after >= 0)
+    _force_break_after = force_break_after;
+  _do_wrap = true;
+}
+
 void Table::lineStyle (TableLineStyle st) {
   if (st < _End)
     _style = st;
index ac441dd..5ec80a0 100644 (file)
@@ -83,18 +83,21 @@ TableRow& operator << (TableRow& tr, const string& s) {
   return tr;
 }
 
+
 class Table {
 public:
+  typedef list<TableRow> container;
+
   static TableLineStyle defaultStyle;
 
   void add (const TableRow& tr);
   void setHeader (const TableHeader& tr);
   void dumpTo (ostream& stream) const;
   bool empty () const { return _rows.empty(); }
-  typedef list<TableRow> container;
+  void sort (unsigned by_column);       // columns start with 0...
 
   void lineStyle (TableLineStyle st);
-  void sort (unsigned by_column);      // columns start with 0...
+  void wrap(int force_break_after = -1);
   void allowAbbrev(unsigned column);
   void margin(unsigned margin);
 
@@ -122,6 +125,11 @@ private:
   vector<bool> _abbrev_col;
   //! left/right margin in number of spaces
   unsigned _margin;
+  //! if _do_wrap is set, first break the table at this column;
+  //! If negative, wrap as needed.
+  int _force_break_after;
+  //! Whether to wrap the table if it exceeds _screen_width
+  bool _do_wrap;
 
   friend class TableRow;
 };