Back to index

nux  3.0.0
KeyboardHandler.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "Nux.h"
00024 #include "KeyboardHandler.h"
00025 #include "Utils.h"
00026 #include "NuxGraphics/GraphicsEngine.h"
00027 #include "NuxCore/Win32Dialogs/NWin32Clipboard.h"
00028 
00029 namespace nux
00030 {
00031 
00032   int BaseKeyboardHandler::s_jump_offset_at_borders = 60;
00033   int BaseKeyboardHandler::s_cursor_width = 4;
00034 
00035   BaseKeyboardHandler::BaseKeyboardHandler()
00036   {
00037     m_text_positionx            = 0;
00038     m_text_positiony            = 0;
00039     m_previous_cursor_position  = 0;
00040     m_clip_region               = Rect(0, 0, 100, 20);
00041     m_KeyType                   = eAlphaNumeric;
00042     m_first_visible_char        = 0;
00043     m_mouse_drag                = false;
00044     m_mouse_inside_text_area    = true;
00045     m_entering_focus            = false;
00046     m_Font                      = GetSysFont();
00047 
00048     m_caret = m_selection_start = 0;
00049     m_insert_mode = true;
00050   }
00051 
00052   BaseKeyboardHandler::~BaseKeyboardHandler()
00053   {
00054   }
00055 
00056   void BaseKeyboardHandler::DeleteSelectionText()
00057   {
00058     int nFirst = Min(m_caret, m_selection_start);
00059     int nLast = Max(m_caret, m_selection_start);
00060     // Update caret and selection
00061     PlaceCaret(nFirst);
00062     m_selection_start = m_caret;
00063 
00064     // Remove the characters
00065     for (int i = nFirst; i < nLast; ++i)
00066       m_textline.Erase(nFirst, 1);
00067   }
00068 
00069   void BaseKeyboardHandler::InsertChar(unsigned int character)
00070   {
00071 
00072   }
00073 
00074   void BaseKeyboardHandler::ClearText()
00075   {
00076     m_text_positionx = 0;
00077     m_text_positiony = 0;
00078     m_caret = 0;
00079 
00080     m_previous_cursor_position = 0;
00081     m_textline.Clear();
00082   }
00083 
00084   void BaseKeyboardHandler::PlaceCaret(unsigned int nCP)
00085   {
00086     nuxAssert((nCP >= 0) && (nCP <= (unsigned int) m_textline.Length()));
00087     m_previous_cursor_position = m_caret;
00088     m_caret = nCP;
00089   }
00090 
00091   unsigned int BaseKeyboardHandler::NextWordPosition(unsigned int cp)
00092   {
00093     unsigned int num_char = (unsigned int) m_textline.Length();
00094 
00095     if (cp == num_char)
00096       return cp;
00097 
00098     unsigned int c = cp + 1;
00099 
00100     while (c < num_char - 1)
00101     {
00102       if (( m_textline[c] == char(' ')) && (m_textline[c+1] != char(' ')))
00103         return c + 1;
00104 
00105       c++;
00106     }
00107 
00108     return num_char;
00109   }
00110 
00111   unsigned int BaseKeyboardHandler::PrevWordPosition(unsigned int cp)
00112   {
00113     if (cp == 0)
00114       return 0;
00115 
00116     unsigned int c = cp - 1;
00117 
00118     while (c > 1)
00119     {
00120       if (( m_textline[c] != char(' ')) && (m_textline[c-1] == char(' ')))
00121         return c;
00122 
00123       c--;
00124     }
00125 
00126     return 0;
00127   }
00128 
00129   void BaseKeyboardHandler::MouseDown(int x, int y)
00130   {
00131     ResolveCaretPosition(x, y);
00132     m_mouse_drag = true;
00133     m_mouse_inside_text_area = true;
00134     m_entering_focus = false;
00135   }
00136 
00137   void BaseKeyboardHandler::MouseUp(int x, int y)
00138   {
00139     m_mouse_drag = false;
00140     m_entering_focus = false;
00141   }
00142 
00143   void BaseKeyboardHandler::MouseDrag(int x, int y)
00144   {
00145     if (m_entering_focus)
00146       return;
00147 
00148     ResolveCaretPosition(x, y);
00149     m_mouse_inside_text_area = true;
00150   }
00151 
00152   void BaseKeyboardHandler::EnterFocus()
00153   {
00154     m_entering_focus = true;
00155   }
00156 
00157   void BaseKeyboardHandler::ResolveCaretPosition(int x, int y)
00158   {
00159     if (m_entering_focus)
00160       return;
00161 
00162     if (m_textline.Length() == 0)
00163       return;
00164 
00165     unsigned int StrLength = (unsigned int) m_textline.Length();
00166     int total = m_text_positionx;
00167     unsigned int nCP = StrLength;
00168 
00169     for (unsigned int i = 0; i < StrLength; i++)
00170     {
00171       unsigned int cw0 = GetFont()->GetCharWidth(m_textline[i]);
00172       unsigned int cw1 = 0;
00173 
00174       if (i+1 < StrLength)
00175       {
00176         cw1 = GetFont()->GetCharWidth(m_textline[i+1]);
00177       }
00178 
00179       {
00180         if (total == x)
00181         {
00182           nCP = i;
00183           break;
00184         }
00185         else if (x < total + (int) cw0 / 2)
00186         {
00187           nCP = i;
00188           break;
00189         }
00190         else if (x < total + (int) cw1 / 2)
00191         {
00192           // I don't quite understand why we need this???
00193           nCP = i + 1;
00194           break;
00195         }
00196       }
00197       total += cw0;
00198     }
00199 
00200     PlaceCaret(nCP);
00201 
00202     if (!m_mouse_drag)
00203     {
00204       m_selection_start = m_caret;
00205     }
00206   }
00207 
00208   void BaseKeyboardHandler::CaretAutoScroll(int x, int y, Geometry geo)
00209   {
00210     if (m_entering_focus)
00211       return;
00212 
00213     if (m_textline.Length() == 0)
00214       return;
00215 
00216     int StrLength = (int) m_textline.Length();
00217 
00218     //nuxDebugMsg("[BaseKeyboardHandler::ResolveCaretPosition]");
00219     if (x < geo.x)
00220     {
00221       if (m_mouse_inside_text_area)
00222       {
00223         while (m_caret && (GetFont()->GetCharStringWidth(m_textline.GetTCharPtr(), m_caret) + m_text_positionx > 0))
00224         {
00225           --m_caret;
00226           //nuxDebugMsg("Group Add: %c", m_textline[m_caret]);
00227         }
00228 
00229         m_mouse_inside_text_area = false;
00230       }
00231       else if (m_caret)
00232       {
00233         --m_caret;
00234         //nuxDebugMsg("Add Char: %c", m_textline[m_caret]);
00235       }
00236       else
00237       {
00238         m_caret = 0;
00239       }
00240     }
00241     else if (x > geo.x + geo.GetWidth())
00242     {
00243       if (m_mouse_inside_text_area)
00244       {
00245         while ((m_caret != StrLength) && (GetFont()->GetCharStringWidth(m_textline.GetTCharPtr(), m_caret) + m_text_positionx < geo.GetWidth()))
00246         {
00247           ++m_caret;
00248           //nuxDebugMsg("Group Add: %c", m_textline[m_caret-1]);
00249         }
00250 
00251         m_mouse_inside_text_area = false;
00252       }
00253       else if (m_caret < StrLength)
00254       {
00255         ++m_caret;
00256         //nuxDebugMsg("Group Add: %c", m_textline[m_caret-1]);
00257       }
00258       else
00259       {
00260         m_caret = StrLength;
00261       }
00262     }
00263 
00264     AdjustCursorAndTextPosition();
00265   }
00266 
00267   long BaseKeyboardHandler::ProcessKey(
00268     unsigned long    eventType    /*event type*/,
00269     unsigned long    keysym       /*event keysym*/,
00270     unsigned long    state        /*event state*/,
00271     char      character    /*character*/,
00272     const Geometry &g)
00273   {
00274     //if(event.event_type != I_AsciiKey && event.event_type != I_KeyPress && event.event_type != I_KeyRelease)
00275     if (eventType != NUX_KEYDOWN)
00276       return 0;
00277 
00278     m_need_redraw = true;
00279     //unsigned key = event.ascii_code;
00280     unsigned key = 0;
00281 
00282     if (character != 0)
00283       key = character;
00284 
00285     long virtual_code = keysym;
00286 
00287     if (key != 0)
00288     {
00289       switch(m_KeyType)
00290       {
00291         case eDecimalNumber:
00292         {
00293           // Check if Key code is in ".0123456789";
00294           // Be careful because WM_KEYDOWN and WM_KEYUP send a key value
00295           // that gets here. If key pad 0 is press/released, WM_KEYDOWN/WM_KEYUP will send key = key_kp0.
00296           // It is WM_CHAR who send key = 0x30 = '0'. Therefore, do not use strchr(".0123456789", key) to test
00297           // if key is a digit character. When using strchr(".0123456789", key_kp0) we get a positive result
00298           // and the result is unexpected.
00299           if ((key >= char('0') && key <= char('9')) || (key == char('.')) || (key == char('-')) || (key == char('+')))
00300           {
00301             if ( m_caret != m_selection_start )
00302             {
00303               DeleteSelectionText();
00304             }
00305 
00306             // '-' and '+' can only be at position 0 of the number
00307             if ((key == char('-')) || (key == char('+')))
00308             {
00309               if ((m_caret == 0) && (m_textline[0] != char('+')) && (m_textline[0] != char('-')))
00310               {
00311                 // If we are in overwrite mode and there is already
00312                 // a char at the caret's position, simply replace it.
00313                 // Otherwise, we insert the char as normal.
00314                 if ( !m_insert_mode && m_caret < (int) m_textline.Length())
00315                 {
00316                   m_textline[m_caret] = key;
00317                   PlaceCaret(m_caret + 1 );
00318                   m_selection_start = m_caret;
00319                 }
00320                 else
00321                 {
00322                   // Insert the char
00323                   if ( m_caret <= (int) m_textline.Length())
00324                   {
00325                     m_textline.Insert(m_caret, 1, key);
00326                     PlaceCaret(m_caret + 1 );
00327                     m_selection_start = m_caret;
00328                   }
00329                 }
00330               }
00331             }
00332             else
00333             {
00334               // If we are in overwrite mode and there is already
00335               // a char at the caret's position, simply replace it.
00336               // Otherwise, we insert the char as normal.
00337               if ( !m_insert_mode && m_caret < (int) m_textline.Length())
00338               {
00339                 m_textline[m_caret] = key;
00340                 PlaceCaret(m_caret + 1 );
00341                 m_selection_start = m_caret;
00342               }
00343               else
00344               {
00345                 // Insert the char
00346                 if ( m_caret <= (int) m_textline.Length())
00347                 {
00348                   m_textline.Insert(m_caret, 1, key);
00349                   PlaceCaret(m_caret + 1 );
00350                   m_selection_start = m_caret;
00351                 }
00352               }
00353             }
00354           }
00355 
00356           break;
00357         }
00358         case eIntegerNumber:
00359         {
00360           // Check if Key code is in "0123456789";
00361           if ((key >= char('0') && key <= char('9')) || (key == char('-')) || (key == char('+')))
00362           {
00363             if ( m_caret != m_selection_start )
00364             {
00365               DeleteSelectionText();
00366             }
00367 
00368             // '-' and '+' can only be at position 0 of the number
00369             if ((key == char('-')) || (key == char('+')))
00370             {
00371               // If we are in overwrite mode and there is already
00372               // a char at the caret's position, simply replace it.
00373               // Otherwise, we insert the char as normal.
00374               if (!m_insert_mode && (m_caret < (int) m_textline.Length()))
00375               {
00376                 m_textline[m_caret] = key;
00377                 PlaceCaret(m_caret + 1 );
00378                 m_selection_start = m_caret;
00379               }
00380               else
00381               {
00382                 // Insert the char
00383                 if ( m_caret <= (int) m_textline.Length())
00384                 {
00385                   m_textline.Insert(m_caret, 1, key);
00386                   PlaceCaret(m_caret + 1 );
00387                   m_selection_start = m_caret;
00388                 }
00389               }
00390             }
00391             else
00392             {
00393               // If we are in overwrite mode and there is already
00394               // a char at the caret's position, simply replace it.
00395               // Otherwise, we insert the char as normal.
00396               if (!m_insert_mode && (m_caret < (int) m_textline.Length()))
00397               {
00398                 m_textline[m_caret] = key;
00399                 PlaceCaret(m_caret + 1 );
00400                 m_selection_start = m_caret;
00401               }
00402               else
00403               {
00404                 // Insert the char
00405                 if (m_caret <= (int) m_textline.Length())
00406                 {
00407                   m_textline.Insert(m_caret, 1, key);
00408                   PlaceCaret(m_caret + 1 );
00409                   m_selection_start = m_caret;
00410                 }
00411               }
00412             }
00413           }
00414 
00415           break;
00416         }
00417 
00418         case eHexadecimalNumber:
00419         {
00420           if ((key >= char('0') && key <= char('9')) || (key >= char('a') && key <= char('f')) || (key >= char('A') && key <= char('F')) || (key == char('-')) || (key == char('+')))
00421             //if(strchr("0123456789abcdefABCDEF", key))
00422           {
00423             if (m_caret != m_selection_start)
00424             {
00425               DeleteSelectionText();
00426             }
00427 
00428             // If we are in overwrite mode and there is already
00429             // a char at the caret's position, simply replace it.
00430             // Otherwise, we insert the char as normal.
00431             if (!m_insert_mode && (m_caret < (int) m_textline.Length()))
00432             {
00433               m_textline[m_caret] = key;
00434               PlaceCaret(m_caret + 1 );
00435               m_selection_start = m_caret;
00436             }
00437             else
00438             {
00439               // Insert the char
00440               if (m_caret <= (int) m_textline.Length())
00441               {
00442                 m_textline.Insert(m_caret, 1, key);
00443                 PlaceCaret(m_caret + 1 );
00444                 m_selection_start = m_caret;
00445               }
00446             }
00447 
00448           }
00449 
00450           break;
00451         }
00452 
00453         case eBinaryNumber:
00454         {
00455           //if(strchr("01", key))
00456           if ((key >= char('0') && key <= char('1')))
00457           {
00458             if ( m_caret != m_selection_start )
00459             {
00460               DeleteSelectionText();
00461             }
00462 
00463             // If we are in overwrite mode and there is already
00464             // a char at the caret's position, simply replace it.
00465             // Otherwise, we insert the char as normal.
00466             if (!m_insert_mode && (m_caret < (int) m_textline.Length()))
00467             {
00468               m_textline[m_caret] = key;
00469               PlaceCaret(m_caret + 1 );
00470               m_selection_start = m_caret;
00471             }
00472             else
00473             {
00474               // Insert the char
00475               if (m_caret <= (int) m_textline.Length())
00476               {
00477                 m_textline.Insert(m_caret, 1, key);
00478                 PlaceCaret(m_caret + 1 );
00479                 m_selection_start = m_caret;
00480               }
00481             }
00482           }
00483 
00484           break;
00485         }
00486 
00487         case eAlphaNumeric:
00488         default:
00489         {
00490           if (key > 0x1F && key < 0x7f)
00491           {
00492             if (m_caret != m_selection_start)
00493             {
00494               DeleteSelectionText();
00495             }
00496 
00497             // If we are in overwrite mode and there is already
00498             // a char at the caret's position, simply replace it.
00499             // Otherwise, we insert the char as normal.
00500             if (!m_insert_mode && (m_caret < (int) m_textline.Length()))
00501             {
00502               m_textline[m_caret] = key;
00503               PlaceCaret(m_caret + 1 );
00504               m_selection_start = m_caret;
00505             }
00506             else
00507             {
00508               // Insert the char
00509               if (m_caret <= (int) m_textline.Length())
00510               {
00511                 m_textline.Insert(m_caret, 1, key);
00512                 PlaceCaret(m_caret + 1 );
00513                 m_selection_start = m_caret;
00514               }
00515             }
00516 
00517           }
00518 
00519           break;
00520         }
00521       }
00522     }
00523 
00524     // CTRL+C
00525     if ((virtual_code == NUX_VK_C) && (state & NUX_STATE_CTRL))
00526     {
00527       NString s = GetSelectedText();
00528 #if defined(NUX_OS_WINDOWS)
00529       inlCopyTextToClipboard(s.GetTCharPtr());
00530 #endif
00531     }
00532 
00533     // CTRL+V
00534     if ((virtual_code == NUX_VK_V) && (state & NUX_STATE_CTRL))
00535     {
00536 #if defined(NUX_OS_WINDOWS)
00537       NString s = inlReadTextToClipboard();
00538 #elif defined(NUX_OS_LINUX)
00539       NString s = "Paste not implemented yet";
00540 #endif
00541       unsigned int start = GetTextSelectionStart();
00542       unsigned int end = GetTextSelectionEnd();
00543       m_textline.Replace(start, end - start, s.m_string);
00544 
00545       m_caret = start + (unsigned int) s.Length();
00546       UnselectAllText();
00547     }
00548 
00549     if ((virtual_code == NUX_VK_ESCAPE))
00550     {
00551       // If Text is selected, Unselect
00552       UnselectAllText();
00553     }
00554 
00555     if ((virtual_code == NUX_VK_ENTER))
00556     {
00557       SelectAllText();
00558     }
00559 
00560     if (virtual_code == NUX_VK_BACKSPACE)
00561     {
00562       if ( m_caret != m_selection_start )
00563       {
00564         DeleteSelectionText();
00565       }
00566       else
00567       {
00568         // Deleting one character
00569         if ( m_caret > 0 )
00570         {
00571           m_textline.Erase(m_caret - 1, 1);
00572           PlaceCaret(m_caret - 1 );
00573 
00574           m_selection_start = m_caret;
00575         }
00576       }
00577     }
00578     else if (virtual_code == NUX_VK_DELETE)
00579     {
00580       // Check if there is a text selection.
00581       if ( m_caret != m_selection_start )
00582       {
00583         DeleteSelectionText();
00584       }
00585       else
00586       {
00587         // Deleting one character
00588         if (m_caret < (int) m_textline.Length())
00589         {
00590           m_textline.Erase(m_caret, 1);
00591         }
00592       }
00593     }
00594     else if (virtual_code == NUX_VK_LEFT)
00595     {
00596       if (IsTextSelected() && ((state & NUX_STATE_SHIFT) == 0))
00597       {
00598         //m_caret = Min(m_caret, m_selection_start);
00599         if (m_caret)
00600           --m_caret;
00601 
00602         UnselectAllText();
00603       }
00604       else
00605       {
00606         if ( state & NUX_STATE_CTRL )
00607         {
00608           // Control is down. Move the caret to a new item
00609           // instead of a character.
00610           m_caret = PrevWordPosition( m_caret);
00611           PlaceCaret(m_caret );
00612         }
00613         else if ( m_caret > 0 )
00614           PlaceCaret(m_caret - 1 );
00615 
00616         if ((state & NUX_STATE_SHIFT) == 0)
00617         {
00618           // Shift is not down. Update selection
00619           // start along with the caret.
00620           m_selection_start = m_caret;
00621         }
00622       }
00623     }
00624     else if (virtual_code == NUX_VK_RIGHT)
00625     {
00626       if (IsTextSelected() && ((state & NUX_STATE_SHIFT) == 0))
00627       {
00628         m_caret = Max(m_caret, m_selection_start);
00629         UnselectAllText();
00630       }
00631       else
00632       {
00633         if ( state & NUX_STATE_CTRL)
00634         {
00635           // Control is down. Move the caret to a new item
00636           // instead of a character.
00637           m_caret = NextWordPosition( m_caret);
00638           PlaceCaret(m_caret );
00639         }
00640         else if (m_caret < (int) m_textline.Length())
00641           PlaceCaret(m_caret + 1 );
00642 
00643         if ((state & NUX_STATE_SHIFT) == 0)
00644         {
00645           // Shift is not down. Update selection
00646           // start along with the caret.
00647           m_selection_start = m_caret;
00648         }
00649       }
00650     }
00651     else if (virtual_code == NUX_VK_HOME)
00652     {
00653       if ((state & NUX_STATE_SHIFT) == 0)
00654       {
00655         PlaceCaret(0);
00656         // Shift is not down. Update selection
00657         // start along with the caret.
00658         m_selection_start = m_caret;
00659       }
00660       else
00661       {
00662         PlaceCaret(0 );
00663       }
00664     }
00665     else if (virtual_code == NUX_VK_END)
00666     {
00667       if ((state & NUX_STATE_SHIFT) == 0)
00668       {
00669         PlaceCaret((unsigned int) m_textline.Length());
00670         // Shift is not down. Update selection
00671         // start along with the caret.
00672         m_selection_start = m_caret;
00673       }
00674       else
00675       {
00676         PlaceCaret((unsigned int) m_textline.Length());
00677       }
00678     }
00679     else if (virtual_code == NUX_VK_ESCAPE)
00680     {
00681       return virtual_code;
00682     }
00683     else if ((virtual_code == NUX_VK_ENTER))
00684     {
00685       return virtual_code;
00686     }
00687     else
00688     {
00689       m_need_redraw = false;
00690     }
00691 
00692     if (virtual_code == NUX_VK_HOME)
00693     {
00694       m_text_positionx = 0;
00695     }
00696     else if (virtual_code == NUX_VK_END)
00697     {
00698       unsigned int str_width = GetFont()->GetStringWidth(m_textline.GetTCharPtr());
00699 
00700       if (str_width + s_cursor_width > (unsigned int) m_clip_region.GetWidth())
00701         m_text_positionx = m_clip_region.GetWidth() - (str_width + s_cursor_width);
00702       else
00703         m_text_positionx = 0;
00704     }
00705     else if (m_textline.Length() != 0)
00706     {
00707       AdjustCursorAndTextPosition();
00708       m_need_redraw = true;
00709     }
00710     else if (m_textline.Length() == 0)
00711     {
00712       ClearText();
00713       m_need_redraw = true;
00714     }
00715 
00716 
00717     return virtual_code;
00718   }
00719 
00720   void BaseKeyboardHandler::AdjustCursorAndTextPosition()
00721   {
00722     int str_width = GetFont()->GetStringWidth(m_textline.GetTCharPtr());
00723     NString temp0;
00724 
00725     if (m_caret > 0)
00726       temp0 = m_textline.GetSubString(0, m_caret - 1).GetTStringRef();
00727     else
00728       temp0 = "";
00729 
00730     //      0          1         2
00731     //      01234567|8901234567890123456789
00732     //      abcdefgh|ijklmn
00733     //
00734     //      Caret pos = 8
00735     //      temp0 = "abcdefg"
00736     //      temp1 = "abcdefgh"
00737     //      temp2 = "abcdefghi"
00738 
00739     NString temp1 = m_textline.GetSubString(0, m_caret).GetTStringRef();
00740     NString temp2 = m_textline.GetSubString(0, m_caret + 1).GetTStringRef();
00741     int str_width0 = GetFont()->GetStringWidth(temp0);
00742     int str_width1 = GetFont()->GetStringWidth(temp1);
00743     int str_width2 = GetFont()->GetStringWidth(temp2);
00744 
00745 
00746     if ((m_text_positionx + str_width1 + s_cursor_width) > m_clip_region.GetWidth())
00747     {
00748       // Hitting the end of the text box
00749       if (m_caret == (int) m_textline.Length())
00750       {
00751         m_text_positionx = - (str_width + (int) s_cursor_width - m_clip_region.GetWidth());
00752       }
00753       else
00754       {
00755         int PreviousCharWidth = str_width1 - str_width0;
00756         int Offset = Min<int> (s_jump_offset_at_borders, str_width + s_cursor_width - str_width1);
00757 
00758         while (Offset > m_clip_region.GetWidth())
00759         {
00760           Offset /= 2;
00761         }
00762 
00763         if (Offset < PreviousCharWidth)
00764           Offset = PreviousCharWidth;
00765 
00766         m_text_positionx -= Offset;
00767 
00768         if (m_text_positionx + str_width + s_cursor_width < (int) m_clip_region.GetWidth())
00769         {
00770           m_text_positionx = - (str_width + (int) s_cursor_width - m_clip_region.GetWidth());
00771         }
00772       }
00773     }
00774     else if ((m_text_positionx + str_width1) <= 0)
00775     {
00776       // Hitting the start of the text box
00777       if (m_caret == 0)
00778       {
00779         m_text_positionx = 0;
00780       }
00781       else
00782       {
00783         int NextCharWidth = str_width2 - str_width1;
00784         int Offset = Min<int> (s_jump_offset_at_borders, str_width1);
00785 
00786         while (Offset > m_clip_region.GetWidth())
00787         {
00788           Offset /= 2;
00789         }
00790 
00791         if (Offset < NextCharWidth)
00792           Offset = NextCharWidth;
00793 
00794         if (Offset > str_width1)
00795         {
00796           m_text_positionx = 0;
00797           return;
00798         }
00799 
00800         m_text_positionx += Offset;
00801 
00802         if (m_text_positionx > 0)
00803         {
00804           m_text_positionx = 0;
00805         }
00806       }
00807     }
00808   }
00809 
00810   void BaseKeyboardHandler::MoveCursorAtStart()
00811   {
00812     m_previous_cursor_position = m_caret;
00813     m_caret  = 0;
00814   }
00815   void BaseKeyboardHandler::MoveCursorAtEnd()
00816   {
00817     unsigned int StrLength = ( unsigned int) m_textline.Length();
00818     m_previous_cursor_position = m_caret;
00819     m_caret = StrLength;
00820   }
00821 
00822   void BaseKeyboardHandler::SetKeyEntryType(BaseKeyboardHandler::eKeyEntryType keytype)
00823   {
00824     m_KeyType = keytype;
00825   }
00826 
00827   BaseKeyboardHandler::eKeyEntryType BaseKeyboardHandler::GetKeyEntryType()
00828   {
00829     return m_KeyType;
00830   }
00831 
00832   void BaseKeyboardHandler::SetText(const char *str)
00833   {
00834     m_textline = str;
00835     // Every time we set the text, we reposition the cursor at the beginning of the text,
00836     // and the text position is set to zero with regard to the start of the geometry area.
00837     MoveCursorAtStart();
00838     m_selection_start = Min<int> (m_selection_start, (int) StringLength(str));
00839     m_caret = Min<int> (m_caret, (int) StringLength(str));
00840 
00841     if (m_caret < m_selection_start)
00842       m_selection_start = Max<int> (m_selection_start, (int) StringLength(str));
00843     else if (m_caret > m_selection_start)
00844       m_caret = Max<int> (m_caret, (int) StringLength(str));
00845 
00846     m_text_positionx = 0;
00847   }
00848 
00849   void BaseKeyboardHandler::SetText(const tstring &s)
00850   {
00851     SetText(s.c_str());
00852   }
00853 
00854   void BaseKeyboardHandler::SetText(const NString &s)
00855   {
00856     SetText(s.GetTCharPtr());
00857   }
00858 
00859   void BaseKeyboardHandler::SetClipRegion(const Geometry &g)
00860   {
00861     m_clip_region = g;
00862   }
00863 
00864   void BaseKeyboardHandler::GetTextSelection(int *start, int *end) const
00865   {
00866     *start = Min(m_selection_start, m_caret);
00867     *end = Max(m_selection_start, m_caret);
00868   }
00869 
00870   int BaseKeyboardHandler::GetTextSelectionStart() const
00871   {
00872     return Min(m_selection_start, m_caret);
00873   }
00874 
00875   int BaseKeyboardHandler::GetTextSelectionEnd() const
00876   {
00877     return Max(m_selection_start, m_caret);
00878   }
00879 
00880   void BaseKeyboardHandler::SelectAllText()
00881   {
00882     m_selection_start = 0;
00883     m_caret = (unsigned int) m_textline.Length();
00884     AdjustCursorAndTextPosition();
00885   }
00886 
00887   void BaseKeyboardHandler::UnselectAllText()
00888   {
00889     m_selection_start = m_caret;
00890   }
00891 
00892   NString BaseKeyboardHandler::GetSelectedText() const
00893   {
00894     if (m_selection_start == m_caret)
00895     {
00896       return NString("");
00897     }
00898     else
00899     {
00900       NString s = m_textline.GetSubString(GetTextSelectionStart(), GetTextSelectionEnd() - GetTextSelectionStart()).GetTStringRef();
00901       return s;
00902     }
00903   }
00904 
00905   bool BaseKeyboardHandler::IsTextSelected()
00906   {
00907     if (m_caret != m_selection_start)
00908       return true;
00909 
00910     return false;
00911   }
00912 
00913   void BaseKeyboardHandler::SetFont(ObjectPtr<FontTexture> Font)
00914   {
00915     m_Font = Font;
00916   }
00917 
00918   ObjectPtr<FontTexture> BaseKeyboardHandler::GetFont() const
00919   {
00920     return m_Font;
00921   }
00922 
00923 }