Date: prev next · Thread: first prev next last
2013 Archives by date, by thread · List index


Hi,

I have submitted a patch for review:

    https://gerrit.libreoffice.org/3849

To pull it, you can do:

    git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/49/3849/1

Support IMR_QUERYCHARPOSITION in Writer and Calc.

Change-Id: I53a344a78688060004cc8bcbbf1127f22a468e20
---
M editeng/source/editeng/impedit2.cxx
M include/vcl/cmdevt.hxx
M include/vcl/window.hxx
M sc/source/ui/app/inputhdl.cxx
M sc/source/ui/view/gridwin.cxx
M sw/inc/crsrsh.hxx
M sw/source/core/crsr/crsrsh.cxx
M sw/source/ui/docvw/edtwin.cxx
M vcl/inc/salwtype.hxx
M vcl/inc/window.h
M vcl/source/control/edit.cxx
M vcl/source/edit/textview.cxx
M vcl/source/window/window.cxx
M vcl/source/window/winproc.cxx
M vcl/win/source/window/salframe.cxx
15 files changed, 264 insertions(+), 7 deletions(-)



diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx
index e75a7f9..dd935ff 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -537,6 +537,33 @@
             }
         }
     }
+    else if ( rCEvt.GetCommand() == COMMAND_QUERYCHARPOSITION )
+    {
+        if ( mpIMEInfos && mpIMEInfos->nLen )
+        {
+            EditPaM aPaM( pView->pImpEditView->GetEditSelection().Max() );
+            if ( !IsFormatted() )
+                FormatDoc();
+
+            ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( GetEditDoc().GetPos( 
aPaM.GetNode() ) );
+            sal_uInt16 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_True );
+            const EditLine* pLine = pParaPortion->GetLines()[nLine];
+            if ( pLine )
+            {
+                Rectangle* aRects = new Rectangle[ mpIMEInfos->nLen ];
+                for (sal_uInt16 i = 0; i < mpIMEInfos->nLen; ++i)
+                {
+                    sal_uInt16 nInputPos = mpIMEInfos->aPos.GetIndex() + i;
+                    if ( nInputPos > pLine->GetEnd() )
+                        nInputPos = pLine->GetEnd();
+                    Rectangle aR2 = GetEditCursor( pParaPortion, nInputPos );
+                    aRects[ i ] = pView->GetImpEditView()->GetWindowPos( aR2 );
+                }
+                pView->GetWindow()->SetCompositionCharRect( aRects, mpIMEInfos->nLen );
+                delete[] aRects;
+            }
+        }
+    }
 
     GetSelEngine().Command( rCEvt );
 }
diff --git a/include/vcl/cmdevt.hxx b/include/vcl/cmdevt.hxx
index 03876e5..75714f2 100644
--- a/include/vcl/cmdevt.hxx
+++ b/include/vcl/cmdevt.hxx
@@ -351,6 +351,8 @@
 #define COMMAND_MEDIA                   ((sal_uInt16)17)
 #define COMMAND_SELECTIONCHANGE         ((sal_uInt16)18)
 #define COMMAND_PREPARERECONVERSION     ((sal_uInt16)19)
+#define COMMAND_QUERYCHARPOSITION       ((sal_uInt16)20)
+
 
 class VCL_DLLPUBLIC CommandEvent
 {
diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index 43e232d..d1c783b 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -680,6 +680,8 @@
     const Rectangle*    GetCursorRect() const;
     long                GetCursorExtTextInputWidth() const;
 
+    void                SetCompositionCharRect( const Rectangle* pRect, long nCompositionLength, 
sal_Bool bVertical = sal_False );
+
     using               OutputDevice::SetSettings;
     virtual void        SetSettings( const AllSettings& rSettings );
     virtual void        SetSettings( const AllSettings& rSettings, sal_Bool bChild );
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index 7f6ac08..8287258 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -3351,6 +3351,21 @@
             }
         }
     }
+    else if ( rCEvt.GetCommand() == COMMAND_QUERYCHARPOSITION )
+    {
+        if ( eMode != SC_INPUT_NONE )
+        {
+            UpdateActiveView();
+            if (pTableView || pTopView)
+            {
+                if (pTableView)
+                    pTableView->Command( rCEvt );
+                else if (pTopView)                      // call only once
+                    pTopView->Command( rCEvt );
+                bUsed = true;
+            }
+        }
+    }
     else
     {
         if ( bForce || eMode != SC_INPUT_NONE )
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index cb9c09f..86cddf2 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -2813,7 +2813,8 @@
     if ( nCmd == COMMAND_STARTEXTTEXTINPUT ||
          nCmd == COMMAND_ENDEXTTEXTINPUT ||
          nCmd == COMMAND_EXTTEXTINPUT ||
-         nCmd == COMMAND_CURSORPOS )
+         nCmd == COMMAND_CURSORPOS ||
+         nCmd == COMMAND_QUERYCHARPOSITION )
     {
         sal_Bool bEditView = pViewData->HasEditView( eWhich );
         if (!bEditView)
diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 2ddb6d5..58107de 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -526,6 +526,10 @@
      * Returns if cursor is wholly or partly within visible range.
      */
     sal_Bool IsCrsrVisible() const { return VisArea().IsOver( GetCharRect() ); }
+    /*
+     * Returns SwRect, at which the character is located.
+     */
+    sal_Bool GetCharRectAt(SwRect& rRect, const SwPosition* pPos);
 
     // Return current page number:
     // TRUE:  in which cursor is located.
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index c32250c..24b2d0e 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -1005,6 +1005,11 @@
     return bRet;
 }
 
+sal_Bool SwCrsrShell::GetCharRectAt(SwRect& rRect, const SwPosition* pPos)
+{
+    SwCntntFrm* pFrm = GetCurrFrm();
+    return pFrm->GetCharRect( rRect, *pPos );
+}
 
 void SwCrsrShell::GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum,
                               sal_Bool bAtCrsrPos, const sal_Bool bCalcFrm )
diff --git a/sw/source/ui/docvw/edtwin.cxx b/sw/source/ui/docvw/edtwin.cxx
index 3ec057d..ba6c20c 100644
--- a/sw/source/ui/docvw/edtwin.cxx
+++ b/sw/source/ui/docvw/edtwin.cxx
@@ -5193,6 +5193,50 @@
             }
         }
         break;
+        case COMMAND_QUERYCHARPOSITION:
+        {
+            SwWrtShell &rSh = m_rView.GetWrtShell();
+            sal_Bool bVertical = rSh.IsInVerticalText();
+            const SwPosition& rPos = *rSh.GetCrsr()->GetPoint();
+            SwDocShell* pDocSh = m_rView.GetDocShell();
+            SwDoc *pDoc = pDocSh->GetDoc();
+            SwExtTextInput* pInput = pDoc->GetExtTextInput( rPos.nNode.GetNode(), 
rPos.nContent.GetIndex() );
+            if ( pInput )
+            {
+                const SwPosition& rStart = *pInput->Start();
+                const SwPosition& rEnd = *pInput->End();
+                int nSize = 0;
+                for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex )
+                {
+                    ++nSize;
+                }
+                Window& rWin = rSh.GetView().GetEditWin();
+                if ( nSize == 0 )
+                {
+                    // When the composition does not exist, use Caret rect instead.
+                    SwRect aCaretRect ( rSh.GetCharRect() );
+                    Rectangle aRect( aCaretRect.Left(), aCaretRect.Top(), aCaretRect.Right(), 
aCaretRect.Bottom() );
+                    rWin.SetCompositionCharRect( &aRect, 1, bVertical );
+                }
+                else
+                {
+                    Rectangle* aRects = new Rectangle[ nSize ];
+                    int nRectIndex = 0;
+                    for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex )
+                    {
+                        const SwPosition aPos( rStart.nNode, nIndex );
+                        SwRect aRect ( rSh.GetCharRect() );
+                        rSh.GetCharRectAt( aRect, &aPos );
+                        aRects[ nRectIndex ] = Rectangle( aRect.Left(), aRect.Top(), 
aRect.Right(), aRect.Bottom() );
+                        ++nRectIndex;
+                    }
+                    rWin.SetCompositionCharRect( aRects, nSize, bVertical );
+                    delete[] aRects;
+                }
+            }
+            bCallBase = false;
+        }
+        break;
 #if OSL_DEBUG_LEVEL > 0
         default:
             OSL_ENSURE( !this, "unknown command." );
diff --git a/vcl/inc/salwtype.hxx b/vcl/inc/salwtype.hxx
index 62b982f..d38f724 100644
--- a/vcl/inc/salwtype.hxx
+++ b/vcl/inc/salwtype.hxx
@@ -82,6 +82,7 @@
 #define SALEVENT_STARTRECONVERSION      ((sal_uInt16)45)
 #define SALEVENT_EXTERNALZOOM           ((sal_uInt16)46)
 #define SALEVENT_EXTERNALSCROLL         ((sal_uInt16)47)
+#define SALEVENT_QUERYCHARPOSITION      ((sal_uInt16)48)
 
 // MOUSELEAVE must send, when the pointer leave the client area and
 // the mouse is not captured
@@ -213,6 +214,20 @@
     sal_uLong       mnEnd;          // The end index of selected range
 };
 
+// QUERYCHARPOSITION
+struct SalQueryCharPositionEvent
+{
+    bool            mbValid;                // The data is valid or not.
+    sal_uLong       mnCharPos;              // The index of character.
+    long            mnPointX;               // Target - X
+    long            mnPointY;               // Target - X
+    sal_uLong       mnLineHeight;           // The line height.
+    long            mnDocumentBoundX;       // BoundRect - X
+    long            mnDocumentBoundY;       // BoundRect - Y
+    long            mnDocumentBoundWidth;   // BoundRect - Width
+    long            mnDocumentBoundHeight;  // BoundRect - Height
+};
+
 // ------------------
 // - SalFrame-Types -
 // ------------------
diff --git a/vcl/inc/window.h b/vcl/inc/window.h
index 725f5ad..230e1b0 100644
--- a/vcl/inc/window.h
+++ b/vcl/inc/window.h
@@ -116,6 +116,9 @@
     sal_uInt16*             mpExtOldAttrAry;
     Rectangle*          mpCursorRect;
     long                mnCursorExtWidth;
+    sal_Bool            mbVertical;
+    Rectangle*          mpCompositionCharRects;
+    long                mnCompositionCharRects;
     Rectangle*          mpFocusRect;
     Rectangle*          mpTrackRect;
     sal_uInt16              mnTrackFlags;
diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx
index db44060..cf43de1 100644
--- a/vcl/source/control/edit.cxx
+++ b/vcl/source/control/edit.cxx
@@ -2313,6 +2313,40 @@
         Selection aSelection( pData->GetStart(), pData->GetEnd() );
         SetSelection(aSelection);
     }
+    else if ( rCEvt.GetCommand() == COMMAND_QUERYCHARPOSITION )
+    {
+        if (mpIMEInfos && mpIMEInfos->nLen > 0)
+        {
+            OUString aText = ImplGetText();
+            sal_Int32   nDXBuffer[256];
+            sal_Int32*  pDXBuffer = NULL;
+            sal_Int32*  pDX = nDXBuffer;
+
+            if( !aText.isEmpty() )
+            {
+                if( (size_t) (2*aText.getLength()) > SAL_N_ELEMENTS(nDXBuffer) )
+                {
+                    pDXBuffer = new sal_Int32[2*(aText.getLength()+1)];
+                    pDX = pDXBuffer;
+                }
+
+                GetCaretPositions( aText, pDX, 0, aText.getLength() );
+            }
+            long    nTH = GetTextHeight();
+            Point   aPos( mnXOffset, ImplGetTextYPosition() );
+
+            Rectangle* aRects = new Rectangle[ mpIMEInfos->nLen ];
+            for ( int nIndex = 0; nIndex < mpIMEInfos->nLen; ++nIndex )
+            {
+                Rectangle aRect( aPos, Size( 10, nTH ) );
+                aRect.Left() = pDX[2*(nIndex+mpIMEInfos->nPos)] + mnXOffset + ImplGetExtraOffset();
+                aRects[ nIndex ] = aRect;
+            }
+            SetCompositionCharRect( aRects, mpIMEInfos->nLen );
+            delete[] aRects;
+            delete[] pDXBuffer;
+        }
+    }
     else
         Control::Command( rCEvt );
 }
diff --git a/vcl/source/edit/textview.cxx b/vcl/source/edit/textview.cxx
index 4483616..81bca83 100644
--- a/vcl/source/edit/textview.cxx
+++ b/vcl/source/edit/textview.cxx
@@ -904,6 +904,8 @@
     mpImpl->mpSelEngine->SelMouseMove( rMouseEvent );
 }
 
+extern "C" void __stdcall OutputDebugStringA(const char *);
+
 void TextView::Command( const CommandEvent& rCEvt )
 {
     mpImpl->mpTextEngine->CheckIdleFormatter();    // Falls schnelles Tippen und MouseButtonDown
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index bc59719..9b6358a 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -1371,8 +1371,10 @@
         ((Window*)this)->mpWindowImpl->mpWinData = new ImplWinData;
         mpWindowImpl->mpWinData->mpExtOldText     = NULL;
         mpWindowImpl->mpWinData->mpExtOldAttrAry  = NULL;
-        mpWindowImpl->mpWinData->mpCursorRect     = 0;
+        mpWindowImpl->mpWinData->mpCursorRect     = NULL;
         mpWindowImpl->mpWinData->mnCursorExtWidth = 0;
+        mpWindowImpl->mpWinData->mpCompositionCharRects = NULL;
+        mpWindowImpl->mpWinData->mnCompositionCharRects = 0;
         mpWindowImpl->mpWinData->mpFocusRect      = NULL;
         mpWindowImpl->mpWinData->mpTrackRect      = NULL;
         mpWindowImpl->mpWinData->mnTrackFlags     = 0;
@@ -4643,6 +4645,8 @@
             delete mpWindowImpl->mpWinData->mpExtOldAttrAry;
         if ( mpWindowImpl->mpWinData->mpCursorRect )
             delete mpWindowImpl->mpWinData->mpCursorRect;
+        if ( mpWindowImpl->mpWinData->mpCompositionCharRects)
+            delete[] mpWindowImpl->mpWinData->mpCompositionCharRects;
         if ( mpWindowImpl->mpWinData->mpFocusRect )
             delete mpWindowImpl->mpWinData->mpFocusRect;
         if ( mpWindowImpl->mpWinData->mpTrackRect )
@@ -5657,6 +5661,24 @@
 }
 
 // -----------------------------------------------------------------------
+
+void Window::SetCompositionCharRect( const Rectangle* pRect, long nCompositionLength, sal_Bool 
bVertical ) {
+    DBG_CHKTHIS( Window, ImplDbgCheckWindow );
+
+    ImplWinData* pWinData = ImplGetWinData();
+    delete[] pWinData->mpCompositionCharRects;
+    pWinData->mbVertical = bVertical;
+    pWinData->mpCompositionCharRects = NULL;
+    pWinData->mnCompositionCharRects = nCompositionLength;
+    if ( pRect && (nCompositionLength > 0) )
+    {
+        pWinData->mpCompositionCharRects = new Rectangle[nCompositionLength];
+        for (long i = 0; i < nCompositionLength; ++i)
+            pWinData->mpCompositionCharRects[i] = pRect[i];
+    }
+}
+
+// -----------------------------------------------------------------------
 void Window::SetSettings( const AllSettings& rSettings )
 {
     SetSettings( rSettings, sal_False );
diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx
index 2a296ca..89f006b 100644
--- a/vcl/source/window/winproc.cxx
+++ b/vcl/source/window/winproc.cxx
@@ -2348,6 +2348,53 @@
 
 // -----------------------------------------------------------------------
 
+static void ImplHandleSalQueryCharPosition( Window *pWindow,
+                                            SalQueryCharPositionEvent *pEvt )
+{
+    pEvt->mbValid = false;            // The data is valid or not.
+    pEvt->mnPointX = 0;               // Target - X
+    pEvt->mnPointY = 0;               // Target - X
+    pEvt->mnLineHeight = 0;           // The line height.
+    pEvt->mnDocumentBoundX = 0;       // BoundRect - X
+    pEvt->mnDocumentBoundY = 0;       // BoundRect - Y
+    pEvt->mnDocumentBoundWidth = 0;   // BoundRect - Width
+    pEvt->mnDocumentBoundHeight = 0;  // BoundRect - Height
+
+    ImplSVData* pSVData = ImplGetSVData();
+    Window*     pChild = pSVData->maWinData.mpExtTextInputWin;
+
+    if ( !pChild )
+        pChild = ImplGetKeyInputWindow( pWindow );
+    else
+    {
+        // Test, if the Window is related to the frame
+        if ( !pWindow->ImplIsWindowOrChild( pChild ) )
+            pChild = ImplGetKeyInputWindow( pWindow );
+    }
+
+    if( pChild )
+    {
+        ImplCallCommand( pChild, COMMAND_QUERYCHARPOSITION );
+
+        ImplWinData* pWinData = pChild->ImplGetWinData();
+        if ( pWinData->mpCompositionCharRects && pEvt->mnCharPos < static_cast<sal_uLong>( 
pWinData->mnCompositionCharRects ) )
+        {
+            const Rectangle& aRect = pWinData->mpCompositionCharRects[ pEvt->mnCharPos ];
+            Rectangle aDeviceRect = pChild->ImplLogicToDevicePixel( aRect );
+            Point aAbsScreenPos = pChild->OutputToAbsoluteScreenPixel( 
pChild->ScreenToOutputPixel(aDeviceRect.TopLeft()) );
+            pEvt->mnPointX = aAbsScreenPos.X();
+            // For vertical writing, X-Y points top-right rather than top-left.
+            if ( pWinData->mbVertical != sal_False )
+                pEvt->mnPointX += aDeviceRect.GetWidth();
+            pEvt->mnPointY = aAbsScreenPos.Y();
+            pEvt->mnLineHeight = (pWinData->mbVertical != sal_False) ? aDeviceRect.GetWidth() : 
aDeviceRect.GetHeight();
+            pEvt->mbValid = true;
+        }
+    }
+}
+
+// -----------------------------------------------------------------------
+
 long ImplWindowFrameProc( Window* pWindow, SalFrame* /*pFrame*/,
                           sal_uInt16 nEvent, const void* pEvent )
 {
@@ -2659,6 +2706,9 @@
             }
             }
             break;
+        case SALEVENT_QUERYCHARPOSITION:
+            ImplHandleSalQueryCharPosition( pWindow, (SalQueryCharPositionEvent*)pEvent );
+            break;
 #ifdef DBG_UTIL
         default:
             SAL_WARN( "vcl.layout", "ImplWindowFrameProc(): unknown event (" << nEvent << ")" );
diff --git a/vcl/win/source/window/salframe.cxx b/vcl/win/source/window/salframe.cxx
index 05ecefd..36ac238 100644
--- a/vcl/win/source/window/salframe.cxx
+++ b/vcl/win/source/window/salframe.cxx
@@ -5523,6 +5523,32 @@
     return TRUE;
 }
 
+static LRESULT ImplHandleIMEQueryCharPosition( HWND hWnd, LPARAM lParam ) {
+    WinSalFrame* pFrame = GetWindowPtr( hWnd );
+    PIMECHARPOSITION pQueryCharPosition = (PIMECHARPOSITION) lParam;
+    if ( pQueryCharPosition->dwSize < sizeof(IMECHARPOSITION) )
+        return FALSE;
+
+    SalQueryCharPositionEvent aEvt;
+    aEvt.mbValid = false;
+    aEvt.mnCharPos = pQueryCharPosition->dwCharPos;
+
+    pFrame->CallCallback( SALEVENT_QUERYCHARPOSITION, (void*)&aEvt );
+
+    if ( !aEvt.mbValid )
+        return FALSE;
+
+    pQueryCharPosition->pt.x = aEvt.mnPointX;
+    pQueryCharPosition->pt.y = aEvt.mnPointY;
+    pQueryCharPosition->cLineHeight = aEvt.mnLineHeight;
+    pQueryCharPosition->rcDocument.left = aEvt.mnDocumentBoundX;
+    pQueryCharPosition->rcDocument.top = aEvt.mnDocumentBoundY;
+    pQueryCharPosition->rcDocument.right = aEvt.mnDocumentBoundX + aEvt.mnDocumentBoundWidth;
+    pQueryCharPosition->rcDocument.bottom = aEvt.mnDocumentBoundY + aEvt.mnDocumentBoundHeight;
+
+    return TRUE;
+}
+
 #endif // WINVER >= 0x0500
 
 // -----------------------------------------------------------------------
@@ -5945,11 +5971,16 @@
                 nRet = ImplHandleIMEReconvertString( hWnd, lParam );
                 rDef = FALSE;
             }
-        else if( (sal_uIntPtr)( wParam ) == IMR_CONFIRMRECONVERTSTRING )
-        {
-        nRet = ImplHandleIMEConfirmReconvertString( hWnd, lParam );
-        rDef = FALSE;
-        }
+            else if( (sal_uIntPtr)( wParam ) == IMR_CONFIRMRECONVERTSTRING )
+            {
+                nRet = ImplHandleIMEConfirmReconvertString( hWnd, lParam );
+                rDef = FALSE;
+            }
+            else if ( (sal_uIntPtr)( wParam ) == IMR_QUERYCHARPOSITION )
+            {
+                nRet = ImplHandleIMEQueryCharPosition( hWnd, lParam );
+                rDef = FALSE;
+            }
             break;
 #endif // WINVER >= 0x0500
     }

-- 
To view, visit https://gerrit.libreoffice.org/3849
To unsubscribe, visit https://gerrit.libreoffice.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I53a344a78688060004cc8bcbbf1127f22a468e20
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: master
Gerrit-Owner: Yohei Yukawa <yukawa@google.com>


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.