[Aptitude-svn-commit] r3431 - in branches/aptitude-0.3/aptitude: . src/vscreen src/vscreen/config

Daniel Burrows dburrows@costa.debian.org
Sat, 25 Jun 2005 19:36:16 +0000


Author: dburrows
Date: Sat Jun 25 19:36:13 2005
New Revision: 3431

Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/vscreen/columnify.cc
   branches/aptitude-0.3/aptitude/src/vscreen/columnify.h
   branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.cc
   branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.h
Log:
Rewrite the columnification code for the wide character era.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Sat Jun 25 19:36:13 2005
@@ -1,5 +1,12 @@
 2005-06-25  Daniel Burrows  <dburrows@debian.org>
 
+	* src/vscreen/columnify.cc, src/vscren/columnify.h, src/vscreen/config/column_definition.cc, src/vscreen/config/column_definition.h:
+
+	  Rewrite the columnification code to handle wide characters
+	  properly: you can include literal wide characters in the
+	  configuration, and multi-column wide characters are accounted
+	  for in calculating widths.
+
 	* src/vscreen/transcode.cc:
 
 	  Get rid of the use of auto_ptr and new[], they aren't really

Modified: branches/aptitude-0.3/aptitude/src/vscreen/columnify.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/columnify.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/columnify.cc	Sat Jun 25 19:36:13 2005
@@ -1,6 +1,6 @@
 // columnify.cc
 //
-//  Copyright 2000 Daniel Burrows
+//  Copyright 2000, 2005 Daniel Burrows
 //  
 //  This program is free software; you can redistribute it and/or modify
 //  it under the terms of the GNU General Public License as published by
@@ -21,9 +21,9 @@
 
 using namespace std;
 
-string columnify(const layout &format, unsigned int width)
+wstring columnify(const layout &format, int width)
 {
-  string rval;
+  wstring rval;
 
   layout final_info;
 
@@ -38,7 +38,7 @@
     }
 
   // Reconcile the widths.
-  unsigned int totalwidth=0;
+  int totalwidth=0;
   for(layout::iterator i=final_info.begin();
       i!=final_info.end(); ++i)
     totalwidth+=i->width;
@@ -91,7 +91,7 @@
     // Do everything again if we were allocated less space than requested. :(
     {
       int nshrinkable=0;
-      unsigned int shortfall=totalwidth-width;
+      int shortfall=totalwidth-width;
       int startloc=0;
 
       for(layout::iterator i=final_info.begin();
@@ -105,7 +105,7 @@
 	{
 	  if(i->shrink)
 	    {
-	      unsigned int amt=shortfall/nshrinkable;
+	      int amt=shortfall/nshrinkable;
 	      if(amt>i->width)
 		amt=i->width;
 
@@ -132,21 +132,39 @@
 	    }
     }
 
+  int curwidth=0;
+  const int spacewidth=wcwidth(L' ');
   for(layout::iterator i=final_info.begin();
       i!=final_info.end(); ++i)
     {
-      string::size_type amt=0;
-      for( ; amt<i->width && amt<i->info.text.size(); amt++)
-	rval+=i->info.text[amt];
-      while(amt<i->width)
+      wstring::size_type amt=0;
+      for( ; curwidth<(i->width) &&
+	     amt<i->info.text.size(); ++amt)
 	{
-	  rval+=' ';
-	  amt++;
+	  wchar_t wch=i->info.text[amt];
+	  // Watch out for wide characters overrunning the column
+	  // boundary!
+	  if(curwidth+wcwidth(wch)<=i->width)
+	    {
+	      rval+=wch;
+	      curwidth+=wcwidth(wch);
+	    }
+	  else
+	    break;
+	}
+      // Is it sane for spacewidth to ever differ from unity?
+      while(curwidth+spacewidth<i->width)
+	{
+	  rval+=L' ';
+	  curwidth+=spacewidth;
 	}
     }
 
-  while(rval.size()<width)
-    rval+=' ';
+  while(curwidth<width)
+    {
+      rval+=L' ';
+      curwidth+=spacewidth;
+    }
 
   return rval;
 }

Modified: branches/aptitude-0.3/aptitude/src/vscreen/columnify.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/columnify.h	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/columnify.h	Sat Jun 25 19:36:13 2005
@@ -1,6 +1,6 @@
 // columnify.h    -*-c++-*-
 //
-//  Copyright 2000 Daniel Burrows
+//  Copyright 2000, 2005 Daniel Burrows
 //  
 //  This program is free software; you can redistribute it and/or modify
 //  it under the terms of the GNU General Public License as published by
@@ -39,17 +39,17 @@
 
 struct column_disposition
 {
-  std::string text;  // The contents of the columns
+  std::wstring text;  // The contents of the columns
   int minx;          // The minimum x value to start this column at (useful for
                      // indenting stuff in trees)
 
-  column_disposition(std::string _text, int _minx):text(_text), minx(_minx) {}
+  column_disposition(std::wstring _text, int _minx):text(_text), minx(_minx) {}
 };
 
 struct column
 {
   column_disposition info;
-  unsigned int width;
+  int width;
   bool expand, shrink;
 
   column(const column_disposition &_info, int _width, bool _expand, bool _shrink)
@@ -63,10 +63,11 @@
 
 typedef std::list<column> layout;
 
-std::string columnify(const layout &format, unsigned int width);
-// Returns a string formatted as requested.  The string will be no longer than
-// width characters.
-// I could probably use printf-style strings, but with the groups it would
-// probably turn into a major pain..
+/* \return a string formatted as requested.  The string will be no
+ * wider than width columns.  I could probably use printf-style
+ * strings, but with the groups it would probably turn into a major
+ * pain..
+ */
+std::wstring columnify(const layout &format, int width);
 
 #endif

Modified: branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.cc	Sat Jun 25 19:36:13 2005
@@ -1,6 +1,6 @@
 // column_definition.cc
 //
-//  Copyright 2000,2001 Daniel Burrows
+//  Copyright 2000,2001, 2005 Daniel Burrows
 //  
 //  This program is free software; you can redistribute it and/or modify
 //  it under the terms of the GNU General Public License as published by
@@ -22,38 +22,41 @@
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 
+// For _()
+#include "../../aptitude.h"
+
 using namespace std;
 
 column_generator::~column_generator()
 {
 }
 
-column_definition_list *parse_columns(string config, column_parser_func parser, column_type_defaults *defaults)
+column_definition_list *parse_columns(wstring config, column_parser_func parser, column_type_defaults *defaults)
 {
   column_definition_list *rval=new column_definition_list;
 
-  string::size_type start=0;
-  string::size_type firstbreak;
+  wstring::size_type start=0;
+  wstring::size_type firstbreak;
   do
     {
-      firstbreak=config.find_first_of("%#", start);
+      firstbreak=config.find_first_of(L"%#", start);
       if(firstbreak!=start)
 	{
-	  string literal=string(config,
-				start,
-				firstbreak==config.npos?config.npos:firstbreak-start);
+	  wstring literal=wstring(config,
+				  start,
+				  firstbreak==config.npos?config.npos:firstbreak-start);
 
 	  // Grok backslashes, sort of
-	  string de_backslashified;
+	  wstring de_backslashified;
 
-	  for(string::size_type i=0; i<literal.size(); ++i)
+	  for(wstring::size_type i=0; i<literal.size(); ++i)
 	    {
-	      if(literal[i]!='\\' || i==literal.size()-1)
+	      if(literal[i]!=L'\\' || i==literal.size()-1)
 		de_backslashified+=literal[i];
 	      else switch(literal[++i])
 		{
-		case 'n':
-		  de_backslashified+='\n';
+		case L'n':
+		  de_backslashified+=L'\n';
 		  break;
 		default:
 		  de_backslashified+=literal[i];
@@ -61,7 +64,8 @@
 	    }
 
 	  rval->push_back(column_definition(-1,
-					    de_backslashified.size(),
+					    wcswidth(de_backslashified.c_str(),
+						     de_backslashified.size()),
 					    false,
 					    false,
 					    de_backslashified));
@@ -69,16 +73,16 @@
 
       if(firstbreak!=config.npos)
 	{
-	  if(config[firstbreak]=='#')
+	  if(config[firstbreak]==L'#')
 	    {
 	      if(rval->empty())
-		rval->push_back(column_definition(-1, 0, true, ""));
+		rval->push_back(column_definition(-1, 0, true, L""));
 	      else
 		rval->back().expand=true;
 
 	      firstbreak++;
 	    }
-	  else if(config[firstbreak]=='%')
+	  else if(config[firstbreak]==L'%')
 	    {
 	      int width=-1;
 
@@ -86,29 +90,31 @@
 
 	      if(firstbreak==config.size())
 		{
-		  _error->Error("Formatting marker with missing format code");
+		  _error->Error(_("Formatting marker with missing format code"));
 		  delete rval;
 		  return NULL;
 		}
 
-	      if(isdigit(config[firstbreak]))
+	      if(iswdigit(config[firstbreak]))
 		{
 		  unsigned long val;
 
-		  string tocvt="";
-		  while(isdigit(config[firstbreak]) && firstbreak<config.size()-1)
+		  wstring tocvt=L"";
+		  while(iswdigit(config[firstbreak]) && firstbreak<config.size()-1)
 		    tocvt+=config[firstbreak++];
 
 		  if(firstbreak==config.size())
 		    {
-		      _error->Error("Formatting marker with missing format code");
+		      _error->Error(_("Formatting marker with missing format code"));
 		      delete rval;
 		      return NULL;
 		    }
 
-		  if(!StrToNum(tocvt.c_str(), val, tocvt.size()))
+		  wchar_t *endptr;
+		  val=wcstol(tocvt.c_str(), &endptr, 0);
+		  if(*endptr!=L'\0')
 		    {
-		      _error->Error(("Bad number in format string: '"+tocvt+"'").c_str());
+		      _error->Error(_("Bad number in format string: '%ls'"), tocvt.c_str());
 		      delete rval;
 		      return NULL;
 		    }
@@ -116,19 +122,20 @@
 		  width=val;
 		}
 
-	      if(config[firstbreak]=='%')
+	      if(config[firstbreak]==L'%')
 		rval->push_back(column_definition(-1,
 						  1,
 						  false,
 						  false,
-						  "%"));
+						  L"%"));
 	      else
 		{
 		  int itemtype=parser(config[firstbreak]);
 
 		  if(itemtype==-1)
 		    {
-		      _error->Error((string("Unknown formatting code '")+config[firstbreak]+"'").c_str());
+		      _error->Error(_("Unknown formatting code '%lc'"),
+				    config[firstbreak]);
 		      delete rval;
 		      return NULL;
 		    }
@@ -140,7 +147,7 @@
 						    width,
 						    defaults[itemtype].expand,
 						    defaults[itemtype].shrink,
-						    ""));
+						    L""));
 		}
 	      firstbreak++;
 	    }
@@ -150,7 +157,7 @@
   return rval;
 }
 
-string column_generator::layout_columns(unsigned int width)
+wstring column_generator::layout_columns(unsigned int width)
 {
   layout l;
 

Modified: branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.h	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/config/column_definition.h	Sat Jun 25 19:36:13 2005
@@ -1,6 +1,6 @@
 // column_definition.h   -*-c++-*-
 //
-//  Copyright 2000 Daniel Burrows
+//  Copyright 2000, 2005 Daniel Burrows
 //  
 //  This program is free software; you can redistribute it and/or modify
 //  it under the terms of the GNU General Public License as published by
@@ -58,10 +58,10 @@
   unsigned int width;
   bool expand, shrink;
 
-  std::string arg; // For plain-text columns, this is the column contents
+  std::wstring arg; // For plain-text columns, this is the column contents
 
   column_definition(int _type, int _width, bool _expand, bool _shrink,
-		    std::string _arg="")
+		    std::wstring _arg=L"")
     :type(_type), width(_width), expand(_expand), shrink(_shrink), arg(_arg)
   {
     assert(_width>=0);
@@ -85,12 +85,12 @@
 
   virtual ~column_generator();
 
-  std::string layout_columns(unsigned int width);
+  std::wstring layout_columns(unsigned int width);
   // Lays out the columns into, well, columns.  startlocs is a list of where
   // the definable groups start -- it should have ngroups entries.
 };
 
-column_definition_list *parse_columns(std::string config,
+column_definition_list *parse_columns(std::wstring config,
 				      column_parser_func parser,
 				      column_type_defaults *defaults);
 // Allocates the array itself; the caller must delete[] it.