1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 //////////////////////////////////////////////////////////////////////
23 // AccActionBase.cpp: implementation of the CAccActionBase class.
24 //////////////////////////////////////////////////////////////////////
25 #include "stdafx.h"
26 
27 #include "AccActionBase.h"
28 #include <com/sun/star/accessibility/XAccessible.hpp>
29 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
30 #include <com/sun/star/accessibility/AccessibleRole.hpp>
31 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
32 
33 #include "AccessibleKeyStroke.h"
34 
35 #ifndef __ACCCOMMON_H_
36 #include "acccommon.h"
37 #endif
38 
39 using namespace com::sun::star::accessibility::AccessibleRole;
40 using namespace com::sun::star::accessibility;
41 using namespace com::sun::star::uno;
42 using namespace com::sun::star::awt;
43 
44 //////////////////////////////////////////////////////////////////////
45 // Construction/Destruction
46 //////////////////////////////////////////////////////////////////////
47 
48 CAccActionBase::CAccActionBase()
49 {}
50 
51 CAccActionBase::~CAccActionBase()
52 {}
53 
54 /**
55  * Helper function used for getting default action by UNO role.
56  *
57  * @param    pRContext    UNO context interface pointer.
58  * @param    pRet         the corresponding string to be returned.
59  */
60 void GetDfActionByUNORole(XAccessibleContext* pRContext, BSTR* pRet)
61 {
62     // #CHECK#
63     if(pRContext == NULL || pRet == NULL)
64     {
65         return;
66     }
67 
68     long Role = pRContext->getAccessibleRole();
69 
70     switch(Role)
71     {
72     case PUSH_BUTTON:
73         *pRet = ::SysAllocString(PRESS);
74         break;
75     case RADIO_BUTTON:
76     case MENU_ITEM:
77     case LIST_ITEM:
78         *pRet = ::SysAllocString(SELECT);
79         break;
80     case CHECK_BOX:
81         {
82             Reference< XAccessibleStateSet > pRState = pRContext->getAccessibleStateSet();
83             if( !pRState.is() )
84             {
85                 return;
86             }
87 
88             Sequence<short> pStates = pRState->getStates();
89             int count = pStates.getLength();
90             *pRet = ::SysAllocString(CHECK);
91             for( int iIndex = 0;iIndex < count;iIndex++ )
92             {
93                 if( pStates[iIndex] == AccessibleStateType::CHECKED )
94                 {
95                     SAFE_SYSFREESTRING(*pRet);
96                     *pRet = ::SysAllocString(UNCHECK);
97                     break;
98                 }
99             }
100             break;
101         }
102     }
103 }
104 
105 /**
106  * Returns the number of action.
107  *
108  * @param    nActions    the number of action.
109  */
110 STDMETHODIMP CAccActionBase::nActions(/*[out,retval]*/long* nActions)
111 {
112 
113 	CHECK_ENABLE_INF
114 
115     ENTER_PROTECTED_BLOCK
116 
117     // #CHECK#
118     if( pRXAct.is() && nActions != NULL )
119     {
120         *nActions = GetXInterface()->getAccessibleActionCount();
121         return S_OK;
122     }
123     *nActions = 0;
124 
125     return S_OK;
126 
127     LEAVE_PROTECTED_BLOCK
128 }
129 
130 /**
131  * Performs specified action on the object.
132  *
133  * @param    actionIndex    the index of action.
134  */
135 STDMETHODIMP CAccActionBase::doAction(/* [in] */ long actionIndex)
136 {
137 
138 	CHECK_ENABLE_INF
139 
140     ENTER_PROTECTED_BLOCK
141 
142     if( pRXAct.is() )
143     {
144         return GetXInterface()->doAccessibleAction( actionIndex )?S_OK:E_FAIL;
145     }
146     return E_FAIL;
147 
148     LEAVE_PROTECTED_BLOCK
149 }
150 
151 /**
152  * Gets description of specified action.
153  *
154  * @param    actionIndex    the index of action.
155  * @param    description    the description string of the specified action.
156  */
157 STDMETHODIMP CAccActionBase::get_description(long actionIndex,BSTR __RPC_FAR *description)
158 {
159 
160 	CHECK_ENABLE_INF
161 
162     ENTER_PROTECTED_BLOCK
163 
164     // #CHECK#
165     if(description == NULL)
166         return E_INVALIDARG;
167 
168     // #CHECK XInterface#
169     if(!pRXAct.is())
170         return E_FAIL;
171 
172     ::rtl::OUString ouStr = GetXInterface()->getAccessibleActionDescription(actionIndex);
173     // #CHECK#
174 
175     SAFE_SYSFREESTRING(*description);
176     *description = SysAllocString((OLECHAR*)ouStr.getStr());
177 
178     return S_OK;
179 
180     LEAVE_PROTECTED_BLOCK
181 }
182 
183 STDMETHODIMP CAccActionBase::get_name( long, BSTR __RPC_FAR *)
184 {
185     return E_NOTIMPL;
186 }
187 
188 STDMETHODIMP CAccActionBase::get_localizedName( long, BSTR __RPC_FAR *)
189 {
190     return E_NOTIMPL;
191 }
192 
193 /**
194  * Returns key binding object (if any) associated with specified action
195  * key binding is string.
196  * e.g. "alt+d" (like IAccessible::get_accKeyboardShortcut).
197  *
198  * @param    actionIndex    the index of action.
199  * @param    nMaxBinding    the max number of key binding.
200  * @param    keyBinding     the key binding array.
201  * @param    nBinding       the actual number of key binding returned.
202  */
203 STDMETHODIMP CAccActionBase::get_keyBinding(
204     /* [in] */ long actionIndex,
205     /* [in] */ long,
206     /* [length_is][length_is][size_is][size_is][out] */ BSTR __RPC_FAR *__RPC_FAR *keyBinding,
207     /* [retval][out] */ long __RPC_FAR *nBinding)
208 {
209 
210 	CHECK_ENABLE_INF
211 
212     ENTER_PROTECTED_BLOCK
213 
214     if( !keyBinding || !nBinding)
215         return E_INVALIDARG;
216 
217     if( !pRXAct.is() )
218         return E_FAIL;
219 
220     Reference< XAccessibleKeyBinding > binding = GetXInterface()->getAccessibleActionKeyBinding(actionIndex);
221     if( !binding.is() )
222         return E_FAIL;
223 
224     long nCount = (binding.get())->getAccessibleKeyBindingCount();
225 
226     OLECHAR wString[64];
227 
228     *keyBinding = (BSTR*)::CoTaskMemAlloc(nCount*sizeof(BSTR));
229 
230     // #CHECK Memory Allocation#
231     if(*keyBinding == NULL)
232         return E_FAIL;
233 
234     for( int index = 0;index < nCount;index++ )
235     {
236         memset(wString,0,sizeof(wString));
237         GetkeyBindingStrByXkeyBinding( (binding.get())->getAccessibleKeyBinding(index), wString );
238 
239         (*keyBinding)[index] = SysAllocString(wString);
240     }
241 
242     *nBinding = nCount;
243     return S_OK;
244 
245     LEAVE_PROTECTED_BLOCK
246 }
247 
248 /**
249  * Overide of IUNOXWrapper.
250  *
251  * @param    pXInterface    the pointer of UNO interface.
252  */
253 STDMETHODIMP CAccActionBase::put_XInterface(long pXInterface)
254 {
255 
256 
257     ENTER_PROTECTED_BLOCK
258 
259     CUNOXWrapper::put_XInterface(pXInterface);
260 
261     //special query.
262     if(pUNOInterface == NULL)
263         return E_FAIL;
264     Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
265     if( !pRContext.is() )
266         return E_FAIL;
267 
268     Reference<XAccessibleAction> pRXI(pRContext,UNO_QUERY);
269     if( !pRXI.is() )
270         pRXAct = NULL;
271     else
272         pRXAct = pRXI.get();
273     return S_OK;
274 
275     LEAVE_PROTECTED_BLOCK
276 }
277 
278 /**
279  * Helper function used for converting keybinding to string.
280  *
281  * @param    keySet    the key stroke sequence.
282  * @param    pString   the output keybinding string.
283  */
284 void CAccActionBase::GetkeyBindingStrByXkeyBinding( const Sequence< KeyStroke > &keySet, OLECHAR* pString )
285 {
286     // #CHECK#
287     if(pString == NULL)
288         return;
289 
290     for( int iIndex = 0;iIndex < keySet.getLength();iIndex++ )
291     {
292         KeyStroke stroke = keySet[iIndex];
293         OLECHAR wString[64] = {NULL};
294         if(iIndex>0)
295             wcscat( wString, OLESTR("  ") );
296         if((stroke.Modifiers & MODIFIER_SHIFT) == MODIFIER_SHIFT)
297             wcscat( wString, OLESTR("Shift+") );
298         if((stroke.Modifiers & MODIFIER_CTRL) == MODIFIER_CTRL)
299             wcscat( wString, OLESTR("Ctrl+") );
300         if((stroke.Modifiers & MODIFIER_ALT) == MODIFIER_ALT)
301             wcscat( wString, OLESTR("Alt+") );
302         if(stroke.KeyCode)
303         {
304             OLECHAR* pChar = getOLECHARFromKeyCode(stroke.KeyCode);
305             if(pChar != NULL)
306                 wcscat( wString, pChar );
307             else if (stroke.KeyCode <= 255)
308             {
309                 OLECHAR pChar[4] = {NULL};
310                 swprintf( pChar, L"%c", stroke.KeyCode);
311                 wcscat( wString, pChar);
312             }
313             else
314             {
315                 OLECHAR pChar[4] = {NULL};
316                 swprintf( pChar, L"%d", stroke.KeyCode);
317                 wcscat( wString, pChar);
318             }
319         }
320 
321         wcscat( pString, wString);
322     }
323 }
324 
325 /**
326  * Helper function used for converting key code to ole string.
327  *
328  * @param    key    the key code.
329  */
330 OLECHAR* CAccActionBase::getOLECHARFromKeyCode(long key)
331 {
332     static struct keyMap
333     {
334         int keyCode;
335         OLECHAR* key;
336     }
337     map[] =
338         {
339             {MODIFIER_SHIFT, L"SHIFT" },
340             {MODIFIER_CTRL, L"CTRL" },
341             {MODIFIER_ALT, L"ALT" },
342             CODEENTRY(NUM0),CODEENTRY(NUM1),CODEENTRY(NUM2),CODEENTRY(NUM3),CODEENTRY(NUM4),CODEENTRY(NUM5),
343             CODEENTRY(NUM6),CODEENTRY(NUM7),CODEENTRY(NUM8),CODEENTRY(NUM9),
344             CODEENTRY(A),CODEENTRY(B),CODEENTRY(C),CODEENTRY(D),CODEENTRY(E),CODEENTRY(F),
345             CODEENTRY(G),CODEENTRY(H),CODEENTRY(I),CODEENTRY(J),CODEENTRY(K),CODEENTRY(L),
346             CODEENTRY(M),CODEENTRY(N),CODEENTRY(O),CODEENTRY(P),CODEENTRY(Q),CODEENTRY(R),
347             CODEENTRY(S),CODEENTRY(T),CODEENTRY(U),CODEENTRY(V),CODEENTRY(W),CODEENTRY(X),
348             CODEENTRY(Y),CODEENTRY(Z),
349             CODEENTRY(F1),CODEENTRY(F2),CODEENTRY(F3),CODEENTRY(F4),CODEENTRY(F5),CODEENTRY(F6),
350             CODEENTRY(F7),CODEENTRY(F8),CODEENTRY(F9),CODEENTRY(F10),CODEENTRY(F11),CODEENTRY(F12),
351             CODEENTRY(F13),CODEENTRY(F14),CODEENTRY(F15),CODEENTRY(F16),CODEENTRY(F17),CODEENTRY(F18),
352             CODEENTRY(F19),CODEENTRY(F20),CODEENTRY(F21),CODEENTRY(F22),CODEENTRY(F23),CODEENTRY(F24),
353             CODEENTRY(F25),CODEENTRY(F26),
354 
355             { KEYCODE_DOWN, L"DOWN" },
356             { KEYCODE_UP, L"UP" },
357             { KEYCODE_LEFT, L"LEFT" },
358             { KEYCODE_RIGHT, L"RIGHT" },
359             { KEYCODE_HOME, L"HOME" },
360             { KEYCODE_END, L"END" },
361             { KEYCODE_PAGEUP, L"PAGEUP" },
362             { KEYCODE_PAGEDOWN, L"PAGEDOWN" },
363             { KEYCODE_RETURN, L"RETURN" },
364             { KEYCODE_ESCAPE, L"ESCAPE" },
365             { KEYCODE_TAB, L"TAB" },
366             { KEYCODE_BACKSPACE, L"BACKSPACE" },
367             { KEYCODE_SPACE, L"SPACE" },
368             { KEYCODE_INSERT, L"INSERT" },
369             { KEYCODE_DELETE, L"DELETE" },
370             { KEYCODE_ADD, L"ADD" },
371             { KEYCODE_SUBTRACT, L"SUBTRACT" },
372             { KEYCODE_MULTIPLY, L"MULTIPLY" },
373             { KEYCODE_DIVIDE, L"DIVIDE" },
374             { KEYCODE_POINT, L"POINT" },
375             { KEYCODE_COMMA, L"COMMA" },
376             { KEYCODE_LESS, L"LESS" },
377             { KEYCODE_GREATER, L"GREATER" },
378             { KEYCODE_EQUAL, L"EQUAL" },
379             { KEYCODE_OPEN, L"OPEN" },
380             { KEYCODE_CUT, L"CUT" },
381             { KEYCODE_COPY, L"COPY" },
382             { KEYCODE_PASTE, L"PASTE" },
383             { KEYCODE_UNDO, L"UNDO" },
384             { KEYCODE_REPEAT, L"REPEAT" },
385             { KEYCODE_FIND, L"FIND" },
386             { KEYCODE_PROPERTIES, L"PROPERTIES" },
387             { KEYCODE_FRONT, L"FRONT" },
388             { KEYCODE_CONTEXTMENU, L"CONTEXTMENU" },
389             { KEYCODE_HELP, L"HELP" },
390         };
391     static long nCount = countof(map);
392 
393     long min = 0;
394     long max = nCount-1;
395     long mid = nCount/2;
396     while(min<max)
397     {
398         if(key<map[mid].keyCode)
399             max = mid-1;
400         else if(key>map[mid].keyCode)
401             min = mid+1;
402         else
403             break;
404         mid = (min+max)/2;
405     }
406 
407     if(key == map[mid].keyCode)
408     {
409         return map[mid].key;
410     }
411     else
412     {
413         return NULL;
414     }
415 }
416 
417