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

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


Author: dburrows
Date: Sat Jun 25 17:16:21 2005
New Revision: 3423

Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/vscreen/fragment.cc
   branches/aptitude-0.3/aptitude/src/vscreen/fragment.h
   branches/aptitude-0.3/aptitude/src/vscreen/fragment_contents.h
Log:
Use wide character strings internally to format text fragments, and require explicit conversion of std::strings.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Sat Jun 25 17:16:21 2005
@@ -1,5 +1,10 @@
 2005-06-25  Daniel Burrows  <dburrows@debian.org>
 
+	* src/vscreen/fragment.cc, src/vscreen/fragment.h, src/vscreen/fragment_contents.h:
+
+	  Use wide character strings internally to format text fragments,
+	  and require explicit conversion of std::strings.
+
 	* src/vscreen/curses++.h:
 
 	  Add a convenience constructor to build a wchstring by repeating

Modified: branches/aptitude-0.3/aptitude/src/vscreen/fragment.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/fragment.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/fragment.cc	Sat Jun 25 17:16:21 2005
@@ -3,6 +3,7 @@
 //   Copyright 2004 Daniel Burrows
 
 #include "fragment.h"
+#include "transcode.h"
 
 #include "config/colors.h"
 
@@ -10,6 +11,8 @@
 
 #include <algorithm>
 
+#include <wctype.h>
+
 using namespace std;
 
 fragment::~fragment()
@@ -22,13 +25,13 @@
 class _text_fragment:public fragment
 {
 public:
-  _text_fragment(const string &_s):s(_s) {}
+  _text_fragment(const wstring &_s):s(_s) {}
 
   fragment_contents layout(size_t firstw, size_t restw,
 			   const style &st)
   {
     fragment_contents rval;
-    rval.push_back(chstring(s, st));
+    rval.push_back(fragment_line(s, st));
     return rval;
   }
 
@@ -49,15 +52,41 @@
     return false;
   }
 private:
-  string s;
+  wstring s;
 };
 
-fragment *text_fragment(const string &s) { return new _text_fragment(s); }
-fragment *text_fragment(const string &s,
-			const style &style)
+fragment *text_fragment(const wstring &s) { return new _text_fragment(s); }
+fragment *text_fragment(const wstring &s,
+			const style &st)
 {
   return style_fragment(text_fragment(s),
-			style);
+			st);
+}
+
+fragment *transcode_fragment(const string &s,
+			     const char *encoding)
+{
+  wstring decoded;
+
+  // The error code is not translated, because that would require an
+  // additional decoding step and could result in infinite loops and
+  // other bad stuff.  Besides, something is very wrong if it appears;
+  // better to just output a diagnostic message that can be cut+paste.
+  if(!transcode(s.c_str(), decoded, encoding))
+    return sequence_fragment(text_fragment(decoded),
+			     text_fragment(L"Error decoding multibyte string",
+					   get_style("Error")),
+			     NULL);
+  else
+    return text_fragment(decoded);
+}
+
+fragment *transcode_fragment(const string &s,
+			     const style &st,
+			     const char *encoding)
+{
+  return style_fragment(transcode_fragment(s, encoding),
+			st);
 }
 
 /** This fragment just expands to a newline. */
@@ -217,7 +246,7 @@
   {
     fragment_contents rval;
 
-    rval.push_back(string(""));
+    rval.push_back(fragment_line(L""));
 
     for(vector<fragment*>::const_iterator i=contents.begin();
 	i!=contents.end(); ++i)
@@ -246,7 +275,7 @@
 	if(lines.size()==0)
 	  {
 	    if(rval.get_final_nl() && lines.get_final_nl())
-	      rval.push_back(chstring(""));
+	      rval.push_back(fragment_line(L""));
 
 	    rval.set_final_nl(rval.get_final_nl() || lines.get_final_nl());
 	  }
@@ -349,7 +378,7 @@
 
 // Fall back on sequence_fragment [for now?]
 fragment *join_fragments(const vector<fragment *> &fragments,
-			 const string &between)
+			 const wstring &between)
 {
   vector<fragment*> rval;
 
@@ -383,7 +412,7 @@
     for(fragment_contents::const_iterator i=lines.begin();
 	i!=lines.end(); ++i)
       {
-	chstring s=*i;
+	fragment_line s=*i;
 
 	// Make sure we at least advance the cursor for every line read.
 	//
@@ -396,7 +425,7 @@
 	while(first<s.size())
 	  {
 	    // Strip leading whitespace.
-	    while(first<s.size() && isspace(s[first]&A_CHARTEXT))
+	    while(first<s.size() && iswspace(s[first].ch))
 	      ++first;
 
 	    if(first==s.size())
@@ -406,7 +435,7 @@
 	    // line, do that.
 	    if(s.size()-first<=firstw)
 	      {
-		rval.push_back(chstring(s, first, s.size()-first));
+		rval.push_back(fragment_line(s, first, s.size()-first));
 		firstw=restw;
 		first=s.size();
 		output_something=true;
@@ -415,13 +444,13 @@
 	      {
 		size_t amt=firstw;
 
-		while(amt>0 && !isspace(s[first+amt]&A_CHARTEXT))
+		while(amt>0 && !iswspace(s[first+amt].ch))
 		  --amt;
 
 		// Oops, there's a word that's longer than the current line.
 		if(amt==0)
 		  {
-		    rval.push_back(chstring(s, first, firstw));
+		    rval.push_back(fragment_line(s, first, firstw));
 		    first+=firstw;
 		    firstw=restw;
 		    output_something=true;
@@ -430,11 +459,11 @@
 		  {
 		    // Eh, strip trailing whitespace.
 		    while(amt>0 &&
-			  isspace(s[first+amt]&A_CHARTEXT) &&
-			  isspace(s[first+amt-1]&A_CHARTEXT))
+			  isspace(s[first+amt].ch) &&
+			  isspace(s[first+amt-1].ch))
 		      --amt;
 
-		    rval.push_back(chstring(s, first, amt));
+		    rval.push_back(fragment_line(s, first, amt));
 		    firstw=restw;
 		    first+=amt;
 		    output_something=true;
@@ -444,7 +473,7 @@
 
 	if(!output_something)
 	  {
-	    rval.push_back(chstring(""));
+	    rval.push_back(fragment_line(L""));
 	    firstw=restw;
 	  }
 
@@ -499,27 +528,27 @@
     for(fragment_contents::const_iterator i=lines.begin();
 	i!=lines.end(); ++i)
       {
-	chstring s=*i;
+	fragment_line s=*i;
 
 	size_t first=0;
 
 	// Build a list of words on the current line.
-	vector<chstring> words;
+	vector<fragment_line> words;
 
 	bool output_something=false;
 
 	while(first<s.size())
 	  {
 	    // Strip leading whitespace.
-	    while(first<s.size() && isspace(s[first]&A_CHARTEXT))
+	    while(first<s.size() && iswspace(s[first].ch))
 	      ++first;
 
 	    size_t amt=0;
-	    while(first+amt<s.size() && !isspace(s[first+amt]&A_CHARTEXT))
+	    while(first+amt<s.size() && !iswspace(s[first+amt].ch))
 	      ++amt;
 
 	    if(amt>0)
-	      words.push_back(chstring(s, first, amt));
+	      words.push_back(fragment_line(s, first, amt));
 
 	    first+=amt;
 	  }
@@ -545,8 +574,8 @@
 	    if(nwords==0)
 	      {
 		// Split a single word: just chop the beginning off.
-		rval.push_back(chstring(words[word_start], 0, firstw));
-		words[word_start]=chstring(words[word_start], firstw);
+		rval.push_back(fragment_line(words[word_start], 0, firstw));
+		words[word_start]=fragment_line(words[word_start], firstw);
 		firstw=restw;
 		output_something=true;
 	      }
@@ -563,7 +592,7 @@
 
 		// Now spit the words into an output string, filled
 		// left and right.
-		chstring final("");
+		fragment_line final(L"");
 
 		// This is similar to the famous algorithm for drawing
 		// a line.  The idea is to add diff/(words-1) spaces
@@ -583,7 +612,7 @@
 			size_t nspaces=1+extra_spaces/(nwords-1);
 			extra_spaces%=nwords-1;
 
-			final+=chstring(nspaces, ' ');
+			final+=fragment_line(nspaces, L' ', st.get_attrs());
 		      }
 
 		    final+=words[word+word_start];
@@ -599,7 +628,7 @@
 
 	if(!output_something)
 	  {
-	    rval.push_back(chstring(""));
+	    rval.push_back(fragment_line(L""));
 	    firstw=restw;
 	  }
       }
@@ -656,24 +685,24 @@
       {
 	if(i->empty())
 	  {
-	    rval.push_back(chstring(""));
+	    rval.push_back(fragment_line(L""));
 	    firstw=restw;
 	  }
 	else
 	  {
-	    chstring s=*i;
-	    chstring::size_type start=0;
+	    fragment_line s=*i;
+	    fragment_line::size_type start=0;
 
 	    while(s.size()-start>firstw)
 	      {
-		rval.push_back(chstring(s, start, firstw));
+		rval.push_back(fragment_line(s, start, firstw));
 		start+=firstw;
 		firstw=restw;
 	      }
 
 	    if(start<s.size())
 	      {
-		rval.push_back(chstring(s, start));
+		rval.push_back(fragment_line(s, start));
 		firstw=restw;
 	      }
 	  }
@@ -724,7 +753,7 @@
 	if(i->size()<=firstw)
 	  rval.push_back(*i);
 	else
-	  rval.push_back(chstring(*i, 0, firstw));
+	  rval.push_back(fragment_line(*i, 0, firstw));
 
 	firstw=restw;
       }
@@ -773,8 +802,8 @@
     if(restw<=restindent)
       return fragment_contents();
 
-    fragment_line firstprepend(firstindent, ' ');
-    fragment_line restprepend(restindent, ' ');
+    fragment_line firstprepend(firstindent, L' ', st.get_attrs());
+    fragment_line restprepend(restindent, L' ', st.get_attrs());
 
     firstprepend.apply_style(st);
     restprepend.apply_style(st);
@@ -788,7 +817,7 @@
 
     for(fragment_contents::const_iterator i=lines.begin(); i!=lines.end(); ++i)
       {
-	chstring l=((i==lines.begin())?firstprepend:restprepend)+*i;
+	fragment_line l=((i==lines.begin())?firstprepend:restprepend)+*i;
 
 	rval.push_back(l);
       }

Modified: branches/aptitude-0.3/aptitude/src/vscreen/fragment.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/fragment.h	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/fragment.h	Sat Jun 25 17:16:21 2005
@@ -81,7 +81,7 @@
  *
  *  \return the new fragment
  */
-fragment *text_fragment(const std::string &s);
+fragment *text_fragment(const std::wstring &s);
 
 /** Create a fragment from a string of text.  The text will simply be
  *  formatted as a single line without clipping.
@@ -95,6 +95,24 @@
 fragment *text_fragment(const std::string &s,
 			const style &st);
 
+/** Create a fragment from a string of multibyte-encoded text.
+ *
+ *  \param s the text to use
+ *  \param encoding the text's encoding; if this is \b null or
+ *   unspecified, LC_CTYPE will be used.
+ *
+ *  \return the new fragment
+ */
+fragment *transcode_fragment(const std::string &s,
+			     const char *encoding=NULL);
+
+/** Create a fragment from a string of multibyte-encoded text,
+ *  wrapping an implicit style_fragment around it.
+ */
+fragment *transcode_fragment(const std::string &s,
+			     const style &st,
+			     const char *encoding=NULL);
+
 /** Create a fragment from a string of text.  The text will simply be
  *  formatted as a single line without clipping.
  *
@@ -158,7 +176,7 @@
  *  \param between a string to place between adjacent items in the input list
  */
 fragment *join_fragments(const std::vector<fragment *> &fragments,
-			 const std::string &between);
+			 const std::wstring &between);
 
 /** Create a flowbox.
  *
@@ -237,6 +255,7 @@
  *
  *  - %F: substitutes a fragment into the sequence being built
  *  - %s: substitutes a const char * into the sequence being built
+ *        with transcoding according to LC_CTYPE
  *  - %n: substitutes a newline fragment into the sequence being built
  *  - %%: inserts a literal %
  *  - %B/%b: toggle the bold character attribute

Modified: branches/aptitude-0.3/aptitude/src/vscreen/fragment_contents.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/fragment_contents.h	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/fragment_contents.h	Sat Jun 25 17:16:21 2005
@@ -15,7 +15,7 @@
  *  worthwhile to change this to a rope<chtype> if this class is
  *  used to format larger pieces of text.
  */
-typedef chstring fragment_line;
+typedef wchstring fragment_line;
 
 /** This class represents the formatted contents of a fragment.
  *