David Rose 24 سال پیش
والد
کامیت
55ae74b3d1

+ 5 - 4
panda/src/pgui/pgEntry.cxx

@@ -361,10 +361,11 @@ keystroke(const MouseWatcherParameter &param, bool background) {
           // 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()) {
             overflow(param);
           } else {
+            _cursor_position = min(_cursor_position, (int)_text.length());
             string new_text = 
               _text.substr(0, _cursor_position) + new_char +
               _text.substr(_cursor_position);
@@ -378,7 +379,7 @@ keystroke(const MouseWatcherParameter &param, bool background) {
             } else {
               measure_text = new_text;
             }
-            
+
             // Check the length.
             bool too_long = false;
             if (_max_width > 0.0f) {
@@ -435,7 +436,7 @@ keystroke(const MouseWatcherParameter &param, bool background) {
                 }
               }
             }
-            
+
             if (too_long) {
               overflow(param);
               
@@ -445,7 +446,7 @@ keystroke(const MouseWatcherParameter &param, bool background) {
                 _obscured_text = measure_text;
               }
               
-              _cursor_position += new_char.size();
+              _cursor_position += new_char.length();
               _cursor_stale = true;
               _text_geom_stale = true;
               type(param);

+ 4 - 1
panda/src/text/dynamicTextFont.cxx

@@ -258,11 +258,14 @@ write(ostream &out, int indent_level) const {
 //               code, as well as an optional scaling parameter that
 //               should be applied to the glyph's geometry and advance
 //               parameters.  Returns true if the glyph exists, false
-//               if it does not.
+//               if it does not.  Even if the return value is false,
+//               the value for glyph might be filled in with a
+//               printable glyph.
 ////////////////////////////////////////////////////////////////////
 bool DynamicTextFont::
 get_glyph(int character, const TextGlyph *&glyph, float &glyph_scale) {
   if (!_is_valid) {
+    glyph = (TextGlyph *)NULL;
     return false;
   }
 

+ 3 - 1
panda/src/text/staticTextFont.cxx

@@ -160,7 +160,9 @@ write(ostream &out, int indent_level) const {
 //               code, as well as an optional scaling parameter that
 //               should be applied to the glyph's geometry and advance
 //               parameters.  Returns true if the glyph exists, false
-//               if it does not.
+//               if it does not.  Even if the return value is false,
+//               the value for glyph might be filled in with a
+//               printable glyph.
 ////////////////////////////////////////////////////////////////////
 bool StaticTextFont::
 get_glyph(int character, const TextGlyph *&glyph, float &glyph_scale) {

+ 19 - 8
panda/src/text/textFont.cxx

@@ -33,6 +33,16 @@ isblank(int ch) {
   return (ch == ' ' || ch == '\t');
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: isspacew
+//  Description: An internal function that works like isspace() but is
+//               safe to call for a wide character.
+////////////////////////////////////////////////////////////////////
+INLINE bool
+isspacew(int ch) {
+  return isascii(ch) && isspace(ch);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: TextFont::Constructor
 //       Access: Public
@@ -69,7 +79,8 @@ calc_width(int character) {
 
   const TextGlyph *glyph;
   float glyph_scale;
-  if (!get_glyph(character, glyph, glyph_scale)) {
+  get_glyph(character, glyph, glyph_scale);
+  if (glyph == (TextGlyph *)NULL) {
     // Unknown character.
     return 0.0f;
   }
@@ -266,7 +277,7 @@ wordwrap_to(const wstring &text, float wordwrap_width,
 
   // Preserve any initial whitespace and newlines.
   float initial_width = 0.0f;
-  while (p < text.length() && isspace(text[p])) {
+  while (p < text.length() && isspacew(text[p])) {
     if (text[p] == '\n') {
       initial_width = 0.0f;
     } else {
@@ -278,7 +289,7 @@ wordwrap_to(const wstring &text, float wordwrap_width,
   bool needs_newline = false;
 
   while (p < text.length()) {
-    nassertr(!isspace(text[p]), wstring());
+    nassertr(!isspacew(text[p]), wstring());
 
     // Scan the next n characters, until the end of the string or an
     // embedded newline character, or we exceed wordwrap_width.
@@ -289,7 +300,7 @@ wordwrap_to(const wstring &text, float wordwrap_width,
 
     float width = initial_width;
     while (q < text.length() && text[q] != '\n') {
-      if (isspace(text[q])) {
+      if (isspacew(text[q])) {
         any_spaces = true;
       }
 
@@ -303,11 +314,11 @@ wordwrap_to(const wstring &text, float wordwrap_width,
         break;
       }
     }
-
+    
     if (overflow && any_spaces) {
       // If we stopped because we exceeded the wordwrap width, then
       // back up to the end of the last complete word.
-      while (q > p && !isspace(text[q])) {
+      while (q > p && !isspacew(text[q])) {
         q--;
       }
     }
@@ -319,7 +330,7 @@ wordwrap_to(const wstring &text, float wordwrap_width,
     }
 
     // Trim off any more blanks on the end.
-    while (q > p && isspace(text[q - 1])) {
+    while (q > p && isspacew(text[q - 1])) {
       q--;
     }
 
@@ -356,7 +367,7 @@ wordwrap_to(const wstring &text, float wordwrap_width,
 
     // Preserve any initial whitespace and newlines.
     initial_width = 0.0f;
-    while (p < text.length() && isspace(text[p])) {
+    while (p < text.length() && isspacew(text[p])) {
       if (text[p] == '\n') {
         initial_width = 0.0f;
       } else {

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

@@ -1078,22 +1078,6 @@ calc_width(const string &line) const {
   return _font->calc_width(decode_text(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.
-////////////////////////////////////////////////////////////////////
-INLINE string TextNode::
-wordwrap_to(const string &text, float wordwrap_width,
-            bool preserve_trailing_whitespace) const {
-  nassertr(_font != (TextFont *)NULL, text);
-  return encode_wtext(_font->wordwrap_to(decode_text(text), wordwrap_width, preserve_trailing_whitespace));
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: TextNode::rebuild
 //       Access: Published

+ 20 - 1
panda/src/text/textNode.cxx

@@ -105,6 +105,25 @@ set_text(const string &text) {
   rebuild(true);
 }
 
+////////////////////////////////////////////////////////////////////
+//     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.
+////////////////////////////////////////////////////////////////////
+string TextNode::
+wordwrap_to(const string &text, float wordwrap_width,
+            bool preserve_trailing_whitespace) const {
+  nassertr(_font != (TextFont *)NULL, text);
+  wstring decoded = decode_text(text);
+  wstring wrapped = 
+    _font->wordwrap_to(decoded, wordwrap_width, preserve_trailing_whitespace);
+  return encode_wtext(wrapped);
+}
+
 
 ////////////////////////////////////////////////////////////////////
 //     Function: TextNode::write
@@ -797,7 +816,7 @@ measure_row(wstring::iterator &si, const wstring::iterator &send) {
 
     if (character == ' ') {
       // A space is a special case.
-      xpos += 0.25f;
+      xpos += _font->get_space_advance();
 
     } else {
       // A printable character.

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

@@ -193,8 +193,8 @@ PUBLISHED:
 
   INLINE float calc_width(int character) const;
   INLINE float calc_width(const string &line) const;
-  INLINE string wordwrap_to(const string &text, float wordwrap_width,
-                            bool preserve_trailing_whitespace) const;
+  string wordwrap_to(const string &text, float wordwrap_width,
+                     bool preserve_trailing_whitespace) const;
 
   virtual void write(ostream &out, int indent_level = 0) const;
 

+ 43 - 31
panda/src/wgldisplay/wglGraphicsWindow.cxx

@@ -1199,7 +1199,9 @@ void wglGraphicsWindow::handle_reshape() {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsWindow::handle_mouse_motion(int x, int y) {
-  _input_devices[0].set_pointer_in_window(x, y);
+  if (!_input_devices.empty()) {
+    _input_devices[0].set_pointer_in_window(x, y);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1209,7 +1211,9 @@ void wglGraphicsWindow::handle_mouse_motion(int x, int y) {
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsWindow::handle_mouse_entry(int state) {
   if (state == MOUSE_EXITED) {
-    _input_devices[0].set_pointer_out_of_window();
+    if (!_input_devices.empty()) {
+      _input_devices[0].set_pointer_out_of_window();
+    }
   }
 }
 
@@ -1220,9 +1224,11 @@ void wglGraphicsWindow::handle_mouse_entry(int state) {
 ////////////////////////////////////////////////////////////////////
 void wglGraphicsWindow::
 handle_keypress(ButtonHandle key, int x, int y) {
-  _input_devices[0].set_pointer_in_window(x, y);
-  if (key != ButtonHandle::none()) {
-    _input_devices[0].button_down(key);
+  if (!_input_devices.empty()) {
+    _input_devices[0].set_pointer_in_window(x, y);
+    if (key != ButtonHandle::none()) {
+      _input_devices[0].button_down(key);
+    }
   }
 }
 
@@ -1234,7 +1240,9 @@ handle_keypress(ButtonHandle key, int x, int y) {
 void wglGraphicsWindow::
 handle_keyrelease(ButtonHandle key) {
   if (key != ButtonHandle::none()) {
-    _input_devices[0].button_up(key);
+    if (!_input_devices.empty()) {
+      _input_devices[0].button_up(key);
+    }
   }
 }
 
@@ -1647,31 +1655,35 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
 
     case WM_IME_COMPOSITION:
       if (lparam & GCS_RESULTSTR) {
-        HIMC hIMC = ImmGetContext(hwnd);
-        nassertr(hIMC != 0, 0);
-
-        static const int max_ime_result = 128;
-        static char ime_result[max_ime_result];
-
-        // There's a rumor that ImmGetCompositionStringW() doesn't
-        // work for Win95 or Win98; for these OS's we must use
-        // ImmGetCompositionStringA().  How does this affect the
-        // returning of multibyte characters?
-        DWORD result_size =
-          ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
-                                   ime_result, max_ime_result);
-        ImmReleaseContext(hwnd, hIMC);
-
-        // Add this string into the text buffer of the application.
-
-        // ImmGetCompositionStringW() returns a string, but it's
-        // filled in with wstring data: every two characters defines a
-        // 16-bit unicode char.  The docs aren't clear on the
-        // endianness of this.  I guess it's safe to assume all Win32
-        // machines are little-endian.
-        for (DWORD i = 0; i < result_size; i += 2) {
-          int result = ((int)ime_result[i + 1] << 8) | ime_result[i];
-          _input_devices[0].keystroke(result);
+        if (!_input_devices.empty()) {
+          HIMC hIMC = ImmGetContext(hwnd);
+          nassertr(hIMC != 0, 0);
+          
+          static const int max_ime_result = 128;
+          static char ime_result[max_ime_result];
+          
+          // There's a rumor that ImmGetCompositionStringW() doesn't
+          // work for Win95 or Win98; for these OS's we must use
+          // ImmGetCompositionStringA().  How does this affect the
+          // returning of multibyte characters?
+          DWORD result_size =
+            ImmGetCompositionStringW(hIMC, GCS_RESULTSTR,
+                                     ime_result, max_ime_result);
+          ImmReleaseContext(hwnd, hIMC);
+          
+          // Add this string into the text buffer of the application.
+          
+          // ImmGetCompositionStringW() returns a string, but it's
+          // filled in with wstring data: every two characters defines a
+          // 16-bit unicode char.  The docs aren't clear on the
+          // endianness of this.  I guess it's safe to assume all Win32
+          // machines are little-endian.
+          for (DWORD i = 0; i < result_size; i += 2) {
+            int result = 
+              ((int)(unsigned char)ime_result[i + 1] << 8) | 
+              (unsigned char)ime_result[i];
+            _input_devices[0].keystroke(result);
+          }
         }
         return 0;
       }