Browse Source

PGEntry should use wstring internally

David Rose 24 years ago
parent
commit
64ddb25aed

+ 38 - 8
panda/src/pgui/pgEntry.I

@@ -21,25 +21,30 @@
 //     Function: PGEntry::set_text
 //     Function: PGEntry::set_text
 //       Access: Published
 //       Access: Published
 //  Description: Changes the text currently displayed within the
 //  Description: Changes the text currently displayed within the
-//               entry.
+//               entry.  This uses the Unicode encoding currently
+//               specified for the "focus" TextNode; therefore, the
+//               TextNode must exist before calling set_text().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PGEntry:: 
 INLINE void PGEntry:: 
 set_text(const string &text) {
 set_text(const string &text) {
-  _text = text;
-  _text_geom_stale = true;
-  _cursor_stale = true;
-  _blink_start = ClockObject::get_global_clock()->get_frame_time();
+  TextNode *text_node = get_text_def(S_focus);
+  nassertv(text_node != (TextNode *)NULL);
+  set_wtext(text_node->decode_text(text));
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PGEntry::get_text
 //     Function: PGEntry::get_text
 //       Access: Published
 //       Access: Published
 //  Description: Returns the text currently displayed within the
 //  Description: Returns the text currently displayed within the
-//               entry.
+//               entry.  This uses the Unicode encoding currently
+//               specified for the "focus" TextNode; therefore, the
+//               TextNode must exist before calling get_text().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE const string &PGEntry:: 
+INLINE string PGEntry:: 
 get_text() const {
 get_text() const {
-  return _text;
+  TextNode *text_node = get_text_def(S_focus);
+  nassertr(text_node != (TextNode *)NULL, string());
+  return text_node->encode_wtext(get_wtext());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -352,3 +357,28 @@ INLINE string PGEntry::
 get_erase_event() const {
 get_erase_event() const {
   return "erase-" + get_id();
   return "erase-" + get_id();
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGEntry::set_wtext
+//       Access: Public
+//  Description: Changes the text currently displayed within the
+//               entry.
+////////////////////////////////////////////////////////////////////
+INLINE void PGEntry:: 
+set_wtext(const wstring &wtext) {
+  _wtext = wtext;
+  _text_geom_stale = true;
+  _cursor_stale = true;
+  _blink_start = ClockObject::get_global_clock()->get_frame_time();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PGEntry::get_wtext
+//       Access: Public
+//  Description: Returns the text currently displayed within the
+//               entry.
+////////////////////////////////////////////////////////////////////
+INLINE const wstring &PGEntry:: 
+get_wtext() const {
+  return _wtext;
+}

+ 71 - 72
panda/src/pgui/pgEntry.cxx

@@ -82,8 +82,8 @@ PGEntry::
 PGEntry::
 PGEntry::
 PGEntry(const PGEntry &copy) :
 PGEntry(const PGEntry &copy) :
   PGItem(copy),
   PGItem(copy),
-  _text(copy._text),
-  _obscured_text(copy._obscured_text),
+  _wtext(copy._wtext),
+  _obscured_wtext(copy._obscured_wtext),
   _cursor_position(copy._cursor_position),
   _cursor_position(copy._cursor_position),
   _max_chars(copy._max_chars),
   _max_chars(copy._max_chars),
   _max_width(copy._max_width),
   _max_width(copy._max_width),
@@ -106,8 +106,8 @@ PGEntry(const PGEntry &copy) :
 void PGEntry::
 void PGEntry::
 operator = (const PGEntry &copy) {
 operator = (const PGEntry &copy) {
   PGItem::operator = (copy);
   PGItem::operator = (copy);
-  _text = copy._text;
-  _obscured_text = copy._obscured_text;
+  _wtext = copy._wtext;
+  _obscured_wtext = copy._obscured_wtext;
   _cursor_position = copy._cursor_position;
   _cursor_position = copy._cursor_position;
   _max_chars = copy._max_chars;
   _max_chars = copy._max_chars;
   _max_width = copy._max_width;
   _max_width = copy._max_width;
@@ -179,7 +179,7 @@ press(const MouseWatcherParameter &param, bool background) {
       } else if ((!background && get_focus()) || 
       } else if ((!background && get_focus()) || 
                  (background && get_background_focus())) {
                  (background && get_background_focus())) {
         // Keyboard button.
         // Keyboard button.
-        _cursor_position = min(_cursor_position, (int)_text.length());
+        _cursor_position = min(_cursor_position, (int)_wtext.length());
         _blink_start = ClockObject::get_global_clock()->get_frame_time();
         _blink_start = ClockObject::get_global_clock()->get_frame_time();
         if (button == KeyboardButton::enter()) {
         if (button == KeyboardButton::enter()) {
           // Enter.  Accept the entry.
           // Enter.  Accept the entry.
@@ -188,10 +188,10 @@ press(const MouseWatcherParameter &param, bool background) {
         } else if (button == KeyboardButton::backspace()) {
         } else if (button == KeyboardButton::backspace()) {
           // Backspace.  Remove the character to the left of the cursor.
           // Backspace.  Remove the character to the left of the cursor.
           if (_cursor_position > 0) {
           if (_cursor_position > 0) {
-            if (_obscure_mode && _obscured_text.length() == _text.length()) {
-              _obscured_text.erase(_obscured_text.begin() + _obscured_text.length() - 1);
+            if (_obscure_mode && _obscured_wtext.length() == _wtext.length()) {
+              _obscured_wtext.erase(_obscured_wtext.begin() + _obscured_wtext.length() - 1);
             }
             }
-            _text.erase(_text.begin() + _cursor_position - 1);
+            _wtext.erase(_wtext.begin() + _cursor_position - 1);
             _cursor_position--;
             _cursor_position--;
             _cursor_stale = true;
             _cursor_stale = true;
             _text_geom_stale = true;
             _text_geom_stale = true;
@@ -200,11 +200,11 @@ press(const MouseWatcherParameter &param, bool background) {
           
           
         } else if (button == KeyboardButton::del()) {
         } else if (button == KeyboardButton::del()) {
           // Delete.  Remove the character to the right of the cursor.
           // Delete.  Remove the character to the right of the cursor.
-          if (_cursor_position < (int)_text.length()) {
-            if (_obscure_mode && _obscured_text.length() == _text.length()) {
-              _obscured_text.erase(_obscured_text.begin() + _obscured_text.length() - 1);
+          if (_cursor_position < (int)_wtext.length()) {
+            if (_obscure_mode && _obscured_wtext.length() == _wtext.length()) {
+              _obscured_wtext.erase(_obscured_wtext.begin() + _obscured_wtext.length() - 1);
             }
             }
-            _text.erase(_text.begin() + _cursor_position);
+            _wtext.erase(_wtext.begin() + _cursor_position);
             _text_geom_stale = true;
             _text_geom_stale = true;
             erase(param);
             erase(param);
           }
           }
@@ -219,7 +219,7 @@ press(const MouseWatcherParameter &param, bool background) {
         } else if (button == KeyboardButton::right()) {
         } else if (button == KeyboardButton::right()) {
           if (_cursor_keys_active) {
           if (_cursor_keys_active) {
             // Right arrow.  Move the cursor position to the right.
             // Right arrow.  Move the cursor position to the right.
-            _cursor_position = min(_cursor_position + 1, (int)_text.length());
+            _cursor_position = min(_cursor_position + 1, (int)_wtext.length());
             _cursor_stale = true;
             _cursor_stale = true;
           }
           }
           
           
@@ -233,29 +233,32 @@ press(const MouseWatcherParameter &param, bool background) {
         } else if (button == KeyboardButton::end()) {
         } else if (button == KeyboardButton::end()) {
           if (_cursor_keys_active) {
           if (_cursor_keys_active) {
             // End.  Move the cursor position to the end.
             // End.  Move the cursor position to the end.
-            _cursor_position = _text.length();
+            _cursor_position = _wtext.length();
             _cursor_stale = true;
             _cursor_stale = true;
           }
           }
           
           
         } else if (!use_keystrokes && button.has_ascii_equivalent()) {
         } else if (!use_keystrokes && button.has_ascii_equivalent()) {
-          char key = button.get_ascii_equivalent();
+          // This part of the code is deprecated and will be removed
+          // soon.  It only supports the old button up/down method of
+          // sending keystrokes, instead of the new keystroke method.
+          wchar_t key = button.get_ascii_equivalent();
           if (isprint(key)) {
           if (isprint(key)) {
             // A normal visible character.  Add a new character to the
             // A normal visible character.  Add a new character to the
             // text entry, if there's room.
             // text entry, if there's room.
             
             
-            if (get_max_chars() > 0 && (int)_text.length() >= get_max_chars()) {
+            if (get_max_chars() > 0 && (int)_wtext.length() >= get_max_chars()) {
               overflow(param);
               overflow(param);
             } else {
             } else {
-              string new_text = 
-                _text.substr(0, _cursor_position) + key +
-                _text.substr(_cursor_position);
+              wstring new_text = 
+                _wtext.substr(0, _cursor_position) + key +
+                _wtext.substr(_cursor_position);
 
 
               // Get a string to measure its length.  In normal mode,
               // Get a string to measure its length.  In normal mode,
               // we measure the text itself.  In obscure mode, we
               // we measure the text itself.  In obscure mode, we
               // measure a string of n asterisks.
               // measure a string of n asterisks.
-              string measure_text;
+              wstring measure_text;
               if (_obscure_mode) {
               if (_obscure_mode) {
-                measure_text = get_display_text() + '*';
+                measure_text = get_display_wtext() + (wchar_t)'*';
               } else {
               } else {
                 measure_text = new_text;
                 measure_text = new_text;
               }
               }
@@ -273,7 +276,7 @@ press(const MouseWatcherParameter &param, bool background) {
                   // If we have multiple lines, we have to check the
                   // If we have multiple lines, we have to check the
                   // length by wordwrapping it and counting up the
                   // length by wordwrapping it and counting up the
                   // number of lines.
                   // number of lines.
-                  string ww_text = text_node->wordwrap_to(measure_text, _max_width, true);
+                  wstring ww_text = text_node->wordwrap_to(measure_text, _max_width, true);
                   int num_lines = 1;
                   int num_lines = 1;
                   size_t last_line_start = 0;
                   size_t last_line_start = 0;
                   for (size_t p = 0;
                   for (size_t p = 0;
@@ -290,7 +293,7 @@ press(const MouseWatcherParameter &param, bool background) {
                     // We must also ensure that the last line is not too
                     // We must also ensure that the last line is not too
                     // long (it might be, because of additional
                     // long (it might be, because of additional
                     // whitespace on the end).
                     // whitespace on the end).
-                    string last_line = ww_text.substr(last_line_start);
+                    wstring last_line = ww_text.substr(last_line_start);
                     float last_line_width = text_node->calc_width(last_line);
                     float last_line_width = text_node->calc_width(last_line);
                     if (num_lines == _num_lines) {
                     if (num_lines == _num_lines) {
                       // Mainly we only care about this if we're on
                       // Mainly we only care about this if we're on
@@ -303,8 +306,8 @@ press(const MouseWatcherParameter &param, bool background) {
                       // infinite number of spaces to accumulate.
                       // infinite number of spaces to accumulate.
                       // However, we must allow at least *one* space
                       // However, we must allow at least *one* space
                       // on the end of a line.
                       // on the end of a line.
-                      if (_text.length() >= 1 && 
-                          _text[_text.length() - 1] == ' ') {
+                      if (_wtext.length() >= 1 && 
+                          _wtext[_wtext.length() - 1] == ' ') {
                         if (last_line_width > _max_width) {
                         if (last_line_width > _max_width) {
                           // In this case, however, it's not exactly
                           // In this case, however, it's not exactly
                           // an overflow; we just want to reject the
                           // an overflow; we just want to reject the
@@ -321,9 +324,9 @@ press(const MouseWatcherParameter &param, bool background) {
                 overflow(param);
                 overflow(param);
                 
                 
               } else {
               } else {
-                _text = new_text;
+                _wtext = new_text;
                 if (_obscure_mode) {
                 if (_obscure_mode) {
-                  _obscured_text = measure_text;
+                  _obscured_wtext = measure_text;
                 }
                 }
                 
                 
                 _cursor_position++;
                 _cursor_position++;
@@ -356,26 +359,22 @@ keystroke(const MouseWatcherParameter &param, bool background) {
         if (!isascii(keycode) || isprint(keycode)) {
         if (!isascii(keycode) || isprint(keycode)) {
           // A normal visible character.  Add a new character to the
           // A normal visible character.  Add a new character to the
           // text entry, if there's room.
           // text entry, if there's room.
+          wstring new_char(1, (wchar_t)keycode);
 
 
-          // Encode the character.  This might expand it to two or
-          // three bytes, or it might remain a one-byte character.
-          TextNode *text_node = get_text_def(S_focus);
-          string new_char = text_node->encode_wchar(keycode);
-
-          if (get_max_chars() > 0 && (int)_text.length() >= get_max_chars()) {
+          if (get_max_chars() > 0 && (int)_wtext.length() >= get_max_chars()) {
             overflow(param);
             overflow(param);
           } else {
           } else {
-            _cursor_position = min(_cursor_position, (int)_text.length());
-            string new_text = 
-              _text.substr(0, _cursor_position) + new_char +
-              _text.substr(_cursor_position);
+            _cursor_position = min(_cursor_position, (int)_wtext.length());
+            wstring new_text = 
+              _wtext.substr(0, _cursor_position) + new_char +
+              _wtext.substr(_cursor_position);
             
             
             // Get a string to measure its length.  In normal mode,
             // Get a string to measure its length.  In normal mode,
             // we measure the text itself.  In obscure mode, we
             // we measure the text itself.  In obscure mode, we
             // measure a string of n asterisks.
             // measure a string of n asterisks.
-            string measure_text;
+            wstring measure_text;
             if (_obscure_mode) {
             if (_obscure_mode) {
-              measure_text = get_display_text() + '*';
+              measure_text = get_display_wtext() + (wchar_t)'*';
             } else {
             } else {
               measure_text = new_text;
               measure_text = new_text;
             }
             }
@@ -393,7 +392,7 @@ keystroke(const MouseWatcherParameter &param, bool background) {
                 // If we have multiple lines, we have to check the
                 // If we have multiple lines, we have to check the
                 // length by wordwrapping it and counting up the
                 // length by wordwrapping it and counting up the
                 // number of lines.
                 // number of lines.
-                string ww_text = text_node->wordwrap_to(measure_text, _max_width, true);
+                wstring ww_text = text_node->wordwrap_to(measure_text, _max_width, true);
                 int num_lines = 1;
                 int num_lines = 1;
                 size_t last_line_start = 0;
                 size_t last_line_start = 0;
                 for (size_t p = 0;
                 for (size_t p = 0;
@@ -410,7 +409,7 @@ keystroke(const MouseWatcherParameter &param, bool background) {
                   // We must also ensure that the last line is not too
                   // We must also ensure that the last line is not too
                   // long (it might be, because of additional
                   // long (it might be, because of additional
                   // whitespace on the end).
                   // whitespace on the end).
-                  string last_line = ww_text.substr(last_line_start);
+                  wstring last_line = ww_text.substr(last_line_start);
                   float last_line_width = text_node->calc_width(last_line);
                   float last_line_width = text_node->calc_width(last_line);
                   if (num_lines == _num_lines) {
                   if (num_lines == _num_lines) {
                     // Mainly we only care about this if we're on
                     // Mainly we only care about this if we're on
@@ -423,8 +422,8 @@ keystroke(const MouseWatcherParameter &param, bool background) {
                     // infinite number of spaces to accumulate.
                     // infinite number of spaces to accumulate.
                     // However, we must allow at least *one* space
                     // However, we must allow at least *one* space
                     // on the end of a line.
                     // on the end of a line.
-                    if (_text.length() >= 1 && 
-                        _text[_text.length() - 1] == ' ') {
+                    if (_wtext.length() >= 1 && 
+                        _wtext[_wtext.length() - 1] == ' ') {
                       if (last_line_width > _max_width) {
                       if (last_line_width > _max_width) {
                         // In this case, however, it's not exactly
                         // In this case, however, it's not exactly
                         // an overflow; we just want to reject the
                         // an overflow; we just want to reject the
@@ -441,9 +440,9 @@ keystroke(const MouseWatcherParameter &param, bool background) {
               overflow(param);
               overflow(param);
               
               
             } else {
             } else {
-              _text = new_text;
+              _wtext = new_text;
               if (_obscure_mode) {
               if (_obscure_mode) {
-                _obscured_text = measure_text;
+                _obscured_wtext = measure_text;
               }
               }
               
               
               _cursor_position += new_char.length();
               _cursor_position += new_char.length();
@@ -561,16 +560,16 @@ setup(float width, int num_lines) {
   frame[3] = max(max(ll[2], ur[2]), max(lr[2], ul[2]));
   frame[3] = max(max(ll[2], ur[2]), max(lr[2], ul[2]));
 
 
   switch (text_node->get_align()) {
   switch (text_node->get_align()) {
-  case TM_ALIGN_LEFT:
+  case TextNode::A_left:
     // The default case.
     // The default case.
     break;
     break;
 
 
-  case TM_ALIGN_CENTER:
+  case TextNode::A_center:
     frame[0] = -width / 2.0;
     frame[0] = -width / 2.0;
     frame[1] = width / 2.0;
     frame[1] = width / 2.0;
     break;
     break;
 
 
-  case TM_ALIGN_RIGHT:
+  case TextNode::A_right:
     frame[0] = -width;
     frame[0] = -width;
     frame[1] = 0.0f;
     frame[1] = 0.0f;
     break;
     break;
@@ -676,30 +675,30 @@ set_focus(bool focus) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PGEntry::get_display_text
+//     Function: PGEntry::get_display_wtext
 //       Access: Private
 //       Access: Private
 //  Description: Returns the string that should be displayed within
 //  Description: Returns the string that should be displayed within
-//               the entry.  This is normally _text, but it may be
-//               _obscured_text.
+//               the entry.  This is normally _wtext, but it may be
+//               _obscured_wtext.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-const string &PGEntry::
-get_display_text() {
+const wstring &PGEntry::
+get_display_wtext() {
   if (_obscure_mode) {
   if (_obscure_mode) {
     // If obscure mode is enabled, we should just display a bunch of
     // If obscure mode is enabled, we should just display a bunch of
     // asterisks.
     // asterisks.
-    if (_obscured_text.length() != _text.length()) {
-      _obscured_text = "";
-      string::const_iterator ti;
-      for (ti = _text.begin(); ti != _text.end(); ++ti) {
-        _obscured_text += '*';
+    if (_obscured_wtext.length() != _wtext.length()) {
+      _obscured_wtext = wstring();
+      wstring::const_iterator ti;
+      for (ti = _wtext.begin(); ti != _wtext.end(); ++ti) {
+        _obscured_wtext += (wchar_t)'*';
       }
       }
     }
     }
 
 
-    return _obscured_text;
+    return _obscured_wtext;
 
 
   } else {
   } else {
     // In normal, non-obscure mode, we display the actual text.
     // In normal, non-obscure mode, we display the actual text.
-    return _text;
+    return _wtext;
   }
   }
 }
 }
 
 
@@ -728,20 +727,20 @@ update_text() {
   nassertv(node != (TextNode *)NULL);
   nassertv(node != (TextNode *)NULL);
 
 
   if (_text_geom_stale || node != _last_text_def) {
   if (_text_geom_stale || node != _last_text_def) {
-    const string &display_text = get_display_text();
+    const wstring &display_wtext = get_display_wtext();
 
 
     // We need to regenerate.
     // We need to regenerate.
     _last_text_def = node;
     _last_text_def = node;
 
 
     if (_max_width > 0.0f && _num_lines > 1) {
     if (_max_width > 0.0f && _num_lines > 1) {
       // Fold the text into multiple lines.
       // Fold the text into multiple lines.
-      string ww_text = 
-        _last_text_def->wordwrap_to(display_text, _max_width, true);
+      wstring ww_text = 
+        _last_text_def->wordwrap_to(display_wtext, _max_width, true);
 
 
       // And chop the lines up into pieces.
       // And chop the lines up into pieces.
       _ww_lines.clear();
       _ww_lines.clear();
       size_t p = 0;
       size_t p = 0;
-      size_t q = ww_text.find('\n');
+      size_t q = ww_text.find((wchar_t)'\n');
       while (q != string::npos) {
       while (q != string::npos) {
         _ww_lines.push_back(WWLine());
         _ww_lines.push_back(WWLine());
         WWLine &line = _ww_lines.back();
         WWLine &line = _ww_lines.back();
@@ -749,8 +748,8 @@ update_text() {
 
 
         // Get the left edge of the text at this line.
         // Get the left edge of the text at this line.
         line._left = 0.0f;
         line._left = 0.0f;
-        if (_last_text_def->get_align() != TM_ALIGN_LEFT) {
-          _last_text_def->set_text(line._str);
+        if (_last_text_def->get_align() != TextNode::A_left) {
+          _last_text_def->set_wtext(line._str);
           line._left = _last_text_def->get_left();
           line._left = _last_text_def->get_left();
         }
         }
 
 
@@ -763,21 +762,21 @@ update_text() {
       
       
       // Get the left edge of the text at this line.
       // Get the left edge of the text at this line.
       line._left = 0.0f;
       line._left = 0.0f;
-      if (_last_text_def->get_align() != TM_ALIGN_LEFT) {
-        _last_text_def->set_text(line._str);
+      if (_last_text_def->get_align() != TextNode::A_left) {
+        _last_text_def->set_wtext(line._str);
         line._left = _last_text_def->get_left();
         line._left = _last_text_def->get_left();
       }
       }
 
 
-      _last_text_def->set_text(ww_text);
+      _last_text_def->set_wtext(ww_text);
 
 
     } else {
     } else {
       // Only one line.
       // Only one line.
       _ww_lines.clear();
       _ww_lines.clear();
       _ww_lines.push_back(WWLine());
       _ww_lines.push_back(WWLine());
       WWLine &line = _ww_lines.back();
       WWLine &line = _ww_lines.back();
-      line._str = display_text;
+      line._str = display_wtext;
 
 
-      _last_text_def->set_text(display_text);
+      _last_text_def->set_wtext(display_wtext);
       line._left = _last_text_def->get_left();
       line._left = _last_text_def->get_left();
     }
     }
 
 
@@ -804,7 +803,7 @@ update_cursor() {
   if (_cursor_stale || node != _last_text_def) {
   if (_cursor_stale || node != _last_text_def) {
     update_text();
     update_text();
 
 
-    _cursor_position = min(_cursor_position, (int)_text.length());
+    _cursor_position = min(_cursor_position, (int)_wtext.length());
 
 
     // Determine the row and column of the cursor.
     // Determine the row and column of the cursor.
     int row = 0;
     int row = 0;

+ 18 - 5
panda/src/pgui/pgEntry.h

@@ -33,6 +33,14 @@
 // Description : This is a particular kind of PGItem that handles
 // Description : This is a particular kind of PGItem that handles
 //               simple one-line text entries, of the sort where the
 //               simple one-line text entries, of the sort where the
 //               user can type any string.
 //               user can type any string.
+//
+//               A PGEntry does all of its internal manipulation on a
+//               wide string, so it can store the full Unicode
+//               character set.  The interface can support either the
+//               wide string getters and setters, or the normal 8-bit
+//               string getters and setters, which use whatever
+//               encoding method is specified by the associated
+//               TextNode.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA PGEntry : public PGItem {
 class EXPCL_PANDA PGEntry : public PGItem {
 PUBLISHED:
 PUBLISHED:
@@ -66,7 +74,7 @@ PUBLISHED:
   void setup(float width, int num_lines);
   void setup(float width, int num_lines);
 
 
   INLINE void set_text(const string &text);
   INLINE void set_text(const string &text);
-  INLINE const string &get_text() const;
+  INLINE string get_text() const;
 
 
   INLINE void set_cursor_position(int position);
   INLINE void set_cursor_position(int position);
   INLINE int get_cursor_position() const;
   INLINE int get_cursor_position() const;
@@ -106,16 +114,21 @@ PUBLISHED:
   INLINE string get_type_event() const;
   INLINE string get_type_event() const;
   INLINE string get_erase_event() const;
   INLINE string get_erase_event() const;
 
 
+public:
+  INLINE void set_wtext(const wstring &wtext);
+  INLINE const wstring &get_wtext() const;
+
+
 private:
 private:
-  const string &get_display_text();
+  const wstring &get_display_wtext();
   void slot_text_def(int state);
   void slot_text_def(int state);
   void update_text();
   void update_text();
   void update_cursor();
   void update_cursor();
   void show_hide_cursor(bool visible);
   void show_hide_cursor(bool visible);
   void update_state();
   void update_state();
 
 
-  string _text;
-  string _obscured_text;
+  wstring _wtext;
+  wstring _obscured_wtext;
   int _cursor_position;
   int _cursor_position;
   bool _cursor_stale;
   bool _cursor_stale;
   bool _cursor_visible;
   bool _cursor_visible;
@@ -142,7 +155,7 @@ private:
   // to compute the correct cursor position.
   // to compute the correct cursor position.
   class WWLine {
   class WWLine {
   public:
   public:
-    string _str;
+    wstring _str;
     float _left;
     float _left;
   };
   };
   typedef pvector<WWLine> WWLines;
   typedef pvector<WWLine> WWLines;

+ 1 - 1
panda/src/text/config_text.cxx

@@ -56,7 +56,7 @@ ConfigureFn(config_text) {
 
 
 const bool text_flatten = config_text.GetBool("text-flatten", true);
 const bool text_flatten = config_text.GetBool("text-flatten", true);
 const bool text_update_cleared_glyphs = config_text.GetBool("text-update-cleared-glyphs", false);
 const bool text_update_cleared_glyphs = config_text.GetBool("text-update-cleared-glyphs", false);
-const bool text_mipmap = config_text.GetBool("text-mipmap", true);
+const bool text_mipmap = config_text.GetBool("text-mipmap", false);
 const int text_anisotropic_degree = config_text.GetInt("text-anisotropic-degree", 1);
 const int text_anisotropic_degree = config_text.GetInt("text-anisotropic-degree", 1);
 const int text_texture_margin = config_text.GetInt("text-texture-margin", 2);
 const int text_texture_margin = config_text.GetInt("text-texture-margin", 2);
 const float text_poly_margin = config_text.GetFloat("text-poly-margin", 1.0f);
 const float text_poly_margin = config_text.GetFloat("text-poly-margin", 1.0f);

+ 68 - 0
panda/src/text/textNode.I

@@ -1022,6 +1022,19 @@ get_coordinate_system() const {
   return _coordinate_system;
   return _coordinate_system;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::set_text
+//       Access: Published
+//  Description: Changes the text that is displayed under the
+//               TextNode.
+////////////////////////////////////////////////////////////////////
+INLINE void TextNode::
+set_text(const string &text) {
+  _text = text;
+  _wtext = decode_text(text);
+  rebuild(true);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TextNode::clear_text
 //     Function: TextNode::clear_text
 //       Access: Published
 //       Access: Published
@@ -1225,3 +1238,58 @@ INLINE int TextNode::
 get_num_rows() const {
 get_num_rows() const {
   return _num_rows;
   return _num_rows;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::set_wtext
+//       Access: Public
+//  Description: Changes the text that is displayed under the
+//               TextNode, with a wide text.  This automatically sets
+//               the string reported by get_text() to the 8-bit
+//               encoded version of the same string.
+////////////////////////////////////////////////////////////////////
+INLINE void TextNode::
+set_wtext(const wstring &wtext) {
+  _wtext = wtext;
+  _text = encode_wtext(wtext);
+  rebuild(true);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::get_wtext
+//       Access: Public
+//  Description: Returns the text associated with the TextNode, as a
+//               wide-character string.
+////////////////////////////////////////////////////////////////////
+INLINE const wstring &TextNode::
+get_wtext() const {
+  return _wtext;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::calc_width
+//       Access: Published
+//  Description: Returns the width of a line of text of arbitrary
+//               characters.  The line should not include the newline
+//               character.
+////////////////////////////////////////////////////////////////////
+INLINE float TextNode::
+calc_width(const wstring &line) const {
+  nassertr(_font != (TextFont *)NULL, 0.0);
+  return _font->calc_width(line);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TextNode::wordwrap_to
+//       Access: Published
+//  Description: Inserts newlines into the given text at the
+//               appropriate places in order to make each line be the
+//               longest possible line that is not longer than
+//               wordwrap_width (and does not break any words, if
+//               possible).  Returns the new string.
+////////////////////////////////////////////////////////////////////
+wstring TextNode::
+wordwrap_to(const wstring &wtext, float wordwrap_width,
+            bool preserve_trailing_whitespace) const {
+  nassertr(_font != (TextFont *)NULL, wtext);
+  return _font->wordwrap_to(wtext, wordwrap_width, preserve_trailing_whitespace);
+}

+ 2 - 15
panda/src/text/textNode.cxx

@@ -92,19 +92,6 @@ TextNode::
 ~TextNode() {
 ~TextNode() {
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: TextNode::set_text
-//       Access: Published
-//  Description: Changes the text that is displayed under the
-//               TextNode.
-////////////////////////////////////////////////////////////////////
-void TextNode::
-set_text(const string &text) {
-  _text = text;
-  _wtext = decode_text(text);
-  rebuild(true);
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TextNode::wordwrap_to
 //     Function: TextNode::wordwrap_to
 //       Access: Published
 //       Access: Published
@@ -439,10 +426,10 @@ encode_wchar(wchar_t ch) const {
 //               accoding to the current encoding.
 //               accoding to the current encoding.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 string TextNode::
 string TextNode::
-encode_wtext(const wstring &text) const {
+encode_wtext(const wstring &wtext) const {
   string result;
   string result;
 
 
-  for (wstring::const_iterator pi = text.begin(); pi != text.end(); ++pi) {
+  for (wstring::const_iterator pi = wtext.begin(); pi != wtext.end(); ++pi) {
     result += encode_wchar(*pi);
     result += encode_wchar(*pi);
   }
   }
 
 

+ 10 - 2
panda/src/text/textNode.h

@@ -186,7 +186,7 @@ PUBLISHED:
   INLINE void set_coordinate_system(CoordinateSystem cs);
   INLINE void set_coordinate_system(CoordinateSystem cs);
   INLINE CoordinateSystem get_coordinate_system() const;
   INLINE CoordinateSystem get_coordinate_system() const;
 
 
-  void set_text(const string &str);
+  INLINE void set_text(const string &text);
   INLINE void clear_text();
   INLINE void clear_text();
   INLINE bool has_text() const;
   INLINE bool has_text() const;
   INLINE string get_text() const;
   INLINE string get_text() const;
@@ -218,8 +218,16 @@ PUBLISHED:
   PT_Node generate();
   PT_Node generate();
 
 
 public:
 public:
+  // Direct support for wide-character strings.
+  INLINE void set_wtext(const wstring &wtext);
+  INLINE const wstring &get_wtext() const;
+
+  INLINE float calc_width(const wstring &line) const;
+  INLINE wstring wordwrap_to(const wstring &wtext, float wordwrap_width,
+                             bool preserve_trailing_whitespace) const;
+
   string encode_wchar(wchar_t ch) const;
   string encode_wchar(wchar_t ch) const;
-  string encode_wtext(const wstring &text) const;
+  string encode_wtext(const wstring &wtext) const;
   wstring decode_text(const string &text) const;
   wstring decode_text(const string &text) const;
 
 
 private:
 private: