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

Daniel Burrows dburrows@costa.debian.org
Wed, 29 Jun 2005 18:10:59 +0000


Author: dburrows
Date: Wed Jun 29 18:10:56 2005
New Revision: 3508

Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/vscreen/vs_menu.cc
   branches/aptitude-0.3/aptitude/src/vscreen/vs_menu.h
Log:
Properly handle wide characters in vs_menu.  I hope.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Wed Jun 29 18:10:56 2005
@@ -1,5 +1,9 @@
 2005-06-29  Daniel Burrows  <dburrows@debian.org>
 
+	* src/vscreen/vs_menu.cc, src/vscreen/vs_menu.h:
+
+	  Rewrote vs_menu to properly handle wide characters.
+
 	* src/vscreen/curses++.h, src/vscreen/vscreen_widget.h:
 
 	  Get rid of the attribute argument, it seems to cause unexpected

Modified: branches/aptitude-0.3/aptitude/src/vscreen/vs_menu.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/vs_menu.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/vs_menu.cc	Wed Jun 29 18:10:56 2005
@@ -51,13 +51,13 @@
 {
 }
 
-vs_menu_item::vs_menu_item(const string &_title, const string &_binding,
-			   const string &_description)
+vs_menu_item::vs_menu_item(const wstring &_title, const string &_binding,
+			   const wstring &_description)
   :title(_title), description(_description), binding(_binding),
    hotkey((chtype) ERR)
 {
-  for(string::size_type i=0; i<title.size(); i++)
-    if(title[i]=='^' && i+1<title.size())
+  for(wstring::size_type i=0; i<title.size(); i++)
+    if(title[i]==L'^' && i+1<title.size())
       {
 	hotkey=title[i+1];
 	break;
@@ -95,9 +95,9 @@
 	  assert(inf->item_name!=NULL);
 
 	  {
-	    vs_menu_item *newitem=new vs_menu_item(inf->item_name,
+	    vs_menu_item *newitem=new vs_menu_item(transcode(inf->item_name),
 						   inf->item_binding?inf->item_binding:"",
-						   inf->item_description?inf->item_description:"");
+						   transcode(inf->item_description?inf->item_description:""));
 
 	    if(inf->item_slot)
 	      newitem->selected.connect(*inf->item_slot);
@@ -130,19 +130,25 @@
   items.push_back(newitem);
   if(newitem)
     {
-      string::size_type shortcutsize=0;
-      string::size_type menusize=0;
+      int shortcutwidth=0;
+      int menuwidth=0;
 
-      for(string::size_type i=0; i<newitem->get_title().size(); ++i)
-	if(newitem->get_title()[i]!='^')
-	  ++menusize;
+      const wstring &title=newitem->get_title();
+      const string &binding=newitem->get_binding();
 
-      if(newitem->get_binding().empty())
-	shortcutsize=0;
+      for(wstring::size_type i=0; i<title.size(); ++i)
+	if(title[i]!=L'^')
+	  menuwidth+=wcwidth(title[i]);
+
+      if(binding.empty())
+	shortcutwidth=0;
       else
-	shortcutsize=global_bindings.readable_keyname(newitem->get_binding()).size()+1;
+	{
+	  wstring keyname=global_bindings.readable_keyname(binding);
+	  shortcutwidth=wcswidth(keyname.c_str(), keyname.size())+1;
+	}
 
-      req_width=max<int>(menusize+2+shortcutsize,req_width);
+      req_width=max<int>(menuwidth+2+shortcutwidth,req_width);
     }
 
   if(get_visible())
@@ -175,6 +181,9 @@
     vscreen_queuelayout();
 }
 
+// Right now the width is cached; maybe it should be calculated
+// dynamically?  At the moment it probably doesn't make a difference.
+// I guess.
 int vs_menu::width_request()
 {
   return req_width;
@@ -369,12 +378,10 @@
   getmaxyx(height, width);
 
   apply_style(border_style);
-  mvaddch(0, 0, ACS_ULCORNER);
+  mvadd_wch(0, 0, WACS_ULCORNER);
   for(int i=1; i<width-1; i++)
-    addch(ACS_HLINE);
-  addch(ACS_URCORNER);
-
-  string::size_type maxlen=width-2;
+    add_wch(WACS_HLINE);
+  add_wch(WACS_URCORNER);
 
   // Make sure that whatever is selected is really selectable.
   sanitize_cursor(true);
@@ -385,27 +392,31 @@
 	bool boldthis=false;
 
 	apply_style(border_style);
-	mvaddch(1+i, 0, ACS_VLINE);
-	mvaddch(1+i, width-1, ACS_VLINE);
+	mvadd_wch(1+i, 0, WACS_VLINE);
+	mvadd_wch(1+i, width-1, WACS_VLINE);
 
-	string title=items[i]->get_title();
-	// HACK, remove once vs_menu is properly widechar-safe.
-	string righttext=transcode(items[i]->get_binding().empty()?L"":global_bindings.readable_keyname(items[i]->get_binding()));
+	wstring title=items[i]->get_title();
+	wstring righttext=items[i]->get_binding().empty()?L"":global_bindings.readable_keyname(items[i]->get_binding());
 
 	bool enabled=items[i]->is_enabled();
+	style textst;
 
 	if(i==cursorloc)
-	  apply_style(highlighted_style);
+	  textst=highlighted_style;
 	else if(enabled)
-	  apply_style(entry_style);
+	  textst=entry_style;
 	else
-	  apply_style(disabled_style);
+	  textst=disabled_style;
+
+	apply_style(textst);
 
 	move(1+i, 1);
 
-	string::size_type titleloc=0, rightloc=0;
+	wstring::size_type titleloc=0, rightloc=0;
+	int rightwidth=wcswidth(righttext.c_str(), righttext.size());
+	int curw=1;
 
-	for(string::size_type j=0; j<maxlen; j++)
+	while(curw<width-1)
 	  {
 	    while(titleloc<title.size() && title[titleloc]=='^')
 	      {
@@ -415,48 +426,76 @@
 
 	    if(titleloc==title.size())
 	      {
-		addch(' ');
-		titleloc++;
+		add_wch(L' ');
+		++titleloc;
+		curw+=wcwidth(L' ');;
 	      }
 	    else if(titleloc>title.size())
 	      {
-		if(j<maxlen-righttext.size())
-		  addch(' ');
+		if(curw<width-1-rightwidth)
+		  {
+		    add_wch(L' ');
+		    curw+=wcwidth(L' ');
+		  }
 		else
-		  addch((unsigned char) righttext[rightloc++]);
+		  {
+		    wchar_t wch=righttext[rightloc];
+
+		    add_wch(wch);
+		    curw+=wcwidth(wch);
+		    ++rightloc;
+		  }
 	      }
 	    else if(boldthis)
 	      {
-		addch(((unsigned char) title[titleloc++])|A_BOLD);
+		wchar_t wch=title[titleloc];
+
+		apply_style(textst+style_attrs_on(A_BOLD));
+		add_wch(wch);
+		apply_style(textst);
 		boldthis=false;
+
+		curw+=wcwidth(wch);
+		++titleloc;
 	      }
 	    else
-	      addch((unsigned char) title[titleloc++]);
+	      {
+		wchar_t wch=title[titleloc];
+
+		add_wch(wch);
+		curw+=wcwidth(wch);
+		++titleloc;
+	      }
 	  }
       }
     else
       {
 	apply_style(border_style);
-	mvaddch(1+i, 0, ACS_LTEE);
+	mvadd_wch(1+i, 0, WACS_LTEE);
 	for(int j=1; j<width-1; j++)
-	  addch(ACS_HLINE);
-	addch(ACS_RTEE);
+	  add_wch(WACS_HLINE);
+	add_wch(WACS_RTEE);
       }
 
   apply_style(border_style);
+
   for(int i=items.size()+1; i<height-1; i++)
     {
       move(i, 0);
-      addch(ACS_VLINE);
+      add_wch(WACS_VLINE);
+
+      apply_style(entry_style);
       for(int j=0; j<width-2; j++)
-	addch(' ');
-      addch(ACS_VLINE);
+	add_wch(L' ');
+      apply_style(border_style);
+
+      add_wch(WACS_VLINE);
     }
 
-  mvaddch(height-1, 0, ACS_LLCORNER);
+  mvadd_wch(height-1, 0, WACS_LLCORNER);
   for(int i=1; i<width-1; i++)
-    addch(ACS_HLINE);
-  addch(ACS_LRCORNER);
+    add_wch(WACS_HLINE);
+  add_wch(WACS_LRCORNER);
 }
 
 bool vs_menu::get_cursorvisible()

Modified: branches/aptitude-0.3/aptitude/src/vscreen/vs_menu.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/vs_menu.h	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/vs_menu.h	Wed Jun 29 18:10:56 2005
@@ -19,10 +19,10 @@
 class vs_menu_item
 {
   // The text displayed in the menu entry
-  std::string title;
+  std::wstring title;
 
   // A string describing the item's function
-  std::string description;
+  std::wstring description;
 
   // The keybinding whose definition (in the GLOBAL bindings list) is
   // displayed to the right of the menu entry.
@@ -32,12 +32,12 @@
   chtype hotkey;
 public:
   // Infers the hotkey from the title
-  vs_menu_item(const std::string &_title, const std::string &_binding,
-	       const std::string &_description);
+  vs_menu_item(const std::wstring &_title, const std::string &_binding,
+	       const std::wstring &_description);
 
-  std::string get_title() {return title;}
+  std::wstring get_title() {return title;}
   std::string get_binding() {return binding;}
-  std::string get_description() {return description;}
+  std::wstring get_description() {return description;}
   chtype get_hotkey() {return hotkey;}
 
   /** The canonical way to test whether an item is really enabled. */
@@ -66,6 +66,7 @@
   // VS_MENU_END: the last item in this information block
   enum item_types {VS_MENU_ITEM, VS_MENU_SEPARATOR, VS_MENU_END} item_type;
 
+  /** item_name and item_description are multibyte representations. */
   const char *item_name, *item_binding, *item_description;
 
   // How to communicate with the outside world..