diff options
Diffstat (limited to 'vcl/source/app/dbggui.cxx')
-rw-r--r-- | vcl/source/app/dbggui.cxx | 2028 |
1 files changed, 2028 insertions, 0 deletions
diff --git a/vcl/source/app/dbggui.cxx b/vcl/source/app/dbggui.cxx new file mode 100644 index 000000000000..b48db1d6ee97 --- /dev/null +++ b/vcl/source/app/dbggui.cxx @@ -0,0 +1,2028 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include <sal/config.h> + +#ifdef DBG_UTIL + +#include <cstdio> +#include <cstring> +#include <cmath> +#include <limits.h> + +#include "vcl/svdata.hxx" +#include "svsys.h" + +#ifdef WNT +#undef min +#endif +#include "tools/debug.hxx" +#include "vcl/svdata.hxx" +#include "vcl/svapp.hxx" +#include "vcl/event.hxx" +#include "vcl/lstbox.hxx" +#include "vcl/button.hxx" +#include "vcl/edit.hxx" +#include "vcl/fixed.hxx" +#include "vcl/group.hxx" +#include "vcl/field.hxx" +#include "vcl/msgbox.hxx" +#include "vcl/wrkwin.hxx" +#include "vcl/sound.hxx" +#include "vcl/threadex.hxx" +#include "vcl/dbggui.hxx" +#include "com/sun/star/i18n/XCharacterClassification.hpp" + +#include "vcl/unohelp.hxx" +#include "vcl/unohelp2.hxx" +#include "vos/mutex.hxx" +#include "vcl/salinst.hxx" + +#include <map> +#include <algorithm> + +using namespace ::com::sun::star; + +// ======================================================================= + +static const sal_Char* pDbgHelpText[] = +{ +"Object Test\n", +"------------------------------------------\n", +"\n", +"--- Macros ---\n", +"DBG_NAME( aName )\n", +"Defines the administration data for a class. This macro may only be used " +" in a source file with the same name.\n", +"\n", +"DBG_NAMEEX( aName )\n", +"Like DBG_NAME, only for other source files.\n", +"\n", +"DBG_CTOR( aName, fTest )\n", +"Must be used in all constructors of a class (also in the CopyCtor). " +"The first parameter must be the registered name (best would be the " +"class name) and the second parameter the test function or 0.\n", +"\n", +"DBG_DTOR( aName, fTest )\n", +"Must be used in the destructor of the class. The first parameter is " +"the registered name and the second parameter is the test function or " +"0.\n", +"\n", +"DBG_CHKTHIS( aName, fTest )\n", +"Can be used in methods of the class when constructors and the " +"desctructor of the class are equiped with the corresponding macros. " +"The first parameter is the registered name, the second parameter is " +"the test function or 0.\n", +"\n", +"DBG_CHKOBJ( pObj, aName, fTest )\n", +"Can be used on instances of a class where the constructors and the " +"destructor of the class are equiped with the corresponding macros. " +"The first parameter is the registered name, the second parameter is " +"the test function or 0.\n", +"\n", +"To make the macros work DBG_UTIL must be defined.\n", +"\n", +"--- Options ---\n", +"This\n", +"The This pointer is validated. This way all objects that are equiped " +"with it can be tested to make sure one is working with existing objects. " +"This way it's easier to find bugs in case of multiple inheritence, " +"alignment or compiler errors. Since almost all standard classes of SV " +"(String, List, Pen, Brush, Polygon, ...) are equiped with DBG_CHKTHIS() " +"a lot of errors are found, although this test will impact performance " +"accordingly.\n", +"\n", +"Function\n", +"When a function is passed with macros, it will be called.\n", +"\n", +"Exit\n", +"This- and Func-Test will also run when exiting the function.\n", +"\n", +"Report\n", +"At the end of the program the number of generated objects is produced " +"as output. Because all important SV classes have at least DBG_CTOR() / " +"DBG_DTOR() it can checked so called resource leaks (system objects which " +" are not freed) exist. These include OutputDevice, Window, VirtualDevice, " +" Printer and Menu. Note: Dtor calls of static objects are not taken into " +" account. Therefor each SV program leaves 2 strings and a bitmap behind.\n", +"\n", +"Trace\n", +"Creation, destruction and usage of objects which are equiped with " +"DBG_XTOR is logged.\n", +"\n", +"\n", +"Memory Test\n", +"------------------------------------------\n", +"\n", +"--- Macros ---\n", +"DBG_MEMTEST()\n", +"Run the specified memory tests.\n", +"\n", +"DBG_MEMTEST_PTR( p )\n", +"Runs the specified memory tests and validates the pointer that was " +"passed if the pointer test is enabled.\n", +"\n", +"--- Options ---\n", +"Initialize\n", +"Allocated memory is initialized with 0x77 and free or freed memory " +"is initialized with 0x33. This option has almost no impact on performance " +"and should thus always be enabled during development. This will also " +"make crashes more often reproducable.\n", +"\n", +"Overwrite\n", +"This test check whether writes occur before or after the blocks. Before " +"and after the block memory is initialized with 0x55. This option costs " +"performance, but should be enabled once in a while to test for common " +"memory overwrites (+-1 errors). This option should also be enabled if the " +"program crashes in a new or delete operator.\n", +"\n", +"Free\n", +"This checks whether writes occur in free memory. This option costs lots " +" of performance and should thus only be used to test memory overwrites. " +" This option should perhaps also be enabled when the program crashes " +" in the new or delete operator.\n", +"\n", +"Pointer\n", +"The pointer is tested with delete and DBG_MEMTEST_PTR() to see if it was " +"created by new or SvMemAlloc(). When this option is enabled errors such as " +"double deletes, deletes on stack objects or invalid pointers will be found. " +"This option has an impact on performance and should therefor not be enabled " +"all the time. However, testing should be done with this option enabled once " +"in a while, because the memory manager does not always crash with delete and " +"invalid pointers. This option should also be enabled if the program crashes " +"in new or delete operators.\n", +"\n", +"Report\n", +"At the end of the program a small statistic and memory that was not freed are " +"output. Note: memory that is freed by global objects is also included in " +"the leak list.\n", +"\n", +"Trace\n", +"Allocating and freeing memory is logged.\n", +"\n", +"Leak report\n", +"Produces under WNT at the end of the program a list of memory leaks with " +"stack trace. Only blocks which were created inside Application::Execute() " +"are included. When this option and Overwrite are both enabled a memory " +"overwrite results in an attempt to output the stack where the block was " +"created. The output is included in the log file after the error message.\n" +"\n", +"New/Delete\n", +"Memory tests are performed on the entire memory with every new/delet. " +"Warning: this option makes programs very slow and should only be enabled " +"to track memory overwrites. Otherwise it is sufficient to enable " +"seperate options because (if no leak is present) every detectable " +"memory overwrite during run time should be found.\n", +"\n", +"Object Test\n", +"Memory test are performed on the entire memory with every object test. " +"Warning: this option makes programs very slow and should only be enabled " +"to track memory overwrite. Otherwise it is sufficient to enable " +"seperate options because (if no leak is present) every detectable " +"memory overwrite during run time should be found.\n", +"\n", +"Windows 16-bit and debug tests\n", +"Warning: when memory test are enabled (except for Initialize) memory with " +"offset 0 is never (even not in case of >= 64KB) returned. If necessary the " +"tests can be performed with 32-bit versions of the programs. To a certain " +"extend it is sufficient to create 64KB - 64 bytes instead of 64KB because " +"it will never come to a segment overflow.\n", +"Memory and object test should only be enabled when only one SV application " +"is running at one time. Otherwise uncontrolled errors may occur. In this " +"case only the use of 32-bit programs can help." +"\n", +"\n", +"\nOther tests and macros\n", +"------------------------------------------\n", +"\n", +"Profiling\n", +"DBG_PROFSTART() / DBG_PROFSTOP() / DBG_PROFCONTINUE() / DBG_PROFPAUSE() " +"are evaluated and at the end of the program the number of run throughs " +"and the time this took (including calls to children) in milliseconds is " +"output. These macros can be used to check the same function runs over the " +"entire development period, for example the startup speed. The registered name " +"which was registered with DBG_NAME() must be passed to the macros.\n", +"\n", +"Resources\n", +"In case of resource errors an error dialog is produced before the " +"exception handler is called.\n", +"\n", +"Dialog\n", +"FixedTexts, CheckBoxes, TriStateBoxes and RadioButtons are equiped with " +"a different background color to determine the size of the controls. This " +"test also shows whether controls overlap, whether the tab order is correct " +"and whether the mnemonic characters are correctly assigned. With dialogs " +"it is indicated when no default button or no OK/CancelButton is present. " +"These tests are not 100% correct (e.g. too many warnings are given) and " +"do not form any guarantee that all problematic cases are covered. For " +"example only initial and only visible controls are tested. No errors are " +"found which will occur during the use of a dialog.\n", +"\n", +"Bold AppFont\n", +"The application font is set to bold to see if the position of texts is " +"sufficient for other systems or other system settings. With very narrow " +"fonts the dialogs are made wider because they otherwise appear too narrow.\n", +"\n", +"Trace output\n", +"DBG_TRACE() can be use to produce TRACE output. DBG_TRACEFILE() also outputs " +"the file and line number where the macro is located. DBG_TRACE1() to " +"DBG_TRACE5() can be used to produce formatted output (printf format string) " +"Trace output is enabled when the corresponding option is selected in the " +"dropdown list.\n" +"\n", +"Warnings\n", +"DBG_WARNING() can be used to output warnings. DBG_WARNINGFILE() also outputs " +"the file and the line number where the macro is located. DBG_WARNING1() to " +"DBG_WARNING5() can be used to produce formatted output (printf format string). " +"In case you want to have conditional warnings DBG_ASSERTWARNING() can be " +"used. The warning will be produced if the condition was not met. The first " +"parameter is the condition and the second parameter is the message to be " +"produced. Warnings are enabled if the corresponding option is selected in the " +"dropdown box. When none are selected the condition with DBG_ASSERTWARNING() " +"is not evaluated.\n", +"\n", +"Errors\n", +"DBG_ERROR() can be used to produce error messages. DBG_ERRORFILE() also " +"produces the file and the line number where the macro is located. " +"DBG_ERROR1() bis DBG_ERROR5() can be used to produce formatted output " +"(print format string). " +"In case you want to have conditional warnings DBG_ASSERT() can be " +"used. The warning will be produced if the condition was not met. The first " +"parameter is the condition and the second parameter is the message to be " +"produced. Warnings are enabled if the corresponding option is selected in the " +"dropdown box. When none are selected the condition with DBG_ASSERT() " +"is not evaluated.\n", +"\n", +"\n", +"Output\n", +"------------------------------------------\n", +"\n", +"Overwrite - CheckBox\n", +"With every new program start the log file is overwritten if output has been " +"generated.\n", +"\n", +"Include ObjectTest filters\n", +"Only classes which contain one of the indicated filters are evaluated with " +"the object test. Filters are seperated by ';' and are case sensitive. " +"Wildcards are not supported. If no text is indicated the filters are not " +"active.\n", +"\n", +"Exclude ObjectTest filters\n", +"Only classes which do not contain one of the indicated filters are evaluated " +"with the object test. Filters are seperated by ';' and are case sensitive. " +"Wildcards are not supported. If no text is indicated the filters are not " +"active.\n", +"\n", +"Include filters\n", +"Only those texts which include the indicated filters are output. " +"Filters are seperated by ';' and are case sensitive. " +"Wildcards are not supported. The filter is used for all output (except for " +"errors). If no text is indicated the filters are not active.\n", +"\n", +"Exclude filters\n", +"Only those texts which do not include the indicated filters are output. " +"Filters are seperated by ';' and are case sensitive. " +"Wildcards are not supported. The filter is used for all output (except for " +"errors). If no text is indicated the filters are not active.\n", +"\n", +"Furthermore you can indicate where the data will be output:\n", +"\n", +"None\n", +"Output is surpressed.\n", +"\n", +"File\n", +"Outputi n debug file. Filename can be entered in the Editfield.\n", +"\n", +"Window\n", +"Output to a small debug window. The window size is stored if the debug " +"dialog is closed with OK and if the window is visible. Each assertion text can " +"be copied to the clipboard via the context menu of the respective entry.\n", +"\n", +"Shell\n", +"Output to a debug system (Windows debug window) when available or under " +"Unix in the shell window. Otherwise the same as Window.\n", +"\n", +"MessageBox\n", +"Output to a MessageBox. In this case you can select whether the program " +"must be continued, terminated (Application::Abort) or interrupted with " +"CoreDump. Additionally on some systems you get a \"Copy\" button pressing which " +"copies the text of the MessageBox to the clipboard. Because a MessageBox allows " +"further event processing other errors caused by Paint, Activate/Deactivate, " +"GetFocus/LoseFocus can cause more errors or incorrect errors and messages. " +"Therefor the message should also be directed to a file/debugger in case of " +"problems in order to produce the (right) error messages.\n", +"\n", +"TestTool\n", +"When the TestTool runs messages will be redirected inside the TestTool.\n", +"\n", +"Debugger\n", +"Attempt to activate the debugger and produce the message there, in order to " +"always obtain the corresponding stack trace in the debugger.\n", +"\n", +"CoreDump\n", +"Causes a crash\n", +"\n", +"\n", +"Reroute osl messages - Checkbox\n", +"OSL_ASSERT and similar messages can be intercepted by the general DBG GUI\n", +"or handled system specific as per normal handling in the sal library.\n", +"default is to reroute osl assertions\n", +"\n", +"\n", +"Settings\n", +"------------------------------------------\n", +"\n", +"Where by default the INI and LOG file is read and written the following " +"can be set:\n", +"\n", +"WIN/WNT (WIN.INI, Group SV, Default: dbgsv.ini and dbgsv.log):\n", +"INI: dbgsv\n", +"LOG: dbgsvlog\n", +"\n", +"OS2 (OS2.INI, Application SV, Default: dbgsv.ini and dbgsv.log):\n", +"INI: DBGSV\n", +"LOG: DBGSVLOG\n", +"\n", +"UNIX (Environment variable, Default: .dbgsv.init and dbgsv.log):\n", +"INI: DBGSV_INIT\n", +"LOG: DBGSV_LOG\n", +"\n", +"MAC (Default: dbgsv.ini and dbgsv.log):\n", +"INI: not possible\n", +"LOG: only debug dialog settings\n", +"\n", +"The path and file name must always be specified. The name of the log " +"file that was entered in the debug dialog has always priority.\n", +"\n", +"\n", +"Example\n", +"------------------------------------------\n", +"\n", +"DBG_NAME( String );\n", +"\n", +"#ifdef DBG_UTIL\n", +"const sal_Char* DbgCheckString( const void* pString )\n", +"{\n", +" String* p = (String*)pString;\n", +"\n", +" if ( p->mpData->maStr[p->mpData->mnLen] != 0 )\n", +" return \"String damaged: aStr[nLen] != 0\";\n", +"\n", +" return NULL;\n", +"}\n", +"#endif\n", +"\n", +"String::String()\n", +"{\n", +" DBG_CTOR( String, DbgCheckString );\n", +" // ...\n", +"}\n", +"\n", +"String::~String()\n", +"{\n", +" DBG_DTOR( String, DbgCheckString );\n", +" //...\n", +"}\n", +"\n", +"char& String::operator [] ( USHORT nIndex )\n", +"{\n", +" DBG_CHKTHIS( String, DbgCheckString );\n", +" DBG_ASSERT( nIndex <= pData->nLen, \"String::[] : nIndex > Len\" );\n", +"\n", +" //...\n", +"}\n", +"\n", +"USHORT String::Search( const String& rStr, USHORT nIndex ) const\n", +"{\n", +" DBG_CHKTHIS( String, DbgCheckString );\n", +" DBG_CHKOBJ( &rStr, String, DbgCheckString );\n", +"\n", +" //...\n", +"}", +"\n", +NULL +}; + +// ======================================================================= + +namespace +{ + // ------------------------------------------------------------------- + typedef ::std::map< XubString, DbgChannelId > UserDefinedChannels; + UserDefinedChannels& ImplDbgGetUserDefinedChannels() + { + static UserDefinedChannels s_aChannels; + return s_aChannels; + } + + // ------------------------------------------------------------------- + void ImplAppendUserDefinedChannels( ListBox& rList ) + { + const UserDefinedChannels& rChannels = ImplDbgGetUserDefinedChannels(); + for ( UserDefinedChannels::const_iterator channel = rChannels.begin(); + channel != rChannels.end(); + ++channel + ) + { + USHORT nEntryPos = rList.InsertEntry( channel->first ); + rList.SetEntryData( nEntryPos, reinterpret_cast< void* >( channel->second ) ); + } + } + + // ------------------------------------------------------------------- + void ImplSelectChannel( ListBox& rList, ULONG nChannelToSelect, USHORT nPositionOffset ) + { + if ( nChannelToSelect < DBG_OUT_USER_CHANNEL_0 ) + rList.SelectEntryPos( (USHORT)( nChannelToSelect - nPositionOffset ) ); + else + { + for ( USHORT pos = 0; pos < rList.GetEntryCount(); ++pos ) + { + DbgChannelId nChannelId = static_cast< DbgChannelId >( reinterpret_cast<sal_IntPtr>(rList.GetEntryData( pos )) ); + if ( nChannelId == nChannelToSelect ) + { + rList.SelectEntryPos( pos ); + return; + } + } + } + } + // ------------------------------------------------------------------- + DbgChannelId ImplGetChannelId( const ListBox& rList, USHORT nPositionOffset ) + { + USHORT nSelectedChannelPos = rList.GetSelectEntryPos(); + DbgChannelId nSelectedChannel = static_cast< DbgChannelId >( reinterpret_cast<sal_IntPtr>(rList.GetEntryData( nSelectedChannelPos )) ); + if ( nSelectedChannel == 0) + return (DbgChannelId)( nSelectedChannelPos + nPositionOffset ); + return nSelectedChannel; + } +} + +// ======================================================================= + +// ------------- +// - DbgWindow - +// ------------- + +#define DBGWIN_MAXLINES 100 + +class DbgWindow : public WorkWindow +{ +private: + ListBox maLstBox; + +public: + DbgWindow(); + + virtual BOOL Close(); + virtual void Resize(); + virtual long PreNotify( NotifyEvent& rNEvt ); + void InsertLine( const XubString& rLine ); + void Update() { WorkWindow::Update(); maLstBox.Update(); } + +private: + void GetAssertionEntryRange( USHORT nInbetweenEntry, USHORT& nFirst, USHORT& nLast ); +}; + +// ----------------- +// - DbgInfoDialog - +// ----------------- + +class DbgInfoDialog : public ModalDialog +{ +private: + ListBox maListBox; + OKButton maOKButton; + BOOL mbHelpText; + +public: + DbgInfoDialog( Window* pParent, BOOL bHelpText = FALSE ); + + void SetInfoText( const XubString& rStr ); +}; + +// ------------- +// - DbgDialog - +// ------------- + +class DbgDialog : public ModalDialog +{ +private: + CheckBox maXtorThis; + CheckBox maXtorFunc; + CheckBox maXtorExit; + CheckBox maXtorReport; + CheckBox maXtorTrace; + GroupBox maBox1; + + CheckBox maMemInit; + CheckBox maMemOverwrite; + CheckBox maMemOverwriteFree; + CheckBox maMemPtr; + CheckBox maMemReport; + CheckBox maMemTrace; + CheckBox maMemLeakReport; + CheckBox maMemNewDel; + CheckBox maMemXtor; + GroupBox maBox2; + + CheckBox maProf; + CheckBox maRes; + CheckBox maDialog; + CheckBox maBoldAppFont; + GroupBox maBox3; + + Edit maDebugName; + CheckBox maOverwrite; + FixedText maInclClassText; + Edit maInclClassFilter; + FixedText maExclClassText; + Edit maExclClassFilter; + FixedText maInclText; + Edit maInclFilter; + FixedText maExclText; + Edit maExclFilter; + FixedText maTraceText; + ListBox maTraceBox; + FixedText maWarningText; + ListBox maWarningBox; + FixedText maErrorText; + ListBox maErrorBox; + CheckBox maHookOSLBox; + GroupBox maBox4; + + OKButton maOKButton; + CancelButton maCancelButton; + PushButton maInfoButton; + HelpButton maHelpButton; + USHORT mnErrorOff; + +public: + DbgDialog(); + + DECL_LINK( ClickHdl, Button* ); + void RequestHelp( const HelpEvent& rHEvt ); +}; + +// ======================================================================= + +static sal_Char aDbgInfoBuf[12288]; +static sal_Char aDbgOutBuf[DBG_BUF_MAXLEN]; + +// ======================================================================= + +DbgWindow::DbgWindow() : + WorkWindow( NULL, WB_STDWORK ), + maLstBox( this, WB_AUTOHSCROLL ) +{ + DbgData* pData = DbgGetData(); + + maLstBox.Show(); + maLstBox.SetPosPixel( Point( 0, 0 ) ); + + SetOutputSizePixel( Size( 600, 480 ) ); + if ( pData->aDbgWinState ) + { + ByteString aState( pData->aDbgWinState ); + SetWindowState( aState ); + } + + SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "StarView Debug Window" ) ) ); + Show(); + Update(); +} + +// ----------------------------------------------------------------------- + +BOOL DbgWindow::Close() +{ + // remember window position + ByteString aState( GetWindowState() ); + DbgData* pData = DbgGetData(); + strncpy( pData->aDbgWinState, + aState.GetBuffer(), + std::min( sizeof( pData->aDbgWinState ), + size_t(aState.Len() + 1U )) ); + pData->aDbgWinState[ sizeof( pData->aDbgWinState ) - 1 ] = 0; + // and save for next session + DbgSaveData( *pData ); + + delete this; + ImplGetSVData()->maWinData.mpDbgWin = NULL; + return TRUE; +} + +// ----------------------------------------------------------------------- + +void DbgWindow::Resize() +{ + maLstBox.SetSizePixel( GetOutputSizePixel() ); +} + +// ----------------------------------------------------------------------- + +void DbgWindow::GetAssertionEntryRange( USHORT nInbetweenEntry, USHORT& nFirst, USHORT& nLast ) +{ + nFirst = nInbetweenEntry; + while ( nFirst > 0 ) + { + if ( maLstBox.GetEntryData( nFirst ) != NULL ) + break; + --nFirst; + } + USHORT nEntryCount = maLstBox.GetEntryCount(); + nLast = nInbetweenEntry + 1; + while ( nLast < nEntryCount ) + { + if ( maLstBox.GetEntryData( nLast ) != NULL ) + break; + ++nLast; + } +} + +// ----------------------------------------------------------------------- + +long DbgWindow::PreNotify( NotifyEvent& rNEvt ) +{ + if ( rNEvt.GetType() == EVENT_COMMAND ) + { + if ( maLstBox.IsWindowOrChild( rNEvt.GetWindow() ) ) + { + const CommandEvent& rCommand = *rNEvt.GetCommandEvent(); + if ( rCommand.GetCommand() == COMMAND_CONTEXTMENU ) + { + PopupMenu aMenu; + aMenu.InsertItem( 1, String::CreateFromAscii( "copy to clipboard" ) ); + + Point aPos; + if ( rCommand.IsMouseEvent() ) + aPos = rCommand.GetMousePosPixel(); + else + { + Rectangle aEntryRect( maLstBox.GetBoundingRectangle( maLstBox.GetSelectEntryPos() ) ); + aPos = aEntryRect.Center(); + } + USHORT nSelected = aMenu.Execute( rNEvt.GetWindow(), aPos ); + if ( nSelected == 1 ) + { + // search all entries which belong to this assertion + USHORT nAssertionFirst = 0; + USHORT nAssertionLast = 0; + GetAssertionEntryRange( maLstBox.GetSelectEntryPos(), nAssertionFirst, nAssertionLast ); + + // build the string to copy to the clipboard + String sAssertion; + String sLineFeed = String::CreateFromAscii( "\n" ); + sLineFeed.ConvertLineEnd( GetSystemLineEnd() ); + while ( nAssertionFirst < nAssertionLast ) + { + sAssertion += maLstBox.GetEntry( nAssertionFirst++ ); + sAssertion += sLineFeed; + } + + ::vcl::unohelper::TextDataObject::CopyStringTo( sAssertion, GetClipboard() ); + } + } + return 1; // handled + } + } + return WorkWindow::PreNotify( rNEvt ); +} + +// ----------------------------------------------------------------------- + +void DbgWindow::InsertLine( const XubString& rLine ) +{ + XubString aStr = rLine; + aStr.ConvertLineEnd( LINEEND_LF ); + xub_StrLen nPos = aStr.Search( _LF ); + BOOL bFirstEntry = TRUE; + while ( nPos != STRING_NOTFOUND ) + { + if ( maLstBox.GetEntryCount() >= DBGWIN_MAXLINES ) + maLstBox.RemoveEntry( 0 ); + + USHORT nInsertionPos = maLstBox.InsertEntry( aStr.Copy( 0, nPos ) ); + if ( bFirstEntry ) + maLstBox.SetEntryData( nInsertionPos, reinterpret_cast< void* >( 0x00000001 ) ); + bFirstEntry = FALSE; + + aStr.Erase( 0, nPos+1 ); + nPos = aStr.Search( _LF ); + } + if ( maLstBox.GetEntryCount() >= DBGWIN_MAXLINES ) + maLstBox.RemoveEntry( 0 ); + USHORT nInsertionPos = maLstBox.InsertEntry( aStr ); + if ( bFirstEntry ) + maLstBox.SetEntryData( nInsertionPos, reinterpret_cast< void* >( 0x00000001 ) ); + maLstBox.SetTopEntry( DBGWIN_MAXLINES-1 ); + maLstBox.Update(); +} + +// ======================================================================= + +DbgDialog::DbgDialog() : + ModalDialog( NULL, WB_STDMODAL | WB_SYSTEMWINDOW ), + maXtorThis( this ), + maXtorFunc( this ), + maXtorExit( this ), + maXtorReport( this ), + maXtorTrace( this ), + maBox1( this ), + maMemInit( this ), + maMemOverwrite( this ), + maMemOverwriteFree( this ), + maMemPtr( this ), + maMemReport( this ), + maMemTrace( this ), + maMemLeakReport( this ), + maMemNewDel( this ), + maMemXtor( this ), + maBox2( this ), + maProf( this ), + maRes( this ), + maDialog( this ), + maBoldAppFont( this ), + maBox3( this ), + maDebugName( this ), + maOverwrite( this ), + maInclClassText( this ), + maInclClassFilter( this ), + maExclClassText( this ), + maExclClassFilter( this ), + maInclText( this ), + maInclFilter( this ), + maExclText( this ), + maExclFilter( this ), + maTraceText( this ), + maTraceBox( this, WB_DROPDOWN ), + maWarningText( this ), + maWarningBox( this, WB_DROPDOWN ), + maErrorText( this ), + maErrorBox( this, WB_DROPDOWN ), + maHookOSLBox( this ), + maBox4( this ), + maOKButton( this, WB_DEFBUTTON ), + maCancelButton( this ), + maInfoButton( this ), + maHelpButton( this ) +{ + DbgData* pData = DbgGetData(); + MapMode aAppMap( MAP_APPFONT ); + Size aButtonSize = LogicToPixel( Size( 60, 12 ), aAppMap ); + + { + maXtorThis.Show(); + maXtorThis.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "T~his" ) ) ); + if ( pData->nTestFlags & DBG_TEST_XTOR_THIS ) + maXtorThis.Check( TRUE ); + maXtorThis.SetPosSizePixel( LogicToPixel( Point( 10, 15 ), aAppMap ), + aButtonSize ); + } + + { + maXtorFunc.Show(); + maXtorFunc.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Function" ) ) ); + if ( pData->nTestFlags & DBG_TEST_XTOR_FUNC ) + maXtorFunc.Check( TRUE ); + maXtorFunc.SetPosSizePixel( LogicToPixel( Point( 75, 15 ), aAppMap ), + aButtonSize ); + } + + { + maXtorExit.Show(); + maXtorExit.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "E~xit" ) ) ); + if ( pData->nTestFlags & DBG_TEST_XTOR_EXIT ) + maXtorExit.Check( TRUE ); + maXtorExit.SetPosSizePixel( LogicToPixel( Point( 140, 15 ), aAppMap ), + aButtonSize ); + } + + { + maXtorReport.Show(); + maXtorReport.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Report" ) ) ); + if ( pData->nTestFlags & DBG_TEST_XTOR_REPORT ) + maXtorReport.Check( TRUE ); + maXtorReport.SetPosSizePixel( LogicToPixel( Point( 205, 15 ), aAppMap ), + aButtonSize ); + } + + { + maXtorTrace.Show(); + maXtorTrace.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Trace" ) ) ); + if ( pData->nTestFlags & DBG_TEST_XTOR_TRACE ) + maXtorTrace.Check( TRUE ); + maXtorTrace.SetPosSizePixel( LogicToPixel( Point( 270, 15 ), aAppMap ), + aButtonSize ); + } + + { + maBox1.Show(); + maBox1.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Object Tests" ) ) ); + maBox1.SetPosSizePixel( LogicToPixel( Point( 5, 5 ), aAppMap ), + LogicToPixel( Size( 330, 30 ), aAppMap ) ); + } + + { + maMemInit.Show(); + maMemInit.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Initialize" ) ) ); + if ( pData->nTestFlags & DBG_TEST_MEM_INIT ) + maMemInit.Check( TRUE ); + maMemInit.SetPosSizePixel( LogicToPixel( Point( 10, 50 ), aAppMap ), + aButtonSize ); + } + + { + maMemOverwrite.Show(); + maMemOverwrite.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Overwrite" )) ); + if ( pData->nTestFlags & DBG_TEST_MEM_OVERWRITE ) + maMemOverwrite.Check( TRUE ); + maMemOverwrite.SetPosSizePixel( LogicToPixel( Point( 75, 50 ), aAppMap ), + aButtonSize ); + } + + { + maMemOverwriteFree.Show(); + maMemOverwriteFree.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Free" ) ) ); + if ( pData->nTestFlags & DBG_TEST_MEM_OVERWRITEFREE ) + maMemOverwriteFree.Check( TRUE ); + maMemOverwriteFree.SetPosSizePixel( LogicToPixel( Point( 140, 50 ), aAppMap ), + aButtonSize ); + } + + { + maMemPtr.Show(); + maMemPtr.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Pointer" ) ) ); + if ( pData->nTestFlags & DBG_TEST_MEM_POINTER ) + maMemPtr.Check( TRUE ); + maMemPtr.SetPosSizePixel( LogicToPixel( Point( 205, 50 ), aAppMap ), + aButtonSize ); + } + + { + maMemReport.Show(); + maMemReport.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Report" ) ) ); + if ( pData->nTestFlags & DBG_TEST_MEM_REPORT ) + maMemReport.Check( TRUE ); + maMemReport.SetPosSizePixel( LogicToPixel( Point( 270, 50 ), aAppMap ), + aButtonSize ); + } + + { + maMemTrace.Show(); + maMemTrace.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Trace" ) ) ); + if ( pData->nTestFlags & DBG_TEST_MEM_TRACE ) + maMemTrace.Check( TRUE ); + maMemTrace.SetPosSizePixel( LogicToPixel( Point( 10, 65 ), aAppMap ), + aButtonSize ); + } + + { + maMemLeakReport.Show(); + maMemLeakReport.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Leak-Report" ) ) ); + if ( pData->nTestFlags & DBG_TEST_MEM_LEAKREPORT ) + maMemLeakReport.Check( TRUE ); + maMemLeakReport.SetPosSizePixel( LogicToPixel( Point( 75, 65 ), aAppMap ), + aButtonSize ); + } + + { + maMemNewDel.Show(); + maMemNewDel.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~New/Delete" ) ) ); + if ( pData->nTestFlags & DBG_TEST_MEM_NEWDEL ) + maMemNewDel.Check( TRUE ); + maMemNewDel.SetPosSizePixel( LogicToPixel( Point( 140, 65 ), aAppMap ), + aButtonSize ); + } + + { + maMemXtor.Show(); + maMemXtor.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Ob~ject Test" ) ) ); + if ( pData->nTestFlags & DBG_TEST_MEM_XTOR ) + maMemXtor.Check( TRUE ); + maMemXtor.SetPosSizePixel( LogicToPixel( Point( 205, 65 ), aAppMap ), + aButtonSize ); + } + + { + maBox2.Show(); + maBox2.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Memory Tests" ) ) ); + maBox2.SetPosSizePixel( LogicToPixel( Point( 5, 40 ), aAppMap ), + LogicToPixel( Size( 330, 40 ), aAppMap ) ); + } + + { + maProf.Show(); + maProf.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Profiling" ) ) ); + if ( pData->nTestFlags & DBG_TEST_PROFILING ) + maProf.Check( TRUE ); + maProf.SetPosSizePixel( LogicToPixel( Point( 10, 95 ), aAppMap ), + aButtonSize ); + } + + { + maRes.Show(); + maRes.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Resourcen" ) ) ); + if ( pData->nTestFlags & DBG_TEST_RESOURCE ) + maRes.Check( TRUE ); + maRes.SetPosSizePixel( LogicToPixel( Point( 75, 95 ), aAppMap ), + aButtonSize ); + } + + { + maDialog.Show(); + maDialog.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Dialog" ) ) ); + if ( pData->nTestFlags & DBG_TEST_DIALOG ) + maDialog.Check( TRUE ); + maDialog.SetPosSizePixel( LogicToPixel( Point( 140, 95 ), aAppMap ), + aButtonSize ); + } + + { + maBoldAppFont.Show(); + maBoldAppFont.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Bold AppFont" ) ) ); + if ( pData->nTestFlags & DBG_TEST_BOLDAPPFONT ) + maBoldAppFont.Check( TRUE ); + maBoldAppFont.SetPosSizePixel( LogicToPixel( Point( 205, 95 ), aAppMap ), + aButtonSize ); + maBoldAppFont.SaveValue(); + } + + { + maBox3.Show(); + maBox3.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Test Options" ) ) ); + maBox3.SetPosSizePixel( LogicToPixel( Point( 5, 85 ), aAppMap ), + LogicToPixel( Size( 330, 30 ), aAppMap ) ); + } + + { + maDebugName.Show(); + maDebugName.SetText( XubString( pData->aDebugName, RTL_TEXTENCODING_UTF8 ) ); + maDebugName.SetMaxTextLen( sizeof( pData->aDebugName ) ); + maDebugName.SetPosSizePixel( LogicToPixel( Point( 10, 130 ), aAppMap ), + LogicToPixel( Size( 185, 14 ), aAppMap ) ); + } + + { + maOverwrite.Show(); + maOverwrite.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Overwrite ~File" ) ) ); + if ( pData->bOverwrite ) + maOverwrite.Check( TRUE ); + maOverwrite.SetPosSizePixel( LogicToPixel( Point( 205, 130 ), aAppMap ), + aButtonSize ); + } + + { + maHookOSLBox.Show(); + maHookOSLBox.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Reroute osl debug ~messages" ) ) ); + if ( pData->bHookOSLAssert ) + maHookOSLBox.Check( TRUE ); + maHookOSLBox.SetPosSizePixel( LogicToPixel( Point( 10, 240 ), aAppMap ), + LogicToPixel( Size( 100, 12 ), aAppMap ) ); + } + + { + maInclClassText.Show(); + maInclClassText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Include-ObjectTest-Filter" ) ) ); + maInclClassText.SetPosSizePixel( LogicToPixel( Point( 10, 150 ), aAppMap ), + LogicToPixel( Size( 95, 9 ), aAppMap ) ); + } + + { + maInclClassFilter.Show(); + maInclClassFilter.SetText( XubString( pData->aInclClassFilter, RTL_TEXTENCODING_UTF8 ) ); + maInclClassFilter.SetMaxTextLen( sizeof( pData->aInclClassFilter ) ); + maInclClassFilter.SetPosSizePixel( LogicToPixel( Point( 10, 160 ), aAppMap ), + LogicToPixel( Size( 95, 14 ), aAppMap ) ); + } + + { + maExclClassText.Show(); + maExclClassText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Exclude-ObjectTest-Filter" ) ) ); + maExclClassText.SetPosSizePixel( LogicToPixel( Point( 115, 150 ), aAppMap ), + LogicToPixel( Size( 95, 9 ), aAppMap ) ); + } + + { + maExclClassFilter.Show(); + maExclClassFilter.SetText( XubString( pData->aExclClassFilter, RTL_TEXTENCODING_UTF8 ) ); + maExclClassFilter.SetMaxTextLen( sizeof( pData->aExclClassFilter ) ); + maExclClassFilter.SetPosSizePixel( LogicToPixel( Point( 115, 160 ), aAppMap ), + LogicToPixel( Size( 95, 14 ), aAppMap ) ); + } + + { + maInclText.Show(); + maInclText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Include-Filter" ) ) ); + maInclText.SetPosSizePixel( LogicToPixel( Point( 10, 180 ), aAppMap ), + LogicToPixel( Size( 95, 9 ), aAppMap ) ); + } + + { + maInclFilter.Show(); + maInclFilter.SetText( XubString( pData->aInclFilter, RTL_TEXTENCODING_UTF8 ) ); + maInclFilter.SetMaxTextLen( sizeof( pData->aInclFilter ) ); + maInclFilter.SetPosSizePixel( LogicToPixel( Point( 10, 190 ), aAppMap ), + LogicToPixel( Size( 95, 14 ), aAppMap ) ); + } + + { + maExclText.Show(); + maExclText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Exclude-Filter" ) ) ); + maExclText.SetPosSizePixel( LogicToPixel( Point( 115, 180 ), aAppMap ), + LogicToPixel( Size( 95, 9 ), aAppMap ) ); + } + + { + maExclFilter.Show(); + maExclFilter.SetText( XubString( pData->aExclFilter, RTL_TEXTENCODING_UTF8 ) ); + maExclFilter.SetMaxTextLen( sizeof( pData->aExclFilter ) ); + maExclFilter.SetPosSizePixel( LogicToPixel( Point( 115, 190 ), aAppMap ), + LogicToPixel( Size( 95, 14 ), aAppMap ) ); + } + + { + maTraceText.Show(); + maTraceText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Trace" ) ) ); + maTraceText.SetPosSizePixel( LogicToPixel( Point( 10, 210 ), aAppMap ), + LogicToPixel( Size( 95, 9 ), aAppMap ) ); + } + + { + maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) ); + maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) ); + maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Window" ) ) ); + maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Shell" ) ) ); + maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "MessageBox" ) ) ); + maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "TestTool" ) ) ); + maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debugger" ) ) ); + maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "CoreDump" ) ) ); + ImplAppendUserDefinedChannels( maTraceBox ); + ImplSelectChannel( maTraceBox, pData->nTraceOut, 0 ); + maTraceBox.Show(); + maTraceBox.SetPosSizePixel( LogicToPixel( Point( 10, 220 ), aAppMap ), + LogicToPixel( Size( 95, 80 ), aAppMap ) ); + } + + { + maWarningText.Show(); + maWarningText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Warning" ) ) ); + maWarningText.SetPosSizePixel( LogicToPixel( Point( 115, 210 ), aAppMap ), + LogicToPixel( Size( 95, 9 ), aAppMap ) ); + } + + { + maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) ); + maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) ); + maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Window" ) ) ); + maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Shell" ) ) ); + maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "MessageBox" ) ) ); + maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "TestTool" ) ) ); + maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debugger" ) ) ); + maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "CoreDump" ) ) ); + ImplAppendUserDefinedChannels( maWarningBox ); + ImplSelectChannel( maWarningBox, pData->nWarningOut, 0 ); + maWarningBox.Show(); + maWarningBox.SetPosSizePixel( LogicToPixel( Point( 115, 220 ), aAppMap ), + LogicToPixel( Size( 95, 80 ), aAppMap ) ); + } + + { + maErrorText.Show(); + maErrorText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Error" ) ) ); + maErrorText.SetPosSizePixel( LogicToPixel( Point( 220, 210 ), aAppMap ), + LogicToPixel( Size( 95, 9 ), aAppMap ) ); + } + + { + if ( DbgIsAllErrorOut() ) + { + maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) ); + maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) ); + maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Window" ) ) ); + maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Shell" ) ) ); + mnErrorOff = 0; + } + else + mnErrorOff = 4; + maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "MessageBox" ) ) ); + maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "TestTool" ) ) ); + maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debugger" ) ) ); + maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "CoreDump" ) ) ); + ImplAppendUserDefinedChannels( maErrorBox ); + ImplSelectChannel( maErrorBox, pData->nErrorOut, mnErrorOff ); + maErrorBox.Show(); + maErrorBox.SetPosSizePixel( LogicToPixel( Point( 220, 220 ), aAppMap ), + LogicToPixel( Size( 95, 80 ), aAppMap ) ); + } + + { + maBox4.Show(); + maBox4.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Output" ) ) ); + maBox4.SetPosSizePixel( LogicToPixel( Point( 5, 120 ), aAppMap ), + LogicToPixel( Size( 330, 135 ), aAppMap ) ); + } + + { + maOKButton.Show(); + maOKButton.SetClickHdl( LINK( this, DbgDialog, ClickHdl ) ); + maOKButton.SetPosSizePixel( LogicToPixel( Point( 10, 260 ), aAppMap ), + LogicToPixel( Size( 50, 15 ), aAppMap ) ); + } + { + maCancelButton.Show(); + maCancelButton.SetPosSizePixel( LogicToPixel( Point( 70, 260 ), aAppMap ), + LogicToPixel( Size( 50, 15 ), aAppMap ) ); + } + { + maInfoButton.Show(); + maInfoButton.SetClickHdl( LINK( this, DbgDialog, ClickHdl ) ); + maInfoButton.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Info..." ) ) ); + maInfoButton.SetPosSizePixel( LogicToPixel( Point( 130, 260 ), aAppMap ), + LogicToPixel( Size( 50, 15 ), aAppMap ) ); + } + { + maHelpButton.Show(); + maHelpButton.SetPosSizePixel( LogicToPixel( Point( 190, 260 ), aAppMap ), + LogicToPixel( Size( 50, 15 ), aAppMap ) ); + } + + { + SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "VCL Debug Options" ) ) ); + SetOutputSizePixel( LogicToPixel( Size( 340, 280 ), aAppMap ) ); + } +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( DbgDialog, ClickHdl, Button*, pButton ) +{ + if ( pButton == &maOKButton ) + { + DbgData aData; + + memcpy( &aData, DbgGetData(), sizeof( DbgData ) ); + aData.nTestFlags = 0; + + aData.nTraceOut = ImplGetChannelId( maTraceBox, 0 ); + aData.nWarningOut = ImplGetChannelId( maWarningBox, 0 ); + aData.nErrorOut = ImplGetChannelId( maErrorBox, mnErrorOff ); + + strncpy( aData.aDebugName, ByteString( maDebugName.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aDebugName ) ); + strncpy( aData.aInclClassFilter, ByteString( maInclClassFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aInclClassFilter ) ); + strncpy( aData.aExclClassFilter, ByteString( maExclClassFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aExclClassFilter ) ); + strncpy( aData.aInclFilter, ByteString( maInclFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aInclFilter ) ); + strncpy( aData.aExclFilter, ByteString( maExclFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aExclFilter ) ); + aData.aDebugName[sizeof( aData.aDebugName )-1] = '\0'; + aData.aInclClassFilter[sizeof( aData.aInclClassFilter )-1] = '\0'; + aData.aExclClassFilter[sizeof( aData.aExclClassFilter )-1] = '\0'; + aData.aInclFilter[sizeof( aData.aInclFilter )-1] = '\0'; + aData.aExclFilter[sizeof( aData.aExclFilter )-1] = '\0'; + + aData.bOverwrite = maOverwrite.IsChecked() ? TRUE : FALSE; + aData.bHookOSLAssert = maHookOSLBox.IsChecked() ? TRUE : FALSE; + + if ( maXtorThis.IsChecked() ) + aData.nTestFlags |= DBG_TEST_XTOR_THIS; + + if ( maXtorFunc.IsChecked() ) + aData.nTestFlags |= DBG_TEST_XTOR_FUNC; + + if ( maXtorExit.IsChecked() ) + aData.nTestFlags |= DBG_TEST_XTOR_EXIT; + + if ( maXtorReport.IsChecked() ) + aData.nTestFlags |= DBG_TEST_XTOR_REPORT; + + if ( maXtorTrace.IsChecked() ) + aData.nTestFlags |= DBG_TEST_XTOR_TRACE; + + if ( maMemInit.IsChecked() ) + aData.nTestFlags |= DBG_TEST_MEM_INIT; + + if ( maMemOverwrite.IsChecked() ) + aData.nTestFlags |= DBG_TEST_MEM_OVERWRITE; + + if ( maMemOverwriteFree.IsChecked() ) + aData.nTestFlags |= DBG_TEST_MEM_OVERWRITEFREE; + + if ( maMemPtr.IsChecked() ) + aData.nTestFlags |= DBG_TEST_MEM_POINTER; + + if ( maMemReport.IsChecked() ) + aData.nTestFlags |= DBG_TEST_MEM_REPORT; + + if ( maMemTrace.IsChecked() ) + aData.nTestFlags |= DBG_TEST_MEM_TRACE; + + if ( maMemLeakReport.IsChecked() ) + aData.nTestFlags |= DBG_TEST_MEM_LEAKREPORT; + + if ( maMemNewDel.IsChecked() ) + aData.nTestFlags |= DBG_TEST_MEM_NEWDEL; + + if ( maMemXtor.IsChecked() ) + aData.nTestFlags |= DBG_TEST_MEM_XTOR; + + if ( maProf.IsChecked() ) + aData.nTestFlags |= DBG_TEST_PROFILING; + + if ( maRes.IsChecked() ) + aData.nTestFlags |= DBG_TEST_RESOURCE; + + if ( maDialog.IsChecked() ) + aData.nTestFlags |= DBG_TEST_DIALOG; + + if ( maBoldAppFont.IsChecked() ) + aData.nTestFlags |= DBG_TEST_BOLDAPPFONT; + + // Daten speichern + DbgSaveData( aData ); + + // Umschalten der Laufzeitwerte + DBG_INSTOUTTRACE( aData.nTraceOut ); + DBG_INSTOUTWARNING( aData.nWarningOut ); + DBG_INSTOUTERROR( aData.nErrorOut ); + DbgUpdateOslHook( &aData ); + + DbgData* pData = DbgGetData(); + #define IMMEDIATE_FLAGS (DBG_TEST_MEM_INIT | DBG_TEST_RESOURCE | DBG_TEST_DIALOG | DBG_TEST_BOLDAPPFONT) + pData->nTestFlags &= ~IMMEDIATE_FLAGS; + pData->nTestFlags |= aData.nTestFlags & IMMEDIATE_FLAGS; + strncpy( pData->aInclClassFilter, aData.aInclClassFilter, sizeof( pData->aInclClassFilter ) ); + strncpy( pData->aExclClassFilter, aData.aExclClassFilter, sizeof( pData->aExclClassFilter ) ); + strncpy( pData->aInclFilter, aData.aInclFilter, sizeof( pData->aInclFilter ) ); + strncpy( pData->aExclFilter, aData.aExclFilter, sizeof( pData->aExclFilter ) ); + if ( maBoldAppFont.GetSavedValue() != maBoldAppFont.IsChecked() ) + { + AllSettings aSettings = Application::GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + Font aFont = aStyleSettings.GetAppFont(); + if ( maBoldAppFont.IsChecked() ) + aFont.SetWeight( WEIGHT_BOLD ); + else + aFont.SetWeight( WEIGHT_NORMAL ); + aStyleSettings.SetAppFont( aFont ); + aSettings.SetStyleSettings( aStyleSettings ); + Application::SetSettings( aSettings ); + } + if( (aData.nTestFlags & ~IMMEDIATE_FLAGS) != (pData->nTestFlags & ~IMMEDIATE_FLAGS) ) + { + InfoBox aBox( this, String( RTL_CONSTASCII_USTRINGPARAM( + "Some of the changed settings will only be active after " + "restarting the process" + ) ) ); + aBox.Execute(); + } + EndDialog( TRUE ); + } + else if ( pButton == &maInfoButton ) + { + DbgInfoDialog aInfoDialog( this ); + aDbgInfoBuf[0] = '\0'; + DbgMemInfo( aDbgInfoBuf ); + DbgXtorInfo( aDbgInfoBuf ); + XubString aInfoText( aDbgInfoBuf, RTL_TEXTENCODING_UTF8 ); + aInfoDialog.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debug InfoReport" ) ) ); + aInfoDialog.SetInfoText( aInfoText ); + aInfoDialog.Execute(); + } + + return 0; +} + +// ----------------------------------------------------------------------- + +void DbgDialog::RequestHelp( const HelpEvent& rHEvt ) +{ + if ( rHEvt.GetMode() & HELPMODE_CONTEXT ) + { + DbgInfoDialog aInfoDialog( this, TRUE ); + XubString aHelpText; + const sal_Char** pHelpStrs = pDbgHelpText; + while ( *pHelpStrs ) + { + aHelpText.AppendAscii( *pHelpStrs ); + pHelpStrs++; + } + aInfoDialog.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debug Hilfe" ) ) ); + aInfoDialog.SetInfoText( aHelpText ); + aInfoDialog.Execute(); + } +} + +// ======================================================================= + +DbgInfoDialog::DbgInfoDialog( Window* pParent, BOOL bHelpText ) : + ModalDialog( pParent, WB_STDMODAL ), + maListBox( this, WB_BORDER | WB_AUTOHSCROLL ), + maOKButton( this, WB_DEFBUTTON ) +{ + mbHelpText = bHelpText; + + if ( !bHelpText ) + { + Font aFont = GetDefaultFont( DEFAULTFONT_FIXED, LANGUAGE_ENGLISH_US, 0 ); + aFont.SetHeight( 8 ); + aFont.SetPitch( PITCH_FIXED ); + maListBox.SetControlFont( aFont ); + } + maListBox.SetPosSizePixel( Point( 5, 5 ), Size( 630, 380 ) ); + maListBox.Show(); + + maOKButton.SetPosSizePixel( Point( 290, 390 ), Size( 60, 25 ) ); + maOKButton.Show(); + + SetOutputSizePixel( Size( 640, 420 ) ); +} + +// ----------------------------------------------------------------------- + +void DbgInfoDialog::SetInfoText( const XubString& rStr ) +{ + maListBox.SetUpdateMode( FALSE ); + maListBox.Clear(); + XubString aStr = rStr; + aStr.ConvertLineEnd( LINEEND_LF ); + USHORT nStrIndex = 0; + USHORT nFoundIndex; + do + { + nFoundIndex = aStr.Search( _LF, nStrIndex ); + XubString aTextParagraph = aStr.Copy( nStrIndex, nFoundIndex-nStrIndex ); + if ( mbHelpText ) + { + long nMaxWidth = maListBox.GetOutputSizePixel().Width()-30; + USHORT nLastIndex = 0; + USHORT nIndex = aTextParagraph.Search( ' ' ); + while ( nIndex != STRING_NOTFOUND ) + { + if ( maListBox.GetTextWidth( aTextParagraph, 0, nIndex ) > nMaxWidth ) + { + if ( !nLastIndex ) + nLastIndex = nIndex+1; + XubString aTempStr = aTextParagraph.Copy( 0, nLastIndex ); + aTextParagraph.Erase( 0, nLastIndex ); + maListBox.InsertEntry( aTempStr ); + nLastIndex = 0; + } + else + nLastIndex = nIndex+1; + nIndex = aTextParagraph.Search( ' ', nLastIndex ); + } + + if ( maListBox.GetTextWidth( aTextParagraph, 0, nIndex ) > nMaxWidth ) + { + if ( !nLastIndex ) + nLastIndex = nIndex+1; + XubString aTempStr = aTextParagraph.Copy( 0, nLastIndex ); + aTextParagraph.Erase( 0, nLastIndex ); + maListBox.InsertEntry( aTempStr ); + } + } + maListBox.InsertEntry( aTextParagraph ); + nStrIndex = nFoundIndex+1; + } + while ( nFoundIndex != STRING_NOTFOUND ); + maListBox.SetUpdateMode( TRUE ); +} + +// ======================================================================= + +void DbgDialogTest( Window* pWindow ) +{ + BOOL aAccelBuf[65536]; + USHORT nChildCount = pWindow->GetChildCount(); + Window* pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD ); + Window* pChild; + Point aTabPos; + + if ( !pGetChild ) + return; + + Rectangle* pRectAry = (Rectangle*)new long[(sizeof(Rectangle)*nChildCount)/sizeof(long)]; + memset( aAccelBuf, 0, sizeof( aAccelBuf ) ); + memset( pRectAry, 0, sizeof(Rectangle)*nChildCount ); + + if ( pWindow->IsDialog() ) + { + BOOL bOKCancelButton = FALSE; + BOOL bDefPushButton = FALSE; + BOOL bButton = FALSE; + pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD ); + while ( pGetChild ) + { + pChild = pGetChild->ImplGetWindow(); + + if ( pChild->ImplIsPushButton() ) + { + bButton = TRUE; + if ( (pChild->GetType() == WINDOW_OKBUTTON) || (pChild->GetType() == WINDOW_CANCELBUTTON) ) + bOKCancelButton = TRUE; + if ( pChild->GetStyle() & WB_DEFBUTTON ) + bDefPushButton = TRUE; + } + + pGetChild = pGetChild->GetWindow( WINDOW_NEXT ); + } + + if ( bButton ) + { + if ( !bOKCancelButton ) + DbgError( "Dialogs should have a OK- or CancelButton" ); + if ( !bDefPushButton ) + DbgError( "Dialogs should have a Button with WB_DEFBUTTON" ); + } + } + + USHORT i = 0; + pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD ); + while ( pGetChild ) + { + pChild = pGetChild->ImplGetWindow(); + + if ( (pChild->GetType() != WINDOW_TABCONTROL) && + (pChild->GetType() != WINDOW_TABPAGE) && + (pChild->GetType() != WINDOW_GROUPBOX) ) + { + XubString aText = pChild->GetText(); + XubString aErrorText = aText; + USHORT nAccelPos = STRING_NOTFOUND; + xub_Unicode cAccel = 0; + if ( aErrorText.Len() > 128 ) + { + aErrorText.Erase( 128 ); + aErrorText.AppendAscii( "..." ); + } + if ( aText.Len() && (aText.Len() < 1024) ) + { + nAccelPos = aText.Search( '~' ); + if ( nAccelPos != STRING_NOTFOUND ) + { + const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLocale(); + uno::Reference < i18n::XCharacterClassification > xCharClass = vcl::unohelper::CreateCharacterClassification(); + XubString aUpperText = xCharClass->toUpper( aText, 0, aText.Len(), rLocale ); + cAccel = aUpperText.GetChar( nAccelPos+1 ); + if ( pChild->IsVisible() ) + { + if ( aAccelBuf[cAccel] ) + DbgOutTypef( DBG_OUT_ERROR, "Double mnemonic char: %c", cAccel ); + else + aAccelBuf[cAccel] = TRUE; + } + } + } + + if ( (pChild->GetType() == WINDOW_RADIOBUTTON) || + (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) || + (pChild->GetType() == WINDOW_CHECKBOX) || + (pChild->GetType() == WINDOW_TRISTATEBOX) || + (pChild->GetType() == WINDOW_PUSHBUTTON) ) + { + if ( aText.Len() && !aText.EqualsAscii( "..." ) ) + { + const char* pClass; + if ( pChild->GetType() == WINDOW_RADIOBUTTON ) + pClass = "RadioButton"; + else if ( pChild->GetType() == WINDOW_IMAGERADIOBUTTON ) + pClass = "ImageRadioButton"; + else if ( pChild->GetType() == WINDOW_CHECKBOX ) + pClass = "CheckBox"; + else if ( pChild->GetType() == WINDOW_TRISTATEBOX ) + pClass = "TriStateBox"; + else if ( pChild->GetType() == WINDOW_PUSHBUTTON ) + pClass = "PushButton"; + else + pClass = "Dontknow"; + if( !cAccel ) + DbgOutTypef( DBG_OUT_ERROR, + "%s should have a mnemonic char (~): %s", + pClass, + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + + // check text width + int aWidth=0; + switch( pChild->GetType() ) + { + case WINDOW_RADIOBUTTON: + case WINDOW_IMAGERADIOBUTTON: + aWidth = ((RadioButton*)pChild)->CalcMinimumSize(0).Width(); + break; + case WINDOW_CHECKBOX: + case WINDOW_TRISTATEBOX: + aWidth = ((CheckBox*)pChild)->CalcMinimumSize(0).Width(); + break; + case WINDOW_PUSHBUTTON: + aWidth = ((PushButton*)pChild)->CalcMinimumSize(0).Width(); + break; + default: break; + } + if( pChild->IsVisible() && pChild->GetSizePixel().Width() < aWidth ) + DbgOutTypef( DBG_OUT_ERROR, + "%s exceeds window width: %s", + pClass, + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + } + + if ( pChild->GetType() == WINDOW_FIXEDLINE ) + { + if ( pChild->GetSizePixel().Width() < pChild->GetTextWidth( aText ) ) + DbgOutTypef( DBG_OUT_ERROR, + "FixedLine exceeds window width: %s", + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + + if ( pChild->GetType() == WINDOW_FIXEDTEXT ) + { + if ( (pChild->GetSizePixel().Height() >= pChild->GetTextHeight()*2) && + !(pChild->GetStyle() & WB_WORDBREAK) ) + { + DbgOutTypef( DBG_OUT_ERROR, + "FixedText greater than one line, but WordBreak is not set: %s", + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + + if ( pChild->IsVisible() ) + { + int aWidth=0; + if( nAccelPos != STRING_NOTFOUND ) + { + aWidth = pChild->GetTextWidth( aText, 0, nAccelPos ) + + pChild->GetTextWidth( aText, nAccelPos+1, aText.Len() - nAccelPos - 1); + } + else + aWidth = pChild->GetTextWidth( aText ); + + if ( pChild->GetSizePixel().Width() < aWidth && !(pChild->GetStyle() & WB_WORDBREAK) ) + { + DbgOutTypef( DBG_OUT_ERROR, + "FixedText exceeds window width: %s", + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + } + + if ( (i+1 < nChildCount) && aText.Len() ) + { + Window* pTempChild = pGetChild->GetWindow( WINDOW_NEXT )->ImplGetWindow(); + if ( (pTempChild->GetType() == WINDOW_EDIT) || + (pTempChild->GetType() == WINDOW_MULTILINEEDIT) || + (pTempChild->GetType() == WINDOW_SPINFIELD) || + (pTempChild->GetType() == WINDOW_PATTERNFIELD) || + (pTempChild->GetType() == WINDOW_NUMERICFIELD) || + (pTempChild->GetType() == WINDOW_METRICFIELD) || + (pTempChild->GetType() == WINDOW_CURRENCYFIELD) || + (pTempChild->GetType() == WINDOW_DATEFIELD) || + (pTempChild->GetType() == WINDOW_TIMEFIELD) || + (pTempChild->GetType() == WINDOW_LISTBOX) || + (pTempChild->GetType() == WINDOW_MULTILISTBOX) || + (pTempChild->GetType() == WINDOW_COMBOBOX) || + (pTempChild->GetType() == WINDOW_PATTERNBOX) || + (pTempChild->GetType() == WINDOW_NUMERICBOX) || + (pTempChild->GetType() == WINDOW_METRICBOX) || + (pTempChild->GetType() == WINDOW_CURRENCYBOX) || + (pTempChild->GetType() == WINDOW_DATEBOX) || + (pTempChild->GetType() == WINDOW_TIMEBOX) ) + { + if ( !cAccel ) + { + DbgOutTypef( DBG_OUT_ERROR, + "Labels befor Fields (Edit,ListBox,...) should have a mnemonic char (~): %s", + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + if ( !pTempChild->IsEnabled() && pChild->IsEnabled() ) + { + DbgOutTypef( DBG_OUT_ERROR, + "Labels befor Fields (Edit,ListBox,...) should be disabled, when the field is disabled: %s", + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + } + } + } + + if ( pChild->GetType() == WINDOW_MULTILINEEDIT ) + { + if ( ( 0 == ( pChild->GetStyle() & WB_IGNORETAB ) ) + && ( 0 == ( pChild->GetStyle() & WB_READONLY ) ) + ) + { + DbgError( "editable MultiLineEdits in Dialogs should have the Style WB_IGNORETAB" ); + } + } + + if ( (pChild->GetType() == WINDOW_RADIOBUTTON) || + (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) || + (pChild->GetType() == WINDOW_CHECKBOX) || + (pChild->GetType() == WINDOW_TRISTATEBOX) || + (pChild->GetType() == WINDOW_FIXEDTEXT) ) + { + pChild->SetBackground( Wallpaper( Color( COL_LIGHTGREEN ) ) ); + } + + if ( pChild->IsVisible() ) + { + BOOL bMaxWarning = FALSE; + if ( pChild->GetType() == WINDOW_NUMERICFIELD ) + { + NumericField* pField = (NumericField*)pChild; + if ( pField->GetMax() == LONG_MAX ) + bMaxWarning = TRUE; + } + else if ( pChild->GetType() == WINDOW_METRICFIELD ) + { + MetricField* pField = (MetricField*)pChild; + if ( pField->GetMax() == LONG_MAX ) + bMaxWarning = TRUE; + } + else if ( pChild->GetType() == WINDOW_CURRENCYFIELD ) + { + CurrencyField* pField = (CurrencyField*)pChild; + if ( pField->GetMax() == LONG_MAX ) + bMaxWarning = TRUE; + } + else if ( pChild->GetType() == WINDOW_TIMEFIELD ) + { + TimeField* pField = (TimeField*)pChild; + if ( pField->GetMax() == Time( 23, 59, 59, 99 ) ) + bMaxWarning = TRUE; + } + else if ( pChild->GetType() == WINDOW_DATEFIELD ) + { + DateField* pField = (DateField*)pChild; + if ( pField->GetMax() == Date( 31, 12, 9999 ) ) + bMaxWarning = TRUE; + } + else if ( pChild->GetType() == WINDOW_NUMERICBOX ) + { + NumericBox* pBox = (NumericBox*)pChild; + if ( pBox->GetMax() == LONG_MAX ) + bMaxWarning = TRUE; + } + else if ( pChild->GetType() == WINDOW_METRICBOX ) + { + MetricBox* pBox = (MetricBox*)pChild; + if ( pBox->GetMax() == LONG_MAX ) + bMaxWarning = TRUE; + } + else if ( pChild->GetType() == WINDOW_CURRENCYBOX ) + { + CurrencyBox* pBox = (CurrencyBox*)pChild; + if ( pBox->GetMax() == LONG_MAX ) + bMaxWarning = TRUE; + } + else if ( pChild->GetType() == WINDOW_TIMEBOX ) + { + TimeBox* pBox = (TimeBox*)pChild; + if ( pBox->GetMax() == Time( 23, 59, 59, 99 ) ) + bMaxWarning = TRUE; + } + else if ( pChild->GetType() == WINDOW_DATEBOX ) + { + DateBox* pBox = (DateBox*)pChild; + if ( pBox->GetMax() == Date( 31, 12, 9999 ) ) + bMaxWarning = TRUE; + } + if ( bMaxWarning ) + { + DbgOutTypef( DBG_OUT_ERROR, + "No Max-Value is set: %s", + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + + if ( (pChild->GetType() == WINDOW_RADIOBUTTON) || + (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) || + (pChild->GetType() == WINDOW_CHECKBOX) || + (pChild->GetType() == WINDOW_TRISTATEBOX) || + (pChild->GetType() == WINDOW_PUSHBUTTON) || + (pChild->GetType() == WINDOW_OKBUTTON) || + (pChild->GetType() == WINDOW_CANCELBUTTON) || + (pChild->GetType() == WINDOW_HELPBUTTON) || + (pChild->GetType() == WINDOW_IMAGEBUTTON) || + (pChild->GetType() == WINDOW_FIXEDTEXT) || + (pChild->GetType() == WINDOW_EDIT) || + (pChild->GetType() == WINDOW_MULTILINEEDIT) || + (pChild->GetType() == WINDOW_SPINFIELD) || + (pChild->GetType() == WINDOW_PATTERNFIELD) || + (pChild->GetType() == WINDOW_NUMERICFIELD) || + (pChild->GetType() == WINDOW_METRICFIELD) || + (pChild->GetType() == WINDOW_CURRENCYFIELD) || + (pChild->GetType() == WINDOW_DATEFIELD) || + (pChild->GetType() == WINDOW_TIMEFIELD) || + (pChild->GetType() == WINDOW_LISTBOX) || + (pChild->GetType() == WINDOW_MULTILISTBOX) || + (pChild->GetType() == WINDOW_COMBOBOX) || + (pChild->GetType() == WINDOW_PATTERNBOX) || + (pChild->GetType() == WINDOW_NUMERICBOX) || + (pChild->GetType() == WINDOW_METRICBOX) || + (pChild->GetType() == WINDOW_CURRENCYBOX) || + (pChild->GetType() == WINDOW_DATEBOX) || + (pChild->GetType() == WINDOW_TIMEBOX) ) + { + Point aNewPos = pChild->GetPosPixel(); + Rectangle aChildRect( aNewPos, pChild->GetSizePixel() ); + + if ( cAccel || (pChild->GetStyle() & WB_TABSTOP) || + (pChild->GetType() == WINDOW_RADIOBUTTON) || + (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) ) + { + if ( (aNewPos.X() <= aTabPos.X()) && (aNewPos.Y() <= aTabPos.Y()) ) + { + DbgOutTypef( DBG_OUT_ERROR, + "Possible wrong childorder for dialogcontrol: %s", + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + aTabPos = aNewPos; + } + + for ( USHORT j = 0; j < i; j++ ) + { + if ( ((pRectAry[j].Right() != 0) || (pRectAry[j].Bottom() != 0)) && + aChildRect.IsOver( pRectAry[j] ) ) + { + DbgOutTypef( DBG_OUT_ERROR, + "Window overlaps with sibling window: %s", + ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() ); + } + } + pRectAry[i] = aChildRect; + } + } + } + + pGetChild = pGetChild->GetWindow( WINDOW_NEXT ); + i++; + } + + delete [] pRectAry; +} + +// ======================================================================= +#ifndef WNT +#define USE_VCL_MSGBOX +#define COPY_BUTTON_ID 25 + +class DbgMessageBox : public ErrorBox +{ + String m_aMessage; + public: + DbgMessageBox( const String& rMessage ) : + ErrorBox( NULL, WB_YES_NO_CANCEL | WB_DEF_NO, rMessage ), + m_aMessage( rMessage ) + { + SetText( String( RTL_CONSTASCII_USTRINGPARAM("Debug Output") ) ); + AddButton( String( RTL_CONSTASCII_USTRINGPARAM( "Copy" ) ), COPY_BUTTON_ID, 0 ); + } + + virtual void Click() + { + if( GetCurButtonId() == COPY_BUTTON_ID ) + vcl::unohelper::TextDataObject::CopyStringTo( m_aMessage, GetClipboard() ); + else + ErrorBox::Click(); + } +}; + +#endif + +class SolarMessageBoxExecutor : public ::vcl::SolarThreadExecutor +{ +private: + String m_sDebugMessage; + +public: + SolarMessageBoxExecutor( const String& _rDebugMessage ) + :m_sDebugMessage( _rDebugMessage ) + { + } + +protected: + virtual long doIt(); +}; + +long SolarMessageBoxExecutor::doIt() +{ + long nResult = RET_NO; + + // Tracking beenden und Mouse freigeben, damit die Boxen nicht haengen + ImplSVData* pSVData = ImplGetSVData(); + if ( pSVData->maWinData.mpTrackWin ) + pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL ); + if ( pSVData->maWinData.mpCaptureWin ) + pSVData->maWinData.mpCaptureWin->ReleaseMouse(); + +#if ! defined USE_VCL_MSGBOX +#ifdef WNT + BOOL bOldCallTimer = pSVData->mbNoCallTimer; + pSVData->mbNoCallTimer = TRUE; + MessageBeep( MB_ICONHAND ); + nResult = MessageBoxW( 0, (LPWSTR)m_sDebugMessage.GetBuffer(), L"Debug Output", + MB_TASKMODAL | MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_ICONSTOP ); + pSVData->mbNoCallTimer = bOldCallTimer; + switch ( nResult ) + { + case IDYES: + nResult = RET_YES; + break; + case IDNO: + nResult = RET_NO; + break; + case IDCANCEL: + nResult = RET_CANCEL; + break; + } +#endif // WNT +#else + USHORT nOldMode = Application::GetSystemWindowMode(); + Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE ); + DbgMessageBox aBox( m_sDebugMessage ); + Application::SetSystemWindowMode( nOldMode ); + nResult = aBox.Execute(); +#endif + + return nResult; +} + +void DbgPrintMsgBox( const char* pLine ) +{ + // are modal message boxes prohibited at the moment? + if ( Application::IsDialogCancelEnabled() ) + { +#if defined( WNT ) + // TODO: Shouldn't this be a IsDebuggerPresent()? + if ( GetSystemMetrics( SM_DEBUG ) ) + { + MessageBeep( MB_ICONHAND ); + strcpy( aDbgOutBuf, pLine ); + strcat( aDbgOutBuf, "\r\n" ); + OutputDebugString( aDbgOutBuf ); + return; + } +#endif + + Sound::Beep( SOUND_ERROR ); +#ifdef UNX + fprintf( stderr, "%s\n", pLine ); + return; +#else + DbgPrintFile( pLine ); + return; +#endif + } + + strcpy( aDbgOutBuf, pLine ); + strcat( aDbgOutBuf, "\nAbort ? (Yes=abort / No=ignore / Cancel=core dump)" ); + + SolarMessageBoxExecutor aMessageBox( String( aDbgOutBuf, RTL_TEXTENCODING_UTF8 ) ); + TimeValue aTimeout; aTimeout.Seconds = 2; aTimeout.Nanosec = 0; + long nResult = aMessageBox.execute( aTimeout ); + + if ( aMessageBox.didTimeout() ) + DbgPrintShell( pLine ); + else if ( nResult == RET_YES ) + GetpApp()->Abort( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debug-Utilities-Error" ) ) ); + else if ( nResult == RET_CANCEL ) + DbgCoreDump(); +} + +// ----------------------------------------------------------------------- + +class SolarWindowPrinter : public ::vcl::SolarThreadExecutor +{ +private: + String m_sDebugMessage; + +public: + SolarWindowPrinter( const String& _rDebugMessage ) + :m_sDebugMessage( _rDebugMessage ) + { + } + +protected: + virtual long doIt(); +}; + +long SolarWindowPrinter::doIt() +{ + DbgWindow* pDbgWindow = ImplGetSVData()->maWinData.mpDbgWin; + if ( !pDbgWindow ) + { + pDbgWindow = new DbgWindow; + ImplGetSVData()->maWinData.mpDbgWin = pDbgWindow; + } + pDbgWindow->InsertLine( m_sDebugMessage ); + + return 0L; +} + +// ----------------------------------------------------------------------- + +void DbgPrintWindow( const char* pLine ) +{ + static BOOL bIn = FALSE; + + // keine rekursiven Traces + if ( bIn ) + return; + bIn = TRUE; + + SolarWindowPrinter aPrinter( String( pLine, RTL_TEXTENCODING_UTF8 ) ); + TimeValue aTimeout; aTimeout.Seconds = 2; aTimeout.Nanosec = 0; + aPrinter.execute( aTimeout ); + + if ( aPrinter.didTimeout() ) + DbgPrintShell( pLine ); + + bIn = FALSE; +} + +// ======================================================================= + +void ImplDbgTestSolarMutex() +{ + bool bCheck = ImplGetSVData()->mpDefInst->CheckYieldMutex(); + OSL_ENSURE( bCheck, "SolarMutex not locked" ); +} + +// ======================================================================= + +void DbgGUIInit() +{ + DbgSetPrintMsgBox( DbgPrintMsgBox ); + DbgSetPrintWindow( DbgPrintWindow ); + DbgSetTestSolarMutex( ImplDbgTestSolarMutex ); +} + +// ----------------------------------------------------------------------- + +void DbgGUIDeInit() +{ + DbgSetPrintMsgBox( NULL ); + DbgSetPrintWindow( NULL ); + DbgSetTestSolarMutex( NULL ); + + DbgWindow* pDbgWindow = ImplGetSVData()->maWinData.mpDbgWin; + if ( pDbgWindow ) + delete pDbgWindow; +} + +// ----------------------------------------------------------------------- + +void DbgGUIStart() +{ + DbgData* pData = DbgGetData(); + + if ( pData ) + { + DbgDialog* pDialog = new DbgDialog; + // Fuer den Debug-Dialog schalten wir Dialogtests aus + ULONG nOldFlags = pData->nTestFlags; + pData->nTestFlags &= ~DBG_TEST_DIALOG; + if ( !pDialog->Execute() ) + pData->nTestFlags |= (nOldFlags & DBG_TEST_DIALOG); + delete pDialog; + } + else + { + ErrorBox( 0, WB_OK, + XubString( RTL_CONSTASCII_USTRINGPARAM( "TOOLS Library has no Debug-Routines" ) ) ).Execute(); + } +} + +// ----------------------------------------------------------------------- + +USHORT DbgRegisterNamedUserChannel( const XubString& _rChannelUIName, DbgPrintLine pProc ) +{ + DbgChannelId nChannelId = DbgRegisterUserChannel( pProc ); + UserDefinedChannels& rChannels = ImplDbgGetUserDefinedChannels(); + rChannels[ _rChannelUIName ] = nChannelId; + return nChannelId; +} + +#endif // DBG_UTIL |