This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

Changeset 9646 for ps


Ignore:
Timestamp:
06/23/11 12:12:43 (14 years ago)
Author:
Jan Wassenberg
Message:

add support for selection and deletion of entire words in text controls (ctrl+backspace/delete/left/right) based on patch by Chakakhan/kenny (thanks!)
also refactored wclipboard
closes #511

Location:
ps/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • ps/trunk/binaries/data/config/default.cfg

    r9443 r9646  
    130130hotkey.console.copy = "Ctrl+C"              ; Copy from console to clipboard
    131131hotkey.console.paste = "Ctrl+V"             ; Paste clipboard to console
     132hotkey.console.cut = "Ctrl+X"               ; Cut the selected text and copy it to the clipboard
    132133
    133134; > ENTITY SELECTION
     
    187188hotkey.chat = Return                        ; Toggle chat window
    188189
     190; > GUI TEXTBOX HOTKEYS
     191hotkey.text.delete.word.left = "Ctrl+Backspace"    ; Used in text input boxes to delete word to the left of cursor
     192hotkey.text.delete.word.right = "Ctrl+Del"         ; Used in text input boxes to delete word to the right of cursor
     193hotkey.text.move.word.left = "Ctrl+LeftArrow"      ; Move cursor to start of word to the left of cursor
     194hotkey.text.move.word.right = "Ctrl+RightArrow"    ; Move cursor to start of word to the left of cursor
     195
    189196; > PROFILER
    190197hotkey.profile.toggle = "F11"               ; Enable/disable real-time profiler
  • ps/trunk/source/gui/CInput.cpp

    r9362 r9646  
    3535#include "ps/Globals.h"
    3636
     37#include <sstream>
    3738
    3839//-------------------------------------------------------------------
     
    7172    ENSURE(m_iBufferPos != -1);
    7273
    73     // Since the GUI framework doesn't handle to set settings
    74     //  in Unicode (CStrW), we'll simply retrieve the actual
    75     //  pointer and edit that.
    76     CStrW *pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
    77 
    7874    if (ev->ev.type == SDL_HOTKEYDOWN)
    7975    {
    80         std::string hotkey = static_cast<const char*>(ev->ev.user.data1);
    81         if (hotkey == "console.paste")
    82         {
    83             wchar_t* text = sys_clipboard_get();
    84             if (text)
    85             {
    86                 if (m_iBufferPos == (int)pCaption->length())
    87                     *pCaption += text;
    88                 else
    89                     *pCaption = pCaption->Left(m_iBufferPos) + text +
    90                     pCaption->Right((long) pCaption->length()-m_iBufferPos);
    91 
    92                 UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1);
    93 
    94                 m_iBufferPos += (int)wcslen(text);
    95 
    96                 sys_clipboard_free(text);
    97             }
    98 
    99             return IN_HANDLED;
    100         }
     76        return(ManuallyHandleHotkeyEvent(ev));
    10177    }
    10278    else if (ev->ev.type == SDL_KEYDOWN)
    10379    {
     80        // Since the GUI framework doesn't handle to set settings
     81        //  in Unicode (CStrW), we'll simply retrieve the actual
     82        //  pointer and edit that.
     83        CStrW *pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     84        bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT];
     85
    10486        int szChar = ev->ev.key.keysym.sym;
    10587        wchar_t cooked = (wchar_t)ev->ev.key.keysym.unicode;
     
    10789        switch (szChar)
    10890        {
    109             case '\t':
     91            case SDLK_TAB: // '\t'
    11092                /* Auto Complete */
    11193                // TODO Gee: (2004-09-07) What to do with tab?
    11294                break;
    11395
    114             case '\b':
    115                 m_WantedX=0.f;
     96            case SDLK_BACKSPACE: // '\b'
     97                m_WantedX=0.0f;
    11698
    11799                if (SelectingText())
     
    121103                    m_iBufferPos_Tail = -1;
    122104
    123                     if (pCaption->empty() ||
    124                         m_iBufferPos == 0)
     105                    if (pCaption->empty() || m_iBufferPos == 0)
     106                    {
    125107                        break;
    126 
    127                     if (m_iBufferPos == (int)pCaption->length())
    128                         *pCaption = pCaption->Left( (long) pCaption->length()-1);
     108                    }
    129109                    else
    130                         *pCaption = pCaption->Left( m_iBufferPos-1 ) +
    131                                     pCaption->Right( (long) pCaption->length()-m_iBufferPos );
    132 
    133                     --m_iBufferPos;
     110                    {
     111                        if (m_iBufferPos == (int)pCaption->length())
     112                            *pCaption = pCaption->Left( (long) pCaption->length()-1);
     113                        else
     114                            *pCaption = pCaption->Left( m_iBufferPos-1 ) +
     115                                        pCaption->Right( (long) pCaption->length()-m_iBufferPos );
     116
     117                        --m_iBufferPos;
    134118                   
    135                     UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos);
     119                        UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos);
     120                    }
    136121                }
    137122
     
    140125
    141126            case SDLK_DELETE:
    142                 m_WantedX=0.f;
     127                m_WantedX=0.0f;
    143128                // If selection:
    144129                if (SelectingText())
     
    148133                else
    149134                {
    150                     if (pCaption->empty() ||
    151                         m_iBufferPos == (int)pCaption->length())
     135                    if (pCaption->empty() || m_iBufferPos == (int)pCaption->length())
     136                    {
    152137                        break;
    153 
    154                     *pCaption = pCaption->Left( m_iBufferPos ) +
    155                                 pCaption->Right( (long) pCaption->length()-(m_iBufferPos+1) );
    156 
    157                     UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos);
     138                    }
     139                    else
     140                    {
     141                        *pCaption = pCaption->Left( m_iBufferPos ) +
     142                                    pCaption->Right( (long) pCaption->length()-(m_iBufferPos+1) );
     143
     144                        UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos);
     145                    }
    158146                }
    159147
     
    163151            case SDLK_HOME:
    164152                // If there's not a selection, we should create one now
    165                 if (!g_keys[SDLK_RSHIFT] && !g_keys[SDLK_LSHIFT])
     153                if (!shiftKeyPressed)
    166154                {
    167155                    // Make sure a selection isn't created.
     
    175163
    176164                m_iBufferPos = 0;
    177                 m_WantedX=0.f;
     165                m_WantedX=0.0f;
    178166
    179167                UpdateAutoScroll();
     
    182170            case SDLK_END:
    183171                // If there's not a selection, we should create one now
    184                 if (!g_keys[SDLK_RSHIFT] && !g_keys[SDLK_LSHIFT])
     172                if (!shiftKeyPressed)
    185173                {
    186174                    // Make sure a selection isn't created.
     
    194182
    195183                m_iBufferPos = (long) pCaption->length();
    196                 m_WantedX=0.f;
     184                m_WantedX=0.0f;
    197185
    198186                UpdateAutoScroll();
     
    222210            **/
    223211            case SDLK_LEFT:
    224                 // reset m_WantedX, very important
    225212                m_WantedX=0.f;
    226213
    227                 if (g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT] ||
    228                     !SelectingText())
    229                 {
    230                     // If there's not a selection, we should create one now
    231                     if (!SelectingText() && !g_keys[SDLK_RSHIFT] && !g_keys[SDLK_LSHIFT])
    232                     {
    233                         // Make sure a selection isn't created.
     214                if (shiftKeyPressed || !SelectingText())
     215                {
     216                    if (!shiftKeyPressed)
     217                    {
    234218                        m_iBufferPos_Tail = -1;
    235219                    }
    236220                    else if (!SelectingText())
    237221                    {
    238                         // Place tail at the current point:
    239222                        m_iBufferPos_Tail = m_iBufferPos;
    240223                    }
    241224
    242                     if (m_iBufferPos)
     225                    if (m_iBufferPos > 0)
    243226                        --m_iBufferPos;
    244227                }
     
    255238
    256239            case SDLK_RIGHT:
    257                 m_WantedX=0.f;
    258 
    259                 if (g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT] ||
    260                     !SelectingText())
    261                 {
    262                     // If there's not a selection, we should create one now
    263                     if (!SelectingText() && !g_keys[SDLK_RSHIFT] && !g_keys[SDLK_LSHIFT])
    264                     {
    265                         // Make sure a selection isn't created.
     240                m_WantedX=0.0f;
     241
     242                if (shiftKeyPressed || !SelectingText())
     243                {
     244                    if (!shiftKeyPressed)
     245                    {
    266246                        m_iBufferPos_Tail = -1;
    267247                    }
    268248                    else if (!SelectingText())
    269249                    {
    270                         // Place tail at the current point:
    271250                        m_iBufferPos_Tail = m_iBufferPos;
    272251                    }
    273252
    274 
    275                     if (m_iBufferPos != (int)pCaption->length())
     253                    if (m_iBufferPos < (int)pCaption->length())
    276254                        ++m_iBufferPos;
    277255                }
     
    309287            case SDLK_UP:
    310288            {
    311                 // If there's not a selection, we should create one now
    312                 if (!g_keys[SDLK_RSHIFT] && !g_keys[SDLK_LSHIFT])
    313                 {
    314                     // Make sure a selection isn't created.
     289                if (!shiftKeyPressed)
     290                {
    315291                    m_iBufferPos_Tail = -1;
    316292                }
    317293                else if (!SelectingText())
    318294                {
    319                     // Place tail at the current point:
    320295                    m_iBufferPos_Tail = m_iBufferPos;
    321296                }
     
    357332            case SDLK_DOWN:
    358333            {
    359                 // If there's not a selection, we should create one now
    360                 if (!g_keys[SDLK_RSHIFT] && !g_keys[SDLK_LSHIFT])
    361                 {
    362                     // Make sure a selection isn't created.
     334                if (!shiftKeyPressed)
     335                {
    363336                    m_iBufferPos_Tail = -1;
    364337                }
    365338                else if (!SelectingText())
    366339                {
    367                     // Place tail at the current point:
    368340                    m_iBufferPos_Tail = m_iBufferPos;
    369341                }
     
    429401            default: //Insert a character
    430402                {
    431                 // If there's a selection, delete if first.
    432403                if (cooked == 0)
    433404                    return IN_PASS; // Important, because we didn't use any key
     
    439410                    break;
    440411
    441                 m_WantedX=0.f;
     412                m_WantedX=0.0f;
    442413
    443414                if (SelectingText())
     
    466437}
    467438
     439
     440InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev)
     441{
     442    CStrW *pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     443    bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT];
     444
     445    std::string hotkey = static_cast<const char*>(ev->ev.user.data1);
     446    if (hotkey == "console.paste")
     447    {
     448        m_WantedX=0.0f;
     449
     450        wchar_t* text = sys_clipboard_get();
     451        if (text)
     452        {
     453            if (m_iBufferPos == (int)pCaption->length())
     454                *pCaption += text;
     455            else
     456                *pCaption = pCaption->Left(m_iBufferPos) + text +
     457                pCaption->Right((long) pCaption->length()-m_iBufferPos);
     458
     459            UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1);
     460
     461            m_iBufferPos += (int)wcslen(text);
     462
     463            sys_clipboard_free(text);
     464        }
     465
     466        return IN_HANDLED;
     467    }
     468    else if (hotkey == "console.copy" || hotkey == "console.cut")
     469    {
     470        m_WantedX=0.0f;
     471
     472        if (SelectingText())
     473        {
     474            int virtualFrom;
     475            int virtualTo;
     476
     477            if (m_iBufferPos_Tail >= m_iBufferPos)
     478            {
     479                virtualFrom = m_iBufferPos;
     480                virtualTo = m_iBufferPos_Tail;
     481            }
     482            else
     483            {
     484                virtualFrom = m_iBufferPos_Tail;
     485                virtualTo = m_iBufferPos;
     486            }
     487
     488            CStrW text = (pCaption->Left(virtualTo)).Right(virtualTo - virtualFrom);
     489
     490            sys_clipboard_set(&text[0]);
     491
     492            if (hotkey == "console.cut")
     493            {
     494                DeleteCurSelection();
     495            }
     496        }
     497
     498        return IN_HANDLED;
     499    }
     500    else if (hotkey == "text.delete.word.left")
     501    {
     502        m_WantedX=0.0f;
     503
     504        if (SelectingText())
     505        {
     506            DeleteCurSelection();
     507        }
     508        if (!pCaption->empty() && !m_iBufferPos == 0)
     509        {
     510            m_iBufferPos_Tail = m_iBufferPos;
     511            CStrW searchString = pCaption->Left( m_iBufferPos );
     512
     513            // If we are starting in whitespace, adjust position until we get a non whitespace
     514            while (m_iBufferPos > 0)
     515            {
     516                if (!iswspace(searchString[m_iBufferPos - 1]))
     517                    break;
     518
     519                m_iBufferPos--;
     520            }
     521               
     522            // If we end up on a puctuation char we just delete it (treat punct like a word)
     523            if (iswpunct(searchString[m_iBufferPos - 1]))
     524                m_iBufferPos--;
     525            else
     526            {
     527                // Now we are on a non white space character, adjust position to char after next whitespace char is found
     528                while (m_iBufferPos > 0)
     529                {
     530                    if (iswspace(searchString[m_iBufferPos - 1]) || iswpunct(searchString[m_iBufferPos - 1]))
     531                        break;
     532
     533                    m_iBufferPos--;
     534                }
     535            }
     536
     537            DeleteCurSelection();
     538        }
     539        return IN_HANDLED;
     540    }
     541    else if (hotkey == "text.delete.word.right")
     542    {
     543        m_WantedX=0.0f;
     544
     545        if (SelectingText())
     546        {
     547            DeleteCurSelection();
     548        }
     549        if (!pCaption->empty() && m_iBufferPos < (int)pCaption->length())
     550        {
     551            // Delete the word to the right of the cursor
     552            m_iBufferPos_Tail = m_iBufferPos;
     553
     554            // Delete chars to the right unit we hit whitespace
     555            while (++m_iBufferPos < (int)pCaption->length())
     556            {
     557                if (iswspace((*pCaption)[m_iBufferPos]) || iswpunct((*pCaption)[m_iBufferPos]))
     558                    break;
     559            }
     560
     561            // Eliminate any whitespace behind the word we just deleted
     562            while (m_iBufferPos < (int)pCaption->length())
     563            {
     564                if (!iswspace((*pCaption)[m_iBufferPos]))
     565                    break;
     566
     567                m_iBufferPos++;
     568            }
     569            DeleteCurSelection();
     570        }
     571        return IN_HANDLED;         
     572    }
     573    else if (hotkey == "text.move.word.left")
     574    {
     575        m_WantedX=0.0f;
     576               
     577        if (shiftKeyPressed || !SelectingText())
     578        {
     579            if (!shiftKeyPressed)
     580            {
     581                m_iBufferPos_Tail = -1;
     582            }
     583            else if (!SelectingText())
     584            {
     585                m_iBufferPos_Tail = m_iBufferPos;
     586            }
     587
     588            if (!pCaption->empty() && !m_iBufferPos == 0)
     589            {
     590                CStrW searchString = pCaption->Left( m_iBufferPos );
     591
     592                // If we are starting in whitespace, adjust position until we get a non whitespace
     593                while (m_iBufferPos > 0)
     594                {
     595                    if (!iswspace(searchString[m_iBufferPos - 1]))
     596                        break;
     597
     598                    m_iBufferPos--;
     599                }
     600               
     601                // If we end up on a puctuation char we just select it (treat punct like a word)
     602                if (iswpunct(searchString[m_iBufferPos - 1]))
     603                    m_iBufferPos--;
     604                else
     605                {
     606                    // Now we are on a non white space character, adjust position to char after next whitespace char is found
     607                    while (m_iBufferPos > 0)
     608                    {
     609                        if (iswspace(searchString[m_iBufferPos - 1]) || iswpunct(searchString[m_iBufferPos - 1]))
     610                            break;
     611
     612                        m_iBufferPos--;
     613                    }
     614                }
     615            }
     616        }
     617        else
     618        {
     619            if (m_iBufferPos_Tail < m_iBufferPos)
     620                m_iBufferPos = m_iBufferPos_Tail;
     621
     622            m_iBufferPos_Tail = -1;
     623        }
     624
     625        UpdateAutoScroll();
     626
     627        return IN_HANDLED;
     628    }
     629    else if (hotkey == "text.move.word.right")
     630    {
     631        m_WantedX=0.0f;
     632
     633        if (shiftKeyPressed || !SelectingText())
     634        {
     635            if (!shiftKeyPressed)
     636            {
     637                m_iBufferPos_Tail = -1;
     638            }
     639            else if (!SelectingText())
     640            {
     641                m_iBufferPos_Tail = m_iBufferPos;
     642            }
     643
     644            if (!pCaption->empty() && m_iBufferPos < (int)pCaption->length())
     645            {
     646                CStrW searchString = *pCaption;
     647
     648                // Select chars to the right until we hit whitespace
     649                while (++m_iBufferPos < (int)pCaption->length())
     650                {
     651                    if (iswspace((*pCaption)[m_iBufferPos]) || iswpunct((*pCaption)[m_iBufferPos]))
     652                        break;
     653                }
     654
     655                // Also select any whitespace following the word we just selected
     656                while (m_iBufferPos < (int)pCaption->length())
     657                {
     658                    if (!iswspace((*pCaption)[m_iBufferPos]))
     659                        break;
     660
     661                    m_iBufferPos++;
     662                }
     663            }
     664        }
     665        else
     666        {
     667            if (m_iBufferPos_Tail > m_iBufferPos)
     668                m_iBufferPos = m_iBufferPos_Tail;
     669
     670            m_iBufferPos_Tail = -1;
     671        }           
     672
     673        UpdateAutoScroll();
     674
     675        return IN_HANDLED;
     676    }
     677    else
     678    {
     679        return IN_PASS;
     680    }
     681}
     682
     683
    468684void CInput::HandleMessage(SGUIMessage &Message)
    469685{
     
    481697        // TODO Gee: (2004-09-01) Is this really updated each time it should?
    482698        if (scrollbar &&
    483             (Message.value == CStr("size") ||
     699            (Message.value == CStr("size") ||
    484700             Message.value == CStr("z") ||
    485701             Message.value == CStr("absolute")))
     
    565781
    566782        }break;
     783
     784    case GUIM_MOUSE_DBLCLICK_LEFT:
     785        {
     786            CStrW *pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     787            m_iBufferPos = m_iBufferPos_Tail = GetMouseHoveringTextPosition();
     788
     789            // See if we are clicking over whitespace
     790            if (iswspace((*pCaption)[m_iBufferPos]))
     791            {
     792                // see if we are in a section of whitespace greater than one character
     793                if ((m_iBufferPos + 1 < (int) pCaption->length() && iswspace((*pCaption)[m_iBufferPos + 1])) ||
     794                    (m_iBufferPos - 1 > 0 && iswspace((*pCaption)[m_iBufferPos - 1])))
     795                {
     796                    //
     797                    // We are clicking in an area with more than one whitespace character
     798                    // so we select both the word to the left and then the word to the right
     799                    //
     800                    // [1] First the left
     801                    // skip the whitespace
     802                    while (m_iBufferPos > 0)
     803                    {
     804                        if (!iswspace((*pCaption)[m_iBufferPos - 1]))
     805                            break;
     806
     807                        m_iBufferPos--;
     808                    }
     809                    // now go until we hit white space or punctuation
     810                    while (m_iBufferPos > 0)
     811                    {
     812                        if (iswspace((*pCaption)[m_iBufferPos - 1]))
     813                            break;
     814
     815                        m_iBufferPos--;
     816
     817                        if (iswpunct((*pCaption)[m_iBufferPos]))
     818                            break;
     819                    }
     820
     821                    // [2] Then the right
     822                    // go right until we are not in whitespace
     823                    while (++m_iBufferPos_Tail < (int)pCaption->length())
     824                    {
     825                        if (!iswspace((*pCaption)[m_iBufferPos_Tail]))
     826                            break;
     827                    }
     828                    // now go to the right until we hit whitespace or punctuation
     829                    while (++m_iBufferPos_Tail < (int)pCaption->length())
     830                    {
     831                        if (iswspace((*pCaption)[m_iBufferPos_Tail]) || iswpunct((*pCaption)[m_iBufferPos_Tail]))
     832                            break;
     833                    }
     834                }
     835                else
     836                {
     837                    // single whitespace so select word to the right
     838                    while (++m_iBufferPos_Tail < (int)pCaption->length())
     839                    {
     840                        if (!iswspace((*pCaption)[m_iBufferPos_Tail]))
     841                            break;
     842                    }
     843
     844                    // Don't include the leading whitespace
     845                    m_iBufferPos = m_iBufferPos_Tail;
     846
     847                    // now go to the right until we hit whitespace or punctuation
     848                    while (++m_iBufferPos_Tail < (int)pCaption->length())
     849                    {
     850                        if (iswspace((*pCaption)[m_iBufferPos_Tail]) || iswpunct((*pCaption)[m_iBufferPos_Tail]))
     851                            break;
     852                    }
     853                }
     854            }
     855            else
     856            {
     857                // clicked on non-whitespace so select current word
     858                // go until we hit white space or punctuation
     859                while (m_iBufferPos > 0)
     860                {
     861                    if (iswspace((*pCaption)[m_iBufferPos - 1]))
     862                        break;
     863
     864                    m_iBufferPos--;
     865
     866                    if (iswpunct((*pCaption)[m_iBufferPos]))
     867                        break;
     868                }
     869                // go to the right until we hit whitespace or punctuation
     870                while (++m_iBufferPos_Tail < (int)pCaption->length())
     871                {
     872                    if (iswspace((*pCaption)[m_iBufferPos_Tail]) || iswpunct((*pCaption)[m_iBufferPos_Tail]))
     873                        break;
     874                }
     875            }
     876        }
     877        break;
    567878
    568879    case GUIM_MOUSE_RELEASE_LEFT:
     
    9221233
    9231234                    if (i < (int)it->m_ListOfX.size())
    924                         x_pointer += (float)font.GetCharacterWidth((*pCaption)[it->m_ListStart + i]);
     1235                        x_pointer += (float)font.GetCharacterWidth((*pCaption)[it->m_ListStart + i]);
    9251236                }
    9261237
     
    9541265                if (multiline)
    9551266                {
    956                     if (buffered_y + buffer_zone > m_CachedActualSize.GetHeight())
     1267                    if (buffered_y + buffer_zone > m_CachedActualSize.GetHeight())
    9571268                        break;
    9581269                }
     
    9621273                // Text must always be drawn in integer values. So we have to convert scroll
    9631274                if (multiline)
    964                     glTranslatef(0.f, -(float)(int)scroll, 0.f);
     1275                    glTranslatef(0.f, -(float)(int)scroll, 0.f);
    9651276                else
    9661277                    glTranslatef(-(float)(int)m_HorizontalScroll, 0.f, 0.f);
     
    11701481        if (destroy_row_to_used == false)
    11711482        {
    1172             destroy_row_to = m_CharacterPositions.end();
     1483            destroy_row_to = m_CharacterPositions.end();
    11731484            check_point_row_start = -1;
    11741485
     
    11811492       
    11821493        if (destroy_row_to != m_CharacterPositions.end())
    1183             to = destroy_row_to->m_ListStart; // notice it will iterate [from, to), so it will never reach to.
     1494            to = destroy_row_to->m_ListStart; // notice it will iterate [from, to), so it will never reach to.
    11841495        else
    11851496            to = (int)caption.length();
     
    14291740
    14301741    // Return position
    1431     int RetPosition;
     1742    int retPosition;
    14321743
    14331744    float buffer_zone;
     
    14941805
    14951806    //m_iBufferPos = m_CharacterPositions.get.m_ListStart;
    1496     RetPosition = current->m_ListStart;
     1807    retPosition = current->m_ListStart;
    14971808   
    14981809    // Okay, now loop through the glyphs to find the appropriate X position
    14991810    float dummy;
    1500     RetPosition += GetXTextPosition(current, mouse.x, dummy);
    1501 
    1502     return RetPosition;
     1811    retPosition += GetXTextPosition(current, mouse.x, dummy);
     1812
     1813    return retPosition;
    15031814}
    15041815
     
    15061817int CInput::GetXTextPosition(const std::list<SRow>::iterator &current, const float &x, float &wanted)
    15071818{
    1508     int Ret=0;
    1509 
     1819    int ret=0;
    15101820    float previous=0.f;
    15111821    int i=0;
     
    15181828        {
    15191829            if (x - previous >= *it - x)
    1520                 Ret += i+1;
     1830                ret += i+1;
    15211831            else
    1522                 Ret += i;
     1832                ret += i;
    15231833
    15241834            break;
     
    15301840    if (i == (int)current->m_ListOfX.size())
    15311841    {
    1532         Ret += i;
     1842        ret += i;
    15331843        wanted = x;
    15341844    }
    15351845    else wanted = 0.f;
    15361846
    1537     return Ret;
     1847    return ret;
    15381848}
    15391849
     
    15421852    CStrW *pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
    15431853
    1544     int VirtualFrom, VirtualTo;
     1854    int virtualFrom;
     1855    int virtualTo;
    15451856
    15461857    if (m_iBufferPos_Tail >= m_iBufferPos)
    15471858    {
    1548         VirtualFrom = m_iBufferPos;
    1549         VirtualTo = m_iBufferPos_Tail;
     1859        virtualFrom = m_iBufferPos;
     1860        virtualTo = m_iBufferPos_Tail;
    15501861    }
    15511862    else
    15521863    {
    1553         VirtualFrom = m_iBufferPos_Tail;
    1554         VirtualTo = m_iBufferPos;
    1555     }
    1556 
    1557     *pCaption = pCaption->Left( VirtualFrom ) +
    1558                 pCaption->Right( (long) pCaption->length()-(VirtualTo) );
    1559 
    1560     UpdateText(VirtualFrom, VirtualTo, VirtualFrom);
     1864        virtualFrom = m_iBufferPos_Tail;
     1865        virtualTo = m_iBufferPos;
     1866    }
     1867
     1868    *pCaption = pCaption->Left( virtualFrom ) +
     1869                pCaption->Right( (long) pCaption->length() - (virtualTo) );
     1870
     1871    UpdateText(virtualFrom, virtualTo, virtualFrom);
    15611872
    15621873    // Remove selection
    15631874    m_iBufferPos_Tail = -1;
    1564     m_iBufferPos = VirtualFrom;
     1875    m_iBufferPos = virtualFrom;
    15651876}
    15661877
  • ps/trunk/source/gui/CInput.h

    r9340 r9646  
    9898
    9999    /**
     100     * Handle hotkey events (called by ManuallyHandleEvent)
     101     */
     102    virtual InReaction ManuallyHandleHotkeyEvent(const SDL_Event_* ev);
     103
     104    /**
    100105     * @see IGUIObject#UpdateCachedSize()
    101106     */
  • ps/trunk/source/lib/sysdep/clipboard.h

    r9410 r9646  
    1 /* Copyright (c) 2010 Wildfire Games
     1/* Copyright (c) 2011 Wildfire Games
    22 *
    33 * Permission is hereby granted, free of charge, to any person obtaining
     
    2121 */
    2222
     23#ifndef INCLUDED_SYSDEP_CLIPBOARD
     24#define INCLUDED_SYSDEP_CLIPBOARD
     25
    2326// "copy" text into the clipboard. replaces previous contents.
    2427extern Status sys_clipboard_set(const wchar_t* text);
    2528
    26 // allow "pasting" from clipboard. returns the current contents if they
    27 // can be represented as text, otherwise 0.
    28 // when it is no longer needed, the returned pointer must be freed via
    29 // sys_clipboard_free. (NB: not necessary if zero, but doesn't hurt)
     29// allow "pasting" from clipboard.
     30// @return current clipboard text or 0 if not representable as text.
     31// callers are responsible for passing this pointer to sys_clipboard_free.
    3032extern wchar_t* sys_clipboard_get();
    3133
    32 // frees memory used by <copy>, which must have been returned by
    33 // sys_clipboard_get. see note above.
     34// free memory returned by sys_clipboard_get.
     35// @param copy is ignored if 0.
    3436extern Status sys_clipboard_free(wchar_t* copy);
     37
     38#endif  // #ifndef INCLUDED_SYSDEP_CLIPBOARD
  • ps/trunk/source/lib/sysdep/os/win/wclipboard.cpp

    r9410 r9646  
    2727#include "lib/sysdep/os/win/wutil.h"
    2828
    29 // caller is responsible for freeing *hMem.
    30 static Status SetClipboardText(const wchar_t* text, HGLOBAL* hMem)
     29
     30// caller is responsible for freeing hMem.
     31static Status SetClipboardText(const wchar_t* text, HGLOBAL& hMem)
    3132{
    3233    const size_t numChars = wcslen(text);
    33     *hMem = GlobalAlloc(GMEM_MOVEABLE, (numChars+1) * sizeof(wchar_t));
    34     if(!*hMem)
     34    hMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, (numChars + 1) * sizeof(wchar_t));
     35    if(!hMem)
    3536        WARN_RETURN(ERR::NO_MEM);
    3637
    37     wchar_t* lockedText = (wchar_t*)GlobalLock(*hMem);
     38    wchar_t* lockedText = (wchar_t*)GlobalLock(hMem);
    3839    if(!lockedText)
    3940        WARN_RETURN(ERR::NO_MEM);
    4041    wcscpy_s(lockedText, numChars+1, text);
    41     GlobalUnlock(*hMem);
     42    GlobalUnlock(hMem);
    4243
    43     HANDLE hData = SetClipboardData(CF_UNICODETEXT, *hMem);
     44    HANDLE hData = SetClipboardData(CF_UNICODETEXT, hMem);
    4445    if(!hData)  // failed
    4546        WARN_RETURN(ERR::FAIL);
     
    4849}
    4950
    50 // "copy" text into the clipboard. replaces previous contents.
     51
     52// @return INFO::OK iff text has been assigned a pointer (which the
     53// caller must free via sys_clipboard_free) to the clipboard text.
     54static Status GetClipboardText(wchar_t*& text)
     55{
     56    // NB: Windows NT/2000+ auto convert CF_UNICODETEXT <-> CF_TEXT.
     57
     58    if(!IsClipboardFormatAvailable(CF_UNICODETEXT))
     59        return INFO::CANNOT_HANDLE;
     60
     61    HGLOBAL hMem = GetClipboardData(CF_UNICODETEXT);
     62    if(!hMem)
     63        WARN_RETURN(ERR::FAIL);
     64
     65    const wchar_t* lockedText = (const wchar_t*)GlobalLock(hMem);
     66    if(!lockedText)
     67        WARN_RETURN(ERR::NO_MEM);
     68
     69    const size_t size = GlobalSize(hMem);
     70    text = (wchar_t*)malloc(size);
     71    if(!text)
     72        WARN_RETURN(ERR::NO_MEM);
     73    wcscpy_s(text, size/sizeof(wchar_t), lockedText);
     74
     75    (void)GlobalUnlock(hMem);
     76
     77    return INFO::OK;
     78}
     79
     80
     81// OpenClipboard parameter.
     82// NB: using wutil_AppWindow() causes GlobalLock to fail.
     83static const HWND hWndNewOwner = 0; // MSDN: associate with "current task"
     84
    5185Status sys_clipboard_set(const wchar_t* text)
    5286{
    53     // note: MSDN claims that the window handle must not be 0;
    54     // that does actually work on WinXP, but we'll play it safe.
    55     if(!OpenClipboard(wutil_AppWindow()))
     87    if(!OpenClipboard(hWndNewOwner))
    5688        WARN_RETURN(ERR::FAIL);
    57     EmptyClipboard();
    5889
     90    WARN_IF_FALSE(EmptyClipboard());
     91
     92    // NB: to enable copy/pasting something other than text, add
     93    // message handlers for WM_RENDERFORMAT and WM_RENDERALLFORMATS.
    5994    HGLOBAL hMem;
    60     Status ret = SetClipboardText(text, &hMem);
     95    Status ret = SetClipboardText(text, hMem);
    6196
    62     CloseClipboard();
     97    WARN_IF_FALSE(CloseClipboard());    // must happen before GlobalFree
    6398
    64     // note: MSDN's SetClipboardData documentation says hMem must not be
    65     // freed until after CloseClipboard. however, GlobalFree still fails
    66     // after the successful completion of both. we'll leave it in to avoid
    67     // memory leaks, but ignore its return value.
    68     (void)GlobalFree(hMem);
     99    ENSURE(GlobalFree(hMem) == 0);  // (0 indicates success)
    69100
    70101    return ret;
     
    72103
    73104
    74 static wchar_t* CopyClipboardContents()
     105wchar_t* sys_clipboard_get()
    75106{
    76     // Windows NT/2000+ auto convert UNICODETEXT <-> TEXT
    77     HGLOBAL hMem = GetClipboardData(CF_UNICODETEXT);
    78     if(!hMem)
     107    if(!OpenClipboard(hWndNewOwner))
    79108        return 0;
    80109
    81     const wchar_t* lockedText = (const wchar_t*)GlobalLock(hMem);
    82     if(!lockedText)
    83         return 0;
     110    wchar_t* text;
     111    Status ret = GetClipboardText(text);
    84112
    85     const size_t numChars = GlobalSize(hMem)/sizeof(wchar_t) - 1;
    86     wchar_t* text = new wchar_t[numChars+1];
    87     wcscpy_s(text, numChars+1, lockedText);
     113    WARN_IF_FALSE(CloseClipboard());
    88114
    89     GlobalUnlock(hMem);
    90 
    91     return text;
    92 }
    93 
    94 // allow "pasting" from clipboard. returns the current contents if they
    95 // can be represented as text, otherwise 0.
    96 // when it is no longer needed, the returned pointer must be freed via
    97 // sys_clipboard_free. (NB: not necessary if zero, but doesn't hurt)
    98 wchar_t* sys_clipboard_get()
    99 {
    100     if(!OpenClipboard(wutil_AppWindow()))
    101         return 0;
    102     wchar_t* const ret = CopyClipboardContents();
    103     CloseClipboard();
    104     return ret;
     115    return (ret == INFO::OK)? text : 0;
    105116}
    106117
    107118
    108 // frees memory used by <copy>, which must have been returned by
    109 // sys_clipboard_get. see note above.
    110119Status sys_clipboard_free(wchar_t* text)
    111120{
    112     delete[] text;
     121    free(text);
    113122    return INFO::OK;
    114123}
Note: See TracChangeset for help on using the changeset viewer.