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 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_automation.hxx"
26 #include <osl/mutex.hxx>
27 
28 #include <vcl/window.hxx>
29 #include <vcl/vclevent.hxx>
30 #include <vcl/button.hxx>
31 #include <vcl/edit.hxx>
32 #include <vcl/spinfld.hxx>
33 #include <vcl/msgbox.hxx>
34 #include <vcl/toolbox.hxx>
35 #include <vcl/lstbox.hxx>
36 #include <vcl/sound.hxx>
37 #include <vcl/combobox.hxx>
38 #include <vcl/floatwin.hxx>
39 #include <basic/ttstrhlp.hxx>
40 #include "statemnt.hxx"
41 #include "retstrm.hxx"
42 #include "rcontrol.hxx"
43 #include "recorder.hxx"
44 
45 #include <comphelper/uieventslogger.hxx>
46 
47 MacroRecorder* MacroRecorder::pMacroRecorder = NULL;
48 
49 MacroRecorder::MacroRecorder()
50 : pLastWin( NULL )
51 , pEditModify( NULL )
52 , pActionParent( NULL )
53 , aKeyUniqueID()
54 , pKeyWin( NULL )
55 , bKeyFollowFocus( sal_False )
56 , m_bRecord( sal_False )
57 , m_bLog( sal_False )
58 {
59     aHookRefresh.SetTimeout( 500 );
60     aHookRefresh.SetTimeoutHdl( LINK( this, MacroRecorder, HookRefreshHdl) );
61     aHookRefresh.Start();
62     aEventListenerHdl = LINK( this, MacroRecorder, EventListener );
63     AddEventHooks();
64 }
65 
66 MacroRecorder::~MacroRecorder()
67 {
68     aHookRefresh.Stop();
69     RemoveEventHooks();
70 }
71 
72 void MacroRecorder::AddEventHooks()
73 {
74     Window *pTopLevel = Application::GetFirstTopLevelWindow();
75     while ( pTopLevel )
76 	{
77         Window *pParent = pTopLevel;
78         while ( pParent->GetParent() )
79             pParent = pParent->GetParent();
80 
81         pParent->RemoveChildEventListener( aEventListenerHdl );     // might be instrumented already
82         pParent->AddChildEventListener( aEventListenerHdl );
83 
84         pTopLevel = Application::GetNextTopLevelWindow( pTopLevel );
85 	}
86 }
87 
88 void MacroRecorder::RemoveEventHooks()
89 {
90     Window *pTopLevel = Application::GetFirstTopLevelWindow();
91     while ( pTopLevel )
92 	{
93         pTopLevel->RemoveChildEventListener( aEventListenerHdl );
94 		pTopLevel = Application::GetNextTopLevelWindow( pTopLevel );
95 	}
96 }
97 
98 IMPL_LINK( MacroRecorder, HookRefreshHdl, void*, EMPTYARG )
99 {
100     AddEventHooks();
101     return 0;
102 }
103 
104 void MacroRecorder::LogVCL( rtl::OString aParentID, sal_uInt16 nVCLWindowType, rtl::OString aID, String aMethod, sal_uInt16 nParam )
105 {
106     ::comphelper::UiEventsLogger::logVcl( Id2Str( aParentID ), nVCLWindowType, Id2Str( aID ), aMethod, nParam );
107 }
108 
109 void MacroRecorder::LogVCL( rtl::OString aParentID, sal_uInt16 nVCLWindowType, rtl::OString aID, String aMethod )
110 {
111     ::comphelper::UiEventsLogger::logVcl( Id2Str( aParentID ), nVCLWindowType, Id2Str( aID ), aMethod );
112 }
113 
114 Window* MacroRecorder::GetParentWithID( Window* pThis )
115 {
116     Window *pOverlap = pThis->GetWindow( WINDOW_OVERLAP );
117     while ( pOverlap != pThis && !pThis->GetUniqueOrHelpId().getLength() && pThis->GET_REAL_PARENT() )
118         pThis = pThis->GET_REAL_PARENT();
119     return pThis;
120 }
121 
122 rtl::OString MacroRecorder::GetParentID( Window* pThis )
123 {
124     if ( pThis->GetParent() )
125         return pThis->GetParent()->GetUniqueOrHelpId();
126     else
127         return rtl::OString();
128 }
129 
130 IMPL_LINK( MacroRecorder, EventListener, VclSimpleEvent*, pEvent )
131 {
132     sal_Bool bSendData = sal_False;
133 
134     if ( pEvent->ISA( VclWindowEvent ) )
135     {
136         VclWindowEvent* pWinEvent = ( VclWindowEvent* ) pEvent;
137         Window* pWin = pWinEvent->GetWindow();
138         sal_uLong nEventID = pWinEvent->GetId();
139 #if OSL_DEBUG_LEVEL > 1
140         if ( nEventID >= 1001 && nEventID != VCLEVENT_WINDOW_KEYUP )
141             nEventID = pWinEvent->GetId();  // Just something to set a breakpoint
142         else
143             return 0;
144 #endif
145 
146 // check for different action after collecting keys
147         // send if there_is_something_to_send
148         // and eather event_is_not_of_interest
149         //     or ( new_window and new_window_is_interesting )    ( ignore interesting events to uninteresting window )
150 
151         if (  aKeyString.Len()
152             && (  ( nEventID != VCLEVENT_WINDOW_KEYINPUT
153                  && nEventID != VCLEVENT_WINDOW_MOUSEMOVE
154                  && nEventID != VCLEVENT_WINDOW_COMMAND
155                  && nEventID != VCLEVENT_WINDOW_KEYUP )
156                 || ( pKeyWin != pWin
157                     && ( pWin->GetType() == WINDOW_CONTROL || pWin->GetType() == WINDOW_WINDOW )
158                    )
159                )
160            )
161         {
162 			if ( m_bRecord )
163 			{
164 				// we cannot access pKeyWin since it might have dissapeared
165 				if ( bKeyFollowFocus )
166 					StatementList::pRet->GenReturn( RET_MacroRecorder, aKeyUniqueID, (sal_uInt16)M_TypeKeys, aKeyString, bKeyFollowFocus );
167 				else
168 					StatementList::pRet->GenReturn( RET_MacroRecorder, aKeyUniqueID, (sal_uInt16)M_TypeKeys, aKeyString );
169 #if OSL_DEBUG_LEVEL > 1
170                 StatementList::pRet->GenReturn( RET_MacroRecorder, aKeyUniqueID, (sal_uInt16)M_TypeKeys, String::CreateFromInt32( nEventID ) );
171 #endif
172 				bSendData = sal_True;
173 			}
174 			if ( m_bLog )
175 			{
176 //  HACK Too many KeyEvents generated              LogVCL( rtl::OString(), 0, aKeyUniqueID, CUniString("TypeKeys"), aKeyString.Len() );
177 			}
178             // cleanup
179             aKeyString.Erase();
180             pKeyWin = NULL;
181             bKeyFollowFocus = sal_False;
182         }
183 
184         switch ( pWin->GetType() )
185         {
186 			case WINDOW_TABPAGE:
187 				switch( nEventID )
188 				{
189 					case VCLEVENT_WINDOW_ACTIVATE:
190 						if ( m_bRecord )
191 						{
192 							StatementList::pRet->GenReturn( RET_MacroRecorder, rtl::OString(), (comm_USHORT)(M_SetPage|M_RET_NUM_CONTROL), Id2Str( pWin->GetUniqueOrHelpId() ) );
193 							bSendData = sal_True;
194 						}
195 						if ( m_bLog )
196 						{
197                             LogVCL( rtl::OString(), pWin->GetType(), pWin->GetUniqueOrHelpId(), CUniString("SetPage") );
198 						}
199 						break;
200 				}
201 				break;
202 			case WINDOW_RADIOBUTTON:
203 			case WINDOW_IMAGERADIOBUTTON:
204 				switch( nEventID )
205 				{
206                     case VCLEVENT_BUTTON_CLICK:  // VCLEVENT_RADIOBUTTON_TOGGLE
207                         {
208                             if ( ((RadioButton*)pWin)->IsChecked() )
209                             {
210 								if ( m_bRecord )
211 								{
212 									StatementList::pRet->GenReturn( RET_MacroRecorder, pWin->GetUniqueOrHelpId(), (comm_USHORT)M_Check );
213 									bSendData = sal_True;
214 								}
215 								if ( m_bLog )
216 								{
217                                     LogVCL( GetParentID( pWin ), pWin->GetType(), pWin->GetUniqueOrHelpId(), CUniString("Check") );
218 								}
219                             }
220                         }
221 						break;
222 				}
223 				break;
224 			case WINDOW_CHECKBOX:
225 			case WINDOW_TRISTATEBOX:
226 				switch( nEventID )
227 				{
228                     case VCLEVENT_BUTTON_CLICK: //VCLEVENT_CHECKBOX_TOGGLE:
229                         {
230                             comm_USHORT nMethod;
231                             String aMethod;
232                             switch ( ((TriStateBox*)pWin)->GetState() )
233                             {
234                                 case STATE_CHECK: nMethod = M_Check; aMethod = CUniString("Check"); break;
235                                 case STATE_NOCHECK: nMethod = M_UnCheck; aMethod = CUniString("UnCheck"); break;
236                                 case STATE_DONTKNOW: nMethod = M_TriState; aMethod = CUniString("TriState"); break;
237                                 default: nMethod = M_Check;
238                                     DBG_ERROR( "Unknown state in TriStateBox::GetState()" );
239                             }
240 							if ( m_bRecord )
241 							{
242 								StatementList::pRet->GenReturn( RET_MacroRecorder, pWin->GetUniqueOrHelpId(), nMethod );
243 								bSendData = sal_True;
244 							}
245 							if ( m_bLog )
246 							{
247                                 LogVCL( GetParentID( pWin ), pWin->GetType(), pWin->GetUniqueOrHelpId(), aMethod );
248 							}
249                         }
250                         break;
251 				}
252 				break;
253 			case WINDOW_EDIT:
254 			case WINDOW_MULTILINEEDIT:
255 				switch( nEventID )
256 				{
257 					case VCLEVENT_EDIT_MODIFY:
258                         pEditModify = pWin;
259                         aEditModifyString = ((Edit*)pWin)->GetText();
260 						break;
261 				}
262 				break;
263 			case WINDOW_MULTILISTBOX:
264 				switch( nEventID )
265 				{
266                     case VCLEVENT_LISTBOX_SELECT:
267                         Sound::Beep();
268                 }
269 			case WINDOW_LISTBOX:
270 				switch( nEventID )
271 				{
272 //                    case VCLEVENT_LISTBOX_DOUBLECLICK:
273                     case VCLEVENT_LISTBOX_SELECT:
274 						if ( m_bRecord )
275 						{
276 							StatementList::pRet->GenReturn( RET_MacroRecorder, pWin->GetUniqueOrHelpId(), (comm_USHORT)M_Select, comm_ULONG( ((ListBox*)pWin)->GetSelectEntryPos() +1 ) );
277 							bSendData = sal_True;
278 						}
279 						if ( m_bLog )
280 						{
281                             LogVCL( GetParentID( pWin ), pWin->GetType(), pWin->GetUniqueOrHelpId(), CUniString("Select"), ((ListBox*)pWin)->GetSelectEntryPos() );
282 						}
283 						break;
284 				}
285 				break;
286 			case WINDOW_COMBOBOX:
287 			case WINDOW_PATTERNBOX:
288 			case WINDOW_NUMERICBOX:
289 			case WINDOW_METRICBOX:
290 			case WINDOW_CURRENCYBOX:
291 			case WINDOW_DATEBOX:
292 			case WINDOW_TIMEBOX:
293                 switch( nEventID )
294 				{
295 					case VCLEVENT_EDIT_MODIFY:
296                         pEditModify = pWin;
297                         aEditModifyString = ((Edit*)pWin)->GetText();
298 						break;
299                     case VCLEVENT_COMBOBOX_SELECT:
300                         {
301                             pEditModify = NULL;
302                             aEditModifyString.Erase();
303 
304                             sal_uInt16 nPos = ((ComboBox*)pWin)->GetEntryPos(((ComboBox*)pWin)->GetText());
305 							if ( m_bRecord )
306 							{
307 								if ( nPos == COMBOBOX_ENTRY_NOTFOUND )
308 									Sound::Beep();
309 								else
310 								{
311 									StatementList::pRet->GenReturn( RET_MacroRecorder, pWin->GetUniqueOrHelpId(), (comm_USHORT)M_Select, (comm_ULONG) nPos+1 );
312 									bSendData = sal_True;
313 								}
314 							}
315 							if ( m_bLog )
316 							{
317                                 LogVCL( GetParentID( pWin ), pWin->GetType(), pWin->GetUniqueOrHelpId(), CUniString("Select"), nPos );
318 							}
319                         }
320 				}
321 				break;
322 			case WINDOW_PUSHBUTTON:
323 			case WINDOW_OKBUTTON:
324 			case WINDOW_CANCELBUTTON:
325 			case WINDOW_IMAGEBUTTON:
326             case WINDOW_MOREBUTTON:
327             case WINDOW_HELPBUTTON:
328 				switch( nEventID )
329 				{
330 					case VCLEVENT_BUTTON_CLICK:
331                         Window* pParent = pWin->GetParent();
332                         sal_Bool bDone = sal_False;
333                         if ( pParent->IsDialog() && !pWin->GetUniqueOrHelpId().getLength() )
334                         {
335                             switch ( pParent->GetType() )
336                             {
337                                 case WINDOW_MESSBOX:
338                                 case WINDOW_INFOBOX:
339                                 case WINDOW_WARNINGBOX:
340                                 case WINDOW_ERRORBOX:
341                                 case WINDOW_QUERYBOX:
342                                 case WINDOW_BUTTONDIALOG:
343                                     {
344                                         comm_USHORT nMethod;
345                                         String aMethod;
346                                         ButtonDialog* pBD = (ButtonDialog*)pParent;
347 
348                                         // we have to find the current Button ID ourselves since it is not generated at this point :-(
349                                         sal_uInt16 nCurrentButtonId = 0xffff;    // Some wild value to wak up people
350 				                        sal_uInt16 i;
351 				                        for ( i = 0; i < pBD->GetButtonCount() ; i++ )
352 				                        {
353 					                        if ( pBD->GetPushButton( pBD->GetButtonId(i) ) == pWin )
354                                             {
355                                                 nCurrentButtonId = pBD->GetButtonId(i);
356                                                 break;
357                                             }
358                                         }
359 
360                                         switch ( nCurrentButtonId )
361                                         {
362                                             case BUTTONID_OK: nMethod = M_OK; aMethod = CUniString("OK"); break;
363                                             case BUTTONID_CANCEL: nMethod = M_Cancel; aMethod = CUniString("Cancel"); break;
364                                             case BUTTONID_YES: nMethod = M_Yes; aMethod = CUniString("Yes"); break;
365                                             case BUTTONID_NO: nMethod = M_No; aMethod = CUniString("No"); break;
366                                             case BUTTONID_RETRY: nMethod = M_Repeat; aMethod = CUniString("Repeat"); break;
367                                             case BUTTONID_HELP: nMethod = M_Help; aMethod = CUniString("Help"); break;
368                                             default: nMethod = M_Click; aMethod = CUniString("Click");
369                                         }
370 										if ( m_bRecord )
371 										{
372 											if ( nMethod != M_Click )
373 												StatementList::pRet->GenReturn( RET_MacroRecorder, UID_ACTIVE, nMethod );
374 											else
375 												StatementList::pRet->GenReturn( RET_MacroRecorder, UID_ACTIVE, nMethod, (comm_ULONG)nCurrentButtonId );
376 											bSendData = sal_True;
377 										}
378 										if ( m_bLog )
379 										{
380 											if ( nMethod != M_Click )
381                                                 LogVCL( rtl::OString(), pWin->GetType(), pWin->GetUniqueOrHelpId(), aMethod );
382                                             else
383                                                 LogVCL( rtl::OString(), pWin->GetType(), pWin->GetUniqueOrHelpId(), aMethod, nCurrentButtonId );
384                                             bDone = sal_True;
385 										}
386                                     }
387                                     break;
388                                 default:
389                                     {
390                                         comm_USHORT nMethod;
391                                         String aMethod;
392                                         switch ( pWin->GetType() )
393                                         {
394 			                                case WINDOW_OKBUTTON: nMethod = M_OK; aMethod = CUniString("OK"); break;
395 			                                case WINDOW_CANCELBUTTON: nMethod = M_Cancel; aMethod = CUniString("Cancel"); break;
396                                             case WINDOW_HELPBUTTON: nMethod = M_Help; aMethod = CUniString("Help"); break;
397                                             default: nMethod = M_Default;aMethod = CUniString("Unknown Button");
398                                                 DBG_ERROR( "Unknown Button" );
399                                         }
400 										if ( m_bRecord )
401 										{
402 											StatementList::pRet->GenReturn( RET_MacroRecorder, pParent->GetUniqueOrHelpId(), nMethod );
403 											bSendData = sal_True;
404 										}
405 										if ( m_bLog )
406 										{
407                                             LogVCL( GetParentID( pWin ), pWin->GetType(), pWin->GetUniqueOrHelpId(), aMethod );
408                                             bDone = sal_True;
409 										}
410                                     }
411                                     break;
412                             }
413                         }
414 						if ( m_bRecord )
415 						{
416 							if ( !bSendData && pWin->GetUniqueOrHelpId().getLength() )
417 							{
418 								StatementList::pRet->GenReturn( RET_MacroRecorder, pWin->GetUniqueOrHelpId(), (comm_USHORT)M_Click );
419 								bSendData = sal_True;
420 							}
421 						}
422                         if ( m_bLog )
423                         {
424                             if ( !bDone )
425                                 LogVCL( GetParentID( pWin ), pWin->GetType(), pWin->GetUniqueOrHelpId(), CUniString("Click") );
426                         }
427 				}
428 				break;
429 /*			case C_MoreButton:
430 				switch( nEventID )
431 				{
432 					case M_IsOpen :
433 						pRet->GenReturn ( RET_Value, nUId, ((MoreButton*)pControl)->GetState());
434 						break;
435 					case M_Click :
436 						((MoreButton*)pControl)->Click();
437 						break;
438 					case M_Open :
439 						((MoreButton*)pControl)->SetState(sal_True);
440 						break;
441 					case M_Close :
442 						((MoreButton*)pControl)->SetState(sal_False);
443 						break;
444 					default:
445 						ReportError( nUId, GEN_RES_STR2c2( S_UNKNOWN_METHOD, MethodString(nMethodId), "MoreButton" ) );
446 						break;
447 				}
448 				break;*/
449 			case WINDOW_SPINFIELD:
450 			case WINDOW_PATTERNFIELD:
451 			case WINDOW_NUMERICFIELD:
452 			case WINDOW_METRICFIELD:
453 			case WINDOW_CURRENCYFIELD:
454 			case WINDOW_DATEFIELD:
455 			case WINDOW_TIMEFIELD:
456 				switch( nEventID )
457 				{
458 					case VCLEVENT_SPINFIELD_UP:
459 					case VCLEVENT_SPINFIELD_DOWN:
460 					case VCLEVENT_SPINFIELD_FIRST:
461 					case VCLEVENT_SPINFIELD_LAST:
462                         {
463                             pEditModify = NULL;
464                             aEditModifyString.Erase();
465 
466                             comm_USHORT nMethod;
467                             String aMethod;
468                             switch ( nEventID )
469                             {
470                                 case VCLEVENT_SPINFIELD_UP: nMethod = M_More; aMethod = CUniString("More"); break;
471                                 case VCLEVENT_SPINFIELD_DOWN: nMethod = M_Less; aMethod = CUniString("Less"); break;
472                                 case VCLEVENT_SPINFIELD_FIRST: nMethod = M_ToMin; aMethod = CUniString("ToMin"); break;
473                                 case VCLEVENT_SPINFIELD_LAST: nMethod = M_ToMax; aMethod = CUniString("ToMax"); break;
474                                 default: nMethod = M_ToMin; aMethod = CUniString("Unknown");
475                                     DBG_ERROR( "Unknown EventID in Spinfield" );
476                             }
477 							if ( m_bRecord )
478 							{
479 								StatementList::pRet->GenReturn( RET_MacroRecorder, pWin->GetUniqueOrHelpId(), nMethod );
480 								bSendData = sal_True;
481 							}
482                             if ( m_bLog )
483                             {
484                                 LogVCL( GetParentID( pWin ), pWin->GetType(), pWin->GetUniqueOrHelpId(), aMethod );
485                             }
486                         }
487                         break;
488 					case VCLEVENT_EDIT_MODIFY:
489                         pEditModify = pWin;
490                         aEditModifyString = ((SpinField*)pWin)->GetText();
491                         break;
492 				}
493 				break;
494 
495 			case WINDOW_MENUBUTTON:
496 					switch( nEventID )
497 					{
498 					case VCLEVENT_BUTTON_CLICK:
499 						if ( m_bRecord )
500 						{
501 							StatementList::pRet->GenReturn( RET_MacroRecorder, pWin->GetUniqueOrHelpId(), (comm_USHORT)M_Click );
502 							bSendData = sal_True;
503 						}
504                         if ( m_bLog )
505                         {
506                             LogVCL( GetParentID( pWin ), pWin->GetType(), pWin->GetUniqueOrHelpId(), CUniString("Click") );
507                         }
508 						break;
509 /*      Keyevent or Timeout
510 					case M_Open :
511 						{
512 							MouseEvent aMEvnt;
513 							Point aPt( pControl->GetSizePixel().Width() / 2, pControl->GetSizePixel().Height() / 2 );
514 							aMEvnt = MouseEvent( aPt,1,MOUSE_SIMPLECLICK,MOUSE_LEFT );
515 							ImplMouseButtonDown( pControl, aMEvnt );
516 
517 							sal_uLong nStart = Time::GetSystemTicks();
518 							sal_uLong nDelay = pControl->GetSettings().GetMouseSettings().GetActionDelay();
519 							while ( ( Time::GetSystemTicks() - nStart ) < nDelay + 100 )
520 								SafeReschedule();
521 
522 							ImplMouseButtonUp  ( pControl, aMEvnt );
523 						}
524 						break;*/
525                     }
526 				break;
527 			case WINDOW_TOOLBOX:
528                 {
529 				    ToolBox *pTB = ((ToolBox*)pWin);
530 				    switch( nEventID )
531 				    {
532                         case VCLEVENT_TOOLBOX_SELECT:
533                             {   // a Button has been clicked
534                                 // so this cannot be a tearoff or OpenMenu anymore
535                                 pActionParent = NULL;
536                                 // compare to 1 for floating ToolBoxes
537 								if ( m_bRecord )
538 								{
539 									if ( !pWin->GetUniqueOrHelpId().getLength() /* || pWin->GetUniqueOrHelpId().Matches( 1 ) */ )
540 										// generate direct Button access
541 										StatementList::pRet->GenReturn( RET_MacroRecorder, Str2Id( pTB->GetItemCommand( pTB->GetCurItemId() ) ), (comm_USHORT)(M_Click) );
542 									else
543 										// access via Toolbox
544 										StatementList::pRet->GenReturn( RET_MacroRecorder, pTB->GetUniqueOrHelpId(), (comm_USHORT)(M_Click|M_RET_NUM_CONTROL), Id2Str( pTB->GetHelpId( pTB->GetCurItemId() ) ) );
545 									bSendData = sal_True;
546 								}
547 /* not needed                               if ( m_bLog )
548                                 {
549                                 }*/
550                             }
551 						    break;
552                         case VCLEVENT_TOOLBOX_CLICK:  /// ATTENTION this is called during initialisation of toolbox. whoever 'invented' this
553                             pActionParent = pTB;
554                             break;
555 //                        case VCLEVENT_WINDOW_SHOW:        // not usable ATM. see above
556 //                            if ( pActionParent )
557 //                            {   // a new toolbox opens up, might be a tearoff
558 //                                if ( pActionParent != pWin )
559 //                                {   // it IS a tearoff not an undock
560 //                                    // compare to 1 for floating ToolBoxes
561 //									if ( m_bRecord )
562 //									{
563 //										if ( !pWin->GetSmartUniqueOrHelpId().HasAny() || pWin->GetSmartUniqueOrHelpId().Matches( 1 ) )
564 //											// generate direct Button access
565 //											StatementList::pRet->GenReturn( RET_MacroRecorder, rtl::OString( pActionParent->GetHelpId( pActionParent->GetCurItemId() ) ), (comm_USHORT)(M_TearOff) );
566 //										else
567 //											// access via Toolbox
568 //											StatementList::pRet->GenReturn( RET_MacroRecorder, pActionParent->GetSmartUniqueOrHelpId(), (comm_USHORT)(M_TearOff|M_RET_NUM_CONTROL), static_cast<comm_ULONG>(pActionParent->GetHelpId( pActionParent->GetCurItemId() )) ); // GetHelpId() sal_uLong != comm_ULONG on 64bit
569 //										bSendData = sal_True;
570 //									}
571 //                                    if ( m_bLog )
572 //                                    {
573 //                                        LogVCL( pActionParent->GetSmartUniqueOrHelpId(), pWin->GetType(), pActionParent->GetHelpId( pActionParent->GetCurItemId() ), CUniString("TearOff") );
574 //                                    }
575 //                                }
576 //                                pActionParent = NULL;
577 //                            }
578 //                            break;
579                         case VCLEVENT_TOOLBOX_DEACTIVATE:
580                             pActionParent = NULL;
581                             break;
582                     }
583                 }
584                 break;
585 /*					ToolBox *pTB = ((ToolBox*)pControl);
586 					if ( pTB->GetUniqueOrHelpId() != nUId )	// Also Button auf der ToolBox gefunden
587 					{
588 						if ( nParams == PARAM_NONE )
589 						{			// Wir f�lschen einen Parameter
590 							nParams = PARAM_USHORT_1;
591 							nNr1 = nUId;
592 						}
593 						else
594 							ReportError( nUId, GEN_RES_STR1( S_INTERNAL_ERROR, MethodString( nMethodId ) ) );
595 					}
596 
597 #define FIND_HELP\
598 {\
599 	if( nParams == PARAM_USHORT_1 )\
600 		nLNr1 = nNr1;\
601 	for ( nNr1 = 0; nNr1 < pTB->GetItemCount() && nLNr1 != pTB->GetHelpId(pTB->GetItemId(nNr1)) ; nNr1++ ) {}\
602 	bBool1 = nLNr1 == pTB->GetHelpId(pTB->GetItemId(nNr1));\
603 	if ( !bBool1 )\
604 		ReportError( nUId, GEN_RES_STR1( S_HELPID_ON_TOOLBOX_NOT_FOUND, MethodString( nMethodId ) ) );\
605 	else\
606 	{\
607 		if ( !pTB->IsItemEnabled( pTB->GetItemId(nNr1) ) && nMethodId != _M_IsEnabled )\
608 		{\
609 			ReportError( nUId, GEN_RES_STR1( S_BUTTON_DISABLED_ON_TOOLBOX, MethodString( nMethodId ) ) );\
610 			bBool1 = sal_False;\
611 		}\
612 		else if ( !pTB->IsItemVisible( pTB->GetItemId(nNr1) ) )\
613 		{\
614 			ReportError( nUId, GEN_RES_STR1( S_BUTTON_HIDDEN_ON_TOOLBOX, MethodString( nMethodId ) ) );\
615 			bBool1 = sal_False;\
616 		}\
617 		else\
618 		{\
619 			if ( pTB->GetItemRect(pTB->GetItemId(nNr1)).IsEmpty() )\
620 			{\
621 				sal_uInt16 nLine = pTB->GetCurLine();\
622 				do\
623 				{\
624 					pTB->ShowLine( sal_False );\
625 					for ( int i = 1 ; i < 30 ; i++ )\
626 						SafeReschedule();\
627 				}\
628 				while ( pTB->GetCurLine() != nLine && pTB->GetItemRect(pTB->GetItemId(nNr1)).IsEmpty() );\
629 				pTB->Invalidate( pTB->GetScrollRect() );\
630 			}\
631 			if ( pTB->GetItemRect(pTB->GetItemId(nNr1)).IsEmpty() )\
632 			{\
633 				ReportError( nUId, GEN_RES_STR1( S_CANNOT_MAKE_BUTTON_VISIBLE_IN_TOOLBOX, MethodString( nMethodId ) ) );\
634 				bBool1 = sal_False;\
635 			}\
636 		}\
637 	}\
638 }\
639 
640 					switch( nEventID )
641 					{
642 						case M_SetNextToolBox :
643 							if ( (nParams & PARAM_STR_1) )
644 								pTB->SetNextToolBox( aString1 );
645 							else
646 								pTB->SetNextToolBox( pTB->GetNextToolBox() );
647 							pTB->NextToolBox();
648 							break;
649 						case M_GetNextToolBox :
650 							pRet->GenReturn ( RET_Value, nUId, (String)pTB->GetNextToolBox());
651 							break;
652 						default:
653 							ReportError( nUId, GEN_RES_STR2c2( S_UNKNOWN_METHOD, MethodString(nMethodId), "ToolBox" ) );
654 							break;
655 					}
656 				}
657 				break;
658 */
659 			case WINDOW_CONTROL:
660 			case WINDOW_WINDOW:
661 				switch( nEventID )
662                 {
663                     case VCLEVENT_WINDOW_COMMAND:
664                         break;
665                     case VCLEVENT_WINDOW_KEYINPUT:
666                         {
667                             const KeyEvent *pKeyEvent = ((KeyEvent*)pWinEvent->GetData());
668                             const KeyCode aKeyCode = pKeyEvent->GetKeyCode();
669                             if ( pKeyEvent )
670                             {
671                                 pKeyWin = pWin;
672                                 Window *pIdWin = GetParentWithID( pWin );
673 								if ( pIdWin != pWin )
674                                    bKeyFollowFocus = sal_True;
675                                 aKeyUniqueID = pIdWin->GetUniqueOrHelpId();
676 		                        if ( m_bLog )
677 		                        {
678 //   HACK Too many KeyEvents generated                                 if ( aKeyString.Len() == 0 )
679 //   HACK Too many KeyEvents generated                                     LogVCL( rtl::OString(), 0, aKeyUniqueID, CUniString("TypeKeysStart") );
680 		                        }
681 						        if ( ( !aKeyCode.IsMod1() && !aKeyCode.IsMod2() ) &&
682 							          (( aKeyCode.GetGroup() == KEYGROUP_NUM)   ||
683 							           ( aKeyCode.GetGroup() == KEYGROUP_ALPHA) ||
684 							           ( aKeyCode.GetCode() == KEY_SPACE) ||
685 							           ( aKeyCode.GetCode() == KEY_ADD) ||
686 							           ( aKeyCode.GetCode() == KEY_SUBTRACT) ||
687 							           ( aKeyCode.GetCode() == KEY_MULTIPLY) ||
688 							           ( aKeyCode.GetCode() == KEY_DIVIDE) ||
689 							           ( aKeyCode.GetCode() == KEY_POINT) ||
690 							           ( aKeyCode.GetCode() == KEY_COMMA) ||
691 							           ( aKeyCode.GetCode() == KEY_EQUAL) ||
692 							           ( aKeyCode.GetCode() == 0) ) )
693                                 {
694                                     DBG_ASSERT( pKeyEvent->GetCharCode(), "no charcode found" );
695                                     aKeyString += pKeyEvent->GetCharCode();
696                                 }
697                                 else
698                                 {   // not a regular key, transfer KeyCode
699                                     aKeyString += sal_Unicode(1);   // mask it
700                                     // extra for '>' which is coded as <SHIFT GREATER>
701 							        if ( pKeyEvent->GetCharCode() == '>' )
702                                         aKeyString += sal_Unicode( KEY_GREATER | (aKeyCode.GetAllModifier() & ~KEY_SHIFT) );
703                                     else
704                                         aKeyString += sal_Unicode( aKeyCode.GetCode() | aKeyCode.GetAllModifier() );
705                                 }
706                             }
707                         }
708                         break;
709 
710                     case VCLEVENT_WINDOW_MOUSEMOVE:
711                     case VCLEVENT_WINDOW_MOUSEBUTTONDOWN:
712                     case VCLEVENT_WINDOW_MOUSEBUTTONUP:
713                         {
714                         }
715                         break;
716 
717 
718                 }
719                 break;
720   		    case WINDOW_DOCKINGWINDOW:
721 //                switch( nEventID )
722 				{
723 //					case 1 .. 0xffff:
724     DBG_TRACE3( "TT_VCLMessage %u %u  %X",nEventID, pWin->GetType(), pWin );
725 //						sal_Bool bx = ((DockingWindow*)pWin)->IsFloatingMode();
726 //						break;
727 /*					case M_Dock :
728 						if ( ((DockingWindow*)pControl)->IsFloatingMode() )
729 							((DockingWindow*)pControl)->SetFloatingMode(sal_False);
730 						else
731 							ReportError( nUId, GEN_RES_STR1( S_ALLOWED_ONLY_IN_FLOATING_MODE, MethodString( nMethodId ) ) );
732 						break;
733 					case M_Undock :
734 						if ( !((DockingWindow*)pControl)->IsFloatingMode() )
735 							((DockingWindow*)pControl)->SetFloatingMode(sal_True);
736 						else
737 							ReportError( nUId, GEN_RES_STR1( S_ALLOWED_ONLY_IN_FLOATING_MODE, MethodString( nMethodId ) ) );
738 						break;
739 					case M_IsDocked :
740 						pRet->GenReturn ( RET_Value, nUId, (comm_BOOL) !((DockingWindow*)pControl)->IsFloatingMode());
741 						break;
742 					case M_Close:
743 							//nWindowWaitUId = nUId;
744 						DBG_ASSERT( nUId == pControl->GetUniqueOrHelpId(), "nUID != UniqueOrHelpId");
745 						SET_WINP_CLOSING(pControl);
746 						((DockingWindow*)pControl)->Close();
747 						break;
748 					case M_Size:
749 					case M_Move:
750 					case M_IsMax :
751 					case M_Minimize :
752 					case M_Maximize :
753 						if ( ((DockingWindow*)pControl)->IsFloatingMode() )
754 						{
755 							pControl = ((DockingWindow*)pControl)->GetFloatingWindow();
756 							goto FloatWin;
757 						}
758 						else
759 							ReportError( nUId, GEN_RES_STR1( S_ALLOWED_ONLY_IN_DOCKING_MODE, MethodString( nMethodId ) ) );
760 						break;
761 					case M_Help:		// Alles was unten weiterbehandelt werden soll
762 						goto MoreDialog;
763 
764 					default:
765 						ReportError( nUId, GEN_RES_STR2c2( S_UNKNOWN_METHOD, MethodString(nMethodId), "DockingWindow" ) );
766 						break;*/
767 				}
768 				break;
769 
770 
771 
772 
773 
774 
775 			case WINDOW_FLOATINGWINDOW:
776                 {
777     DBG_TRACE3( "TT_VCLMessage %u %u  %X",nEventID, pWin->GetType(), pWin );
778 //                    FloatingWindow *pFW = ((FloatingWindow*)pWin);
779 /*				    switch( nEventID )
780 				    {
781 
782 // M_OpenMenu an einem ToolboxButton
783                         case VCLEVENT_WINDOW_SHOW:
784                             if ( pActionParent )
785                             {   // a new FloatingWindow opens up, so we assume an OpenMenu
786                                 // compare to 1 for floating ToolBoxes
787                                 if ( ( pActionParent->GetUniqueOrHelpId() == 0 || pActionParent->GetUniqueOrHelpId() == 1 ) )
788                                     // generate direct Button access
789                                     StatementList::pRet->GenReturn( RET_MacroRecorder, pActionParent->GetHelpId( pActionParent->GetCurItemId() ), (comm_USHORT)(M_OpenMenu) );
790                                 else
791                                     // access via Toolbox
792                                     StatementList::pRet->GenReturn( RET_MacroRecorder, pActionParent->GetUniqueOrHelpId(), (comm_USHORT)(M_OpenMenu|M_RET_NUM_CONTROL), pActionParent->GetHelpId( pActionParent->GetCurItemId() ) );
793                                 bSendData = sal_True;
794                             }
795                             break;
796 
797                     }
798   */              }
799                 break;
800 /*
801 					case M_AnimateMouse :
802 						AnimateMouse( pControl, MitteOben);
803 						break;
804 					case M_IsMax :
805 						pRet->GenReturn ( RET_Value, nUId, (comm_BOOL)!((FloatingWindow*)pControl)->IsRollUp());
806 						break;
807 					case M_Minimize :
808 						((FloatingWindow*)pControl)->RollUp();
809 						break;
810 					case M_Maximize :
811 						((FloatingWindow*)pControl)->RollDown();
812 						break;
813 					case M_Size:
814 					{
815 						if ( pControl->GetStyle() & WB_SIZEABLE )
816 						{
817 							pControl->SetSizePixel(Size(nNr1,nNr2));
818 							pControl->Resize();
819 						}
820 						else
821 							ReportError( nUId, GEN_RES_STR1( S_SIZE_NOT_CHANGEABLE, MethodString( nMethodId ) ) );
822 						break;
823 					}
824 					case M_Close:
825 						DBG_ASSERT( nUId == pControl->GetUniqueOrHelpId(), "nUID != UniqueOrHelpId");
826 						SET_WINP_CLOSING(pControl);
827 						((FloatingWindow*)pControl)->Close();
828 						break;
829 					case M_Help:		// Alles was unten weiterbehandelt werden soll
830 					case M_Move:
831 						goto MoreDialog;
832 					default:
833 						ReportError( nUId, GEN_RES_STR2c2( S_UNKNOWN_METHOD, MethodString(nMethodId), "FloatingWin" ) );
834 						break;
835 				}
836 				break;*/
837 
838 
839 
840 
841 
842 
843 
844 
845 /*
846 			case C_ModelessDlg:
847 			case C_Dlg:
848 			case C_TabDlg:
849 				MoreDialog:
850 				switch( nEventID )
851 				{
852 
853 					// (Rect GetRect)
854 
855 					case M_AnimateMouse :
856 						AnimateMouse( pControl, MitteOben);
857 						break;
858 					case M_Close:
859 						DBG_ASSERT( nUId == pControl->GetUniqueOrHelpId(), "nUID != UniqueOrHelpId");
860 						SET_WINP_CLOSING(pControl);
861 						((SystemWindow*)pControl)->Close();
862 						break;
863 					case M_Move:
864 					{
865 						pControl->SetPosPixel(Point(nNr1,nNr2));
866 						break;
867 					}
868 					default:
869 						ReportError( nUId, GEN_RES_STR2c2( S_UNKNOWN_METHOD, MethodString(nMethodId), "Dialog" ) );
870 						break;
871 				}
872 				break;*/
873 
874 
875 
876 
877 
878 
879 
880 
881 
882 
883 
884 
885 
886 /*
887 			case C_WorkWin:
888 				switch( nEventID )
889 				{
890 					case M_Close:
891 						DBG_ASSERT( nUId == pControl->GetUniqueOrHelpId(), "nUID != UniqueOrHelpId");
892 						SET_WINP_CLOSING(pControl);
893 						((WorkWindow*)pControl)->Close();
894 						break;
895 					case M_Size:
896 					case M_Move:
897 						goto FloatWin;
898 						break;
899 					case M_Help:		// Alles was unten weiterbehandelt werden soll
900 						goto MoreDialog;
901 					default:
902 						ReportError( nUId, GEN_RES_STR2c2( S_UNKNOWN_METHOD, MethodString(nMethodId), "WorkWindow" ) );
903 						break;
904 				}
905 				break;
906   */
907 
908 
909 /*			case C_TabPage:
910 				switch( nEventID )
911 				{
912 				}
913 				break;*/
914 
915 
916 
917 
918 
919 
920 
921 
922 
923 
924 
925 
926 
927 /*
928 			case C_MessBox:
929 			case C_InfoBox:
930 			case C_WarningBox:
931 			case C_ErrorBox:
932 			case C_QueryBox:
933 				{
934 					sal_Bool bDone = sal_True;
935 					MessBox* pMB = (MessBox*)pControl;
936 					switch( nEventID )
937 					{
938 						case M_GetCheckBoxText:
939 							pRet->GenReturn ( RET_Value, nUId, pMB->GetCheckBoxText() );
940 							break;
941 						case M_IsChecked :
942 							pRet->GenReturn ( RET_Value, nUId, comm_BOOL( pMB->GetCheckBoxState() == STATE_CHECK) );
943 							break;
944 						case M_GetState :
945 							pRet->GenReturn ( RET_Value, nUId, comm_ULONG( pMB->GetCheckBoxState() ));
946 							break;
947 						case M_Check :
948 							pMB->SetCheckBoxState( STATE_CHECK );
949 							break;
950 						case M_UnCheck :
951 							pMB->SetCheckBoxState( STATE_NOCHECK );
952 							break;
953 						case M_GetText :
954 							pRet->GenReturn ( RET_Value, nUId, pMB->GetMessText());
955 							break;
956 
957 						default:
958 							bDone = sal_False;
959 							break;
960 					}
961 					if ( bDone )
962 						break;	// break the case here else continue at C_ButtonDialog
963 				}
964 			case C_ButtonDialog:
965 				{
966 					ButtonDialog* pBD = (ButtonDialog*)pControl;
967 #if OSL_DEBUG_LEVEL > 1
968 					m_pDbgWin->AddText( "Working MessBox: " );
969 					if (pControl->IsVisible())
970 						m_pDbgWin->AddText("*(Visible)\n");
971 					else
972 						m_pDbgWin->AddText("*(nicht Visible)\n");
973 #endif
974 					switch( nEventID )
975 					{
976 						case M_GetText :
977 							pRet->GenReturn ( RET_Value, nUId, pControl->GetText());
978 							break;
979 						case M_Click:
980 							if ( nParams & PARAM_USHORT_1 )
981 							{
982 								if ( pBD->GetPushButton( nNr1 ) )
983 								{
984 									if ( nNr1 != BUTTONID_HELP )
985 									{
986 										SET_WINP_CLOSING(pControl);
987 									}
988 									pBD->GetPushButton( nNr1 )->Click();
989 								}
990 								else
991 									ReportError( nUId, GEN_RES_STR2( S_NO_DEFAULT_BUTTON, UniString::CreateFromInt32( nNr1 ), MethodString( nMethodId ) ) );
992 							}
993 							else
994 								ReportError( nUId, GEN_RES_STR1( S_BUTTONID_REQUIRED, MethodString( nMethodId ) ) );
995 							break;
996 						case M_GetButtonCount :
997 							pRet->GenReturn ( RET_Value, nUId, comm_ULONG(pBD->GetButtonCount()));
998 							break;
999 						case M_GetButtonId :
1000 							if ( ValueOK(nUId, MethodString( nMethodId ),nNr1,pBD->GetButtonCount()) )
1001 								pRet->GenReturn ( RET_Value, nUId, comm_ULONG(pBD->GetButtonId(nNr1-1)));
1002 							break;
1003 						default:
1004 							ReportError( nUId, GEN_RES_STR2c2( S_UNKNOWN_METHOD, MethodString(nMethodId), "MessageBox" ) );
1005 							break;
1006 					}
1007 					break;
1008 
1009 
1010                  */
1011 
1012 
1013         }
1014 
1015 
1016 		switch( nEventID )
1017 		{
1018 			case VCLEVENT_CONTROL_LOSEFOCUS:
1019                 if ( pEditModify == pWin )
1020                 {
1021 					if ( m_bRecord )
1022 					{
1023 						StatementList::pRet->GenReturn( RET_MacroRecorder, pWin->GetUniqueOrHelpId(), M_SetText, aEditModifyString );
1024 						bSendData = sal_True;
1025 					}
1026                     if ( m_bLog )
1027                     {
1028                         LogVCL( GetParentID( pWin ), pWin->GetType(), pWin->GetUniqueOrHelpId(), CUniString("Modify") );
1029                     }
1030                     pEditModify = NULL;
1031                     aEditModifyString.Erase();  //could be somewhat lengthy
1032                 }
1033 				break;
1034         }
1035 
1036         pLastWin = pWin;
1037 
1038     }  // if
1039     else if ( pEvent->ISA( VclMenuEvent ) )
1040     {
1041 //        VclMenuEvent* pMenuEvent = ( VclMenuEvent* ) pEvent;
1042     }
1043 
1044 
1045     if ( bSendData )
1046         new StatementFlow( NULL, F_EndCommandBlock );	// Kommando zum Senden erzeugen und in que eintragen
1047 
1048     return 0;
1049 }
1050 
1051 
1052 
1053 static ::osl::Mutex * getRecorderMutex()
1054 {
1055     static ::osl::Mutex * pMutex  = NULL;
1056     if(pMutex==NULL)
1057     {
1058         ::osl::MutexGuard aGuard(::osl::Mutex::getGlobalMutex());
1059         if(pMutex==NULL)
1060             pMutex = new ::osl::Mutex();
1061     }
1062     return pMutex;
1063 }
1064 
1065 
1066 void MacroRecorder::CheckDelete()
1067 {
1068 	::osl::MutexGuard aGuard( getRecorderMutex() );
1069     if ( !m_bRecord && !m_bLog )
1070     {
1071         pMacroRecorder = NULL;
1072         delete this;
1073     }
1074 }
1075 
1076 
1077 MacroRecorder* MacroRecorder::GetMacroRecorder()
1078 {
1079 	::osl::MutexGuard aGuard( getRecorderMutex() );
1080     if ( !pMacroRecorder )
1081         pMacroRecorder = new MacroRecorder;
1082 
1083     return pMacroRecorder;
1084 }
1085 
1086 sal_Bool MacroRecorder::HasMacroRecorder()
1087 {
1088 	::osl::MutexGuard aGuard( getRecorderMutex() );
1089     return pMacroRecorder != NULL;
1090 }
1091 
1092