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