Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / vcl / source / app / dbggui.cxx
blob69ee0c7ff1eda111d96830ee0306543f8b165662
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <sal/config.h>
24 #ifdef DBG_UTIL
26 #include <cstdio>
27 #include <cstring>
28 #include <cmath>
29 #include <limits.h>
31 #include <tools/debug.hxx>
32 #include <tools/lineend.hxx>
33 #include "sal/log.hxx"
35 #include "vcl/svapp.hxx"
36 #include "vcl/event.hxx"
37 #include "vcl/lstbox.hxx"
38 #include "vcl/button.hxx"
39 #include "vcl/edit.hxx"
40 #include "vcl/fixed.hxx"
41 #include "vcl/group.hxx"
42 #include "vcl/field.hxx"
43 #include "vcl/msgbox.hxx"
44 #include "vcl/wrkwin.hxx"
45 #include "vcl/threadex.hxx"
47 #include "svdata.hxx"
48 #include "dbggui.hxx"
50 #include "vcl/unohelp.hxx"
51 #include "vcl/unohelp2.hxx"
53 #include "salinst.hxx"
54 #include "svsys.h"
56 #include "com/sun/star/i18n/XCharacterClassification.hpp"
58 #include <map>
59 #include <algorithm>
61 using namespace ::com::sun::star;
63 // =======================================================================
65 static const sal_Char* pDbgHelpText[] =
67 "Object Test\n",
68 "------------------------------------------\n",
69 "\n",
70 "--- Macros ---\n",
71 "DBG_NAME( aName )\n",
72 "Defines the administration data for a class. This macro may only be used "
73 " in a source file with the same name.\n",
74 "\n",
75 "DBG_NAMEEX( aName )\n",
76 "Like DBG_NAME, only for other source files.\n",
77 "\n",
78 "DBG_CTOR( aName, fTest )\n",
79 "Must be used in all constructors of a class (also in the CopyCtor). "
80 "The first parameter must be the registered name (best would be the "
81 "class name) and the second parameter the test function or 0.\n",
82 "\n",
83 "DBG_DTOR( aName, fTest )\n",
84 "Must be used in the destructor of the class. The first parameter is "
85 "the registered name and the second parameter is the test function or "
86 "0.\n",
87 "\n",
88 "DBG_CHKTHIS( aName, fTest )\n",
89 "Can be used in methods of the class when constructors and the "
90 "desctructor of the class are equiped with the corresponding macros. "
91 "The first parameter is the registered name, the second parameter is "
92 "the test function or 0.\n",
93 "\n",
94 "DBG_CHKOBJ( pObj, aName, fTest )\n",
95 "Can be used on instances of a class where the constructors and the "
96 "destructor of the class are equiped with the corresponding macros. "
97 "The first parameter is the registered name, the second parameter is "
98 "the test function or 0.\n",
99 "\n",
100 "To make the macros work DBG_UTIL must be defined.\n",
101 "\n",
102 "--- Options ---\n",
103 "This\n",
104 "The This pointer is validated. This way all objects that are equiped "
105 "with it can be tested to make sure one is working with existing objects. "
106 "This way it's easier to find bugs in case of multiple inheritence, "
107 "alignment or compiler errors. Since almost all standard classes of SV "
108 "(String, List, Pen, Brush, Polygon, ...) are equiped with DBG_CHKTHIS() "
109 "a lot of errors are found, although this test will impact performance "
110 "accordingly.\n",
111 "\n",
112 "Function\n",
113 "When a function is passed with macros, it will be called.\n",
114 "\n",
115 "Exit\n",
116 "This- and Func-Test will also run when exiting the function.\n",
117 "\n",
118 "Report\n",
119 "At the end of the program the number of generated objects is produced "
120 "as output. Because all important SV classes have at least DBG_CTOR() / "
121 "DBG_DTOR() it can checked so called resource leaks (system objects which "
122 " are not freed) exist. These include OutputDevice, Window, VirtualDevice, "
123 " Printer and Menu. Note: Dtor calls of static objects are not taken into "
124 " account. Therefor each SV program leaves 2 strings and a bitmap behind.\n",
125 "\n",
126 "Trace\n",
127 "Creation, destruction and usage of objects which are equiped with "
128 "DBG_XTOR is logged.\n",
129 "\n",
130 "\n",
131 "\nOther tests and macros\n",
132 "------------------------------------------\n",
133 "\n",
134 "Profiling\n",
135 "DBG_PROFSTART() / DBG_PROFSTOP() / DBG_PROFCONTINUE() / DBG_PROFPAUSE() "
136 "are evaluated and at the end of the program the number of run throughs "
137 "and the time this took (including calls to children) in milliseconds is "
138 "output. These macros can be used to check the same function runs over the "
139 "entire development period, for example the startup speed. The registered name "
140 "which was registered with DBG_NAME() must be passed to the macros.\n",
141 "\n",
142 "Resources\n",
143 "In case of resource errors an error dialog is produced before the "
144 "exception handler is called.\n",
145 "\n",
146 "Dialog\n",
147 "FixedTexts, CheckBoxes, TriStateBoxes and RadioButtons are equiped with "
148 "a different background color to determine the size of the controls. This "
149 "test also shows whether controls overlap, whether the tab order is correct "
150 "and whether the mnemonic characters are correctly assigned. With dialogs "
151 "it is indicated when no default button or no OK/CancelButton is present. "
152 "These tests are not 100% correct (e.g. too many warnings are given) and "
153 "do not form any guarantee that all problematic cases are covered. For "
154 "example only initial and only visible controls are tested. No errors are "
155 "found which will occur during the use of a dialog.\n",
156 "\n",
157 "Bold AppFont\n",
158 "The application font is set to bold to see if the position of texts is "
159 "sufficient for other systems or other system settings. With very narrow "
160 "fonts the dialogs are made wider because they otherwise appear too narrow.\n",
161 "\n",
162 "Trace output\n",
163 "DBG_TRACE() can be use to produce TRACE output. DBG_TRACEFILE() also outputs "
164 "the file and line number where the macro is located. DBG_TRACE1() to "
165 "DBG_TRACE5() can be used to produce formatted output (printf format string) "
166 "Trace output is enabled when the corresponding option is selected in the "
167 "dropdown list.\n"
168 "\n",
169 "Warnings\n",
170 "DBG_WARNING() can be used to output warnings. DBG_WARNING1() to "
171 "DBG_WARNING3() can be used to produce formatted output (printf format string). "
172 "In case you want to have conditional warnings DBG_ASSERTWARNING() can be "
173 "used. The warning will be produced if the condition was not met. The first "
174 "parameter is the condition and the second parameter is the message to be "
175 "produced. Warnings are enabled if the corresponding option is selected in the "
176 "dropdown box. When none are selected the condition with DBG_ASSERTWARNING() "
177 "is not evaluated.\n",
178 "\n",
179 "Errors\n",
180 "DBG_ERROR() can be used to produce error messages. DBG_ERRORFILE() also "
181 "produces the file and the line number where the macro is located. "
182 "DBG_ERROR1() bis DBG_ERROR5() can be used to produce formatted output "
183 "(print format string). "
184 "In case you want to have conditional warnings DBG_ASSERT() can be "
185 "used. The warning will be produced if the condition was not met. The first "
186 "parameter is the condition and the second parameter is the message to be "
187 "produced. Warnings are enabled if the corresponding option is selected in the "
188 "dropdown box. When none are selected the condition with DBG_ASSERT() "
189 "is not evaluated.\n",
190 "\n",
191 "\n",
192 "Output\n",
193 "------------------------------------------\n",
194 "\n",
195 "Overwrite - CheckBox\n",
196 "With every new program start the log file is overwritten if output has been "
197 "generated.\n",
198 "\n",
199 "Include ObjectTest filters\n",
200 "Only classes which contain one of the indicated filters are evaluated with "
201 "the object test. Filters are separated by ';' and are case sensitive. "
202 "Wildcards are not supported. If no text is indicated the filters are not "
203 "active.\n",
204 "\n",
205 "Exclude ObjectTest filters\n",
206 "Only classes which do not contain one of the indicated filters are evaluated "
207 "with the object test. Filters are separated by ';' and are case sensitive. "
208 "Wildcards are not supported. If no text is indicated the filters are not "
209 "active.\n",
210 "\n",
211 "Include filters\n",
212 "Only those texts which include the indicated filters are output. "
213 "Filters are separated by ';' and are case sensitive. "
214 "Wildcards are not supported. The filter is used for all output (except for "
215 "errors). If no text is indicated the filters are not active.\n",
216 "\n",
217 "Exclude filters\n",
218 "Only those texts which do not include the indicated filters are output. "
219 "Filters are separated by ';' and are case sensitive. "
220 "Wildcards are not supported. The filter is used for all output (except for "
221 "errors). If no text is indicated the filters are not active.\n",
222 "\n",
223 "Furthermore you can indicate where the data will be output:\n",
224 "\n",
225 "None\n",
226 "Output is surpressed.\n",
227 "\n",
228 "File\n",
229 "Outputi n debug file. Filename can be entered in the Editfield.\n",
230 "\n",
231 "Window\n",
232 "Output to a small debug window. The window size is stored if the debug "
233 "dialog is closed with OK and if the window is visible. Each assertion text can "
234 "be copied to the clipboard via the context menu of the respective entry.\n",
235 "\n",
236 "Shell\n",
237 "Output to a debug system (Windows debug window) when available or under "
238 "Unix in the shell window. Otherwise the same as Window.\n",
239 "\n",
240 "MessageBox\n",
241 "Output to a MessageBox. In this case you can select whether the program "
242 "must be continued, terminated (Application::Abort) or interrupted with "
243 "CoreDump. Additionally on some systems you get a \"Copy\" button pressing which "
244 "copies the text of the MessageBox to the clipboard. Because a MessageBox allows "
245 "further event processing other errors caused by Paint, Activate/Deactivate, "
246 "GetFocus/LoseFocus can cause more errors or incorrect errors and messages. "
247 "Therefor the message should also be directed to a file/debugger in case of "
248 "problems in order to produce the (right) error messages.\n",
249 "\n",
250 "TestTool\n",
251 "When the TestTool runs messages will be redirected inside the TestTool.\n",
252 "\n",
253 "Debugger\n",
254 "Attempt to activate the debugger and produce the message there, in order to "
255 "always obtain the corresponding stack trace in the debugger.\n",
256 "\n",
257 "Abort\n",
258 "Aborts the application\n",
259 "\n",
260 "\n",
261 "Reroute osl messages - Checkbox\n",
262 "OSL_ASSERT and similar messages can be intercepted by the general DBG GUI\n",
263 "or handled system specific as per normal handling in the sal library.\n",
264 "default is to reroute osl assertions\n",
265 "\n",
266 "\n",
267 "Settings\n",
268 "------------------------------------------\n",
269 "\n",
270 "Where by default the INI and LOG file is read and written the following "
271 "can be set:\n",
272 "\n",
273 "WIN/WNT (WIN.INI, Group SV, Default: dbgsv.ini and dbgsv.log):\n",
274 "INI: dbgsv\n",
275 "LOG: dbgsvlog\n",
276 "\n",
277 "OS2 (OS2.INI, Application SV, Default: dbgsv.ini and dbgsv.log):\n",
278 "INI: DBGSV\n",
279 "LOG: DBGSVLOG\n",
280 "\n",
281 "UNIX (Environment variable, Default: .dbgsv.init and dbgsv.log):\n",
282 "INI: DBGSV_INIT\n",
283 "LOG: DBGSV_LOG\n",
284 "\n",
285 "MAC (Default: dbgsv.ini and dbgsv.log):\n",
286 "INI: not possible\n",
287 "LOG: only debug dialog settings\n",
288 "\n",
289 "The path and file name must always be specified. The name of the log "
290 "file that was entered in the debug dialog has always priority.\n",
291 "\n",
292 "\n",
293 "Example\n",
294 "------------------------------------------\n",
295 "\n",
296 "DBG_NAME( String );\n",
297 "\n",
298 "#ifdef DBG_UTIL\n",
299 "const sal_Char* DbgCheckString( const void* pString )\n",
300 "{\n",
301 " String* p = (String*)pString;\n",
302 "\n",
303 " if ( p->mpData->maStr[p->mpData->mnLen] != 0 )\n",
304 " return \"String damaged: aStr[nLen] != 0\";\n",
305 "\n",
306 " return NULL;\n",
307 "}\n",
308 "#endif\n",
309 "\n",
310 "String::String()\n",
311 "{\n",
312 " DBG_CTOR( String, DbgCheckString );\n",
313 " // ...\n",
314 "}\n",
315 "\n",
316 "String::~String()\n",
317 "{\n",
318 " DBG_DTOR( String, DbgCheckString );\n",
319 " //...\n",
320 "}\n",
321 "\n",
322 "char& String::operator [] ( sal_uInt16 nIndex )\n",
323 "{\n",
324 " DBG_CHKTHIS( String, DbgCheckString );\n",
325 " DBG_ASSERT( nIndex <= pData->nLen, \"String::[] : nIndex > Len\" );\n",
326 "\n",
327 " //...\n",
328 "}\n",
329 "\n",
330 "sal_uInt16 String::Search( const String& rStr, sal_uInt16 nIndex ) const\n",
331 "{\n",
332 " DBG_CHKTHIS( String, DbgCheckString );\n",
333 " DBG_CHKOBJ( &rStr, String, DbgCheckString );\n",
334 "\n",
335 " //...\n",
336 "}",
337 "\n",
338 NULL
341 // =======================================================================
343 namespace
345 // -------------------------------------------------------------------
346 typedef ::std::map< OUString, DbgChannelId > UserDefinedChannels;
347 UserDefinedChannels& ImplDbgGetUserDefinedChannels()
349 static UserDefinedChannels s_aChannels;
350 return s_aChannels;
353 // -------------------------------------------------------------------
354 void ImplAppendUserDefinedChannels( ListBox& rList )
356 const UserDefinedChannels& rChannels = ImplDbgGetUserDefinedChannels();
357 for ( UserDefinedChannels::const_iterator channel = rChannels.begin();
358 channel != rChannels.end();
359 ++channel
362 sal_uInt16 nEntryPos = rList.InsertEntry( channel->first );
363 rList.SetEntryData( nEntryPos, reinterpret_cast< void* >( channel->second ) );
367 // -------------------------------------------------------------------
368 void ImplSelectChannel( ListBox& rList, sal_uLong nChannelToSelect, sal_uInt16 nPositionOffset )
370 if ( nChannelToSelect < DBG_OUT_USER_CHANNEL_0 )
371 rList.SelectEntryPos( (sal_uInt16)( nChannelToSelect - nPositionOffset ) );
372 else
374 for ( sal_uInt16 pos = 0; pos < rList.GetEntryCount(); ++pos )
376 DbgChannelId nChannelId = static_cast< DbgChannelId >( reinterpret_cast<sal_IntPtr>(rList.GetEntryData( pos )) );
377 if ( nChannelId == nChannelToSelect )
379 rList.SelectEntryPos( pos );
380 return;
385 // -------------------------------------------------------------------
386 DbgChannelId ImplGetChannelId( const ListBox& rList, sal_uInt16 nPositionOffset )
388 sal_uInt16 nSelectedChannelPos = rList.GetSelectEntryPos();
389 DbgChannelId nSelectedChannel = static_cast< DbgChannelId >( reinterpret_cast<sal_IntPtr>(rList.GetEntryData( nSelectedChannelPos )) );
390 if ( nSelectedChannel == 0)
391 return (DbgChannelId)( nSelectedChannelPos + nPositionOffset );
392 return nSelectedChannel;
396 // =======================================================================
398 // -------------
399 // - DbgWindow -
400 // -------------
402 #define DBGWIN_MAXLINES 100
404 class DbgWindow : public WorkWindow
406 private:
407 ListBox maLstBox;
409 public:
410 DbgWindow();
412 virtual sal_Bool Close();
413 virtual void Resize();
414 virtual long PreNotify( NotifyEvent& rNEvt );
415 void InsertLine( const OUString& rLine );
416 void Update() { WorkWindow::Update(); maLstBox.Update(); }
418 private:
419 void GetAssertionEntryRange( sal_uInt16 nInbetweenEntry, sal_uInt16& nFirst, sal_uInt16& nLast );
422 // -----------------
423 // - DbgInfoDialog -
424 // -----------------
426 class DbgInfoDialog : public ModalDialog
428 private:
429 ListBox maListBox;
430 OKButton maOKButton;
431 bool mbHelpText;
433 public:
434 DbgInfoDialog( Window* pParent, bool bHelpText = false );
436 void SetInfoText( const OUString& rStr );
439 // -------------
440 // - DbgDialog -
441 // -------------
443 class DbgDialog : public ModalDialog
445 private:
446 CheckBox maXtorThis;
447 CheckBox maXtorFunc;
448 CheckBox maXtorExit;
449 CheckBox maXtorReport;
450 CheckBox maXtorTrace;
451 GroupBox maBox1;
453 CheckBox maProf;
454 CheckBox maRes;
455 CheckBox maDialog;
456 CheckBox maBoldAppFont;
457 GroupBox maBox3;
459 Edit maDebugName;
460 CheckBox maOverwrite;
461 FixedText maInclClassText;
462 Edit maInclClassFilter;
463 FixedText maExclClassText;
464 Edit maExclClassFilter;
465 FixedText maInclText;
466 Edit maInclFilter;
467 FixedText maExclText;
468 Edit maExclFilter;
469 FixedText maTraceText;
470 ListBox maTraceBox;
471 FixedText maWarningText;
472 ListBox maWarningBox;
473 FixedText maErrorText;
474 ListBox maErrorBox;
475 CheckBox maHookOSLBox;
476 GroupBox maBox4;
478 OKButton maOKButton;
479 CancelButton maCancelButton;
480 PushButton maInfoButton;
481 HelpButton maHelpButton;
482 sal_uInt16 mnErrorOff;
484 public:
485 DbgDialog();
487 DECL_LINK( ClickHdl, Button* );
488 void RequestHelp( const HelpEvent& rHEvt );
491 // =======================================================================
493 static sal_Char aDbgInfoBuf[12288];
494 static sal_Char aDbgOutBuf[DBG_BUF_MAXLEN];
496 // =======================================================================
498 DbgWindow::DbgWindow() :
499 WorkWindow( NULL, WB_STDWORK ),
500 maLstBox( this, WB_AUTOHSCROLL )
502 DbgData* pData = DbgGetData();
504 maLstBox.Show();
505 maLstBox.SetPosPixel( Point( 0, 0 ) );
507 SetOutputSizePixel( Size( 600, 480 ) );
508 if ( pData->aDbgWinState )
510 OString aState( pData->aDbgWinState );
511 SetWindowState( aState );
514 SetText("StarView Debug Window");
515 Show();
516 Update();
519 // -----------------------------------------------------------------------
521 sal_Bool DbgWindow::Close()
523 // remember window position
524 OString aState( GetWindowState() );
525 DbgData* pData = DbgGetData();
526 size_t nCopy = (sizeof( pData->aDbgWinState ) < size_t(aState.getLength() + 1U ))
527 ? sizeof( pData->aDbgWinState ) : size_t(aState.getLength() + 1U );
528 strncpy( pData->aDbgWinState, aState.getStr(), nCopy );
529 pData->aDbgWinState[ sizeof( pData->aDbgWinState ) - 1 ] = 0;
530 // and save for next session
531 DbgSaveData( *pData );
533 delete this;
534 ImplGetSVData()->maWinData.mpDbgWin = NULL;
535 return sal_True;
538 // -----------------------------------------------------------------------
540 void DbgWindow::Resize()
542 maLstBox.SetSizePixel( GetOutputSizePixel() );
545 // -----------------------------------------------------------------------
547 void DbgWindow::GetAssertionEntryRange( sal_uInt16 nInbetweenEntry, sal_uInt16& nFirst, sal_uInt16& nLast )
549 nFirst = nInbetweenEntry;
550 while ( nFirst > 0 )
552 if ( maLstBox.GetEntryData( nFirst ) != NULL )
553 break;
554 --nFirst;
556 sal_uInt16 nEntryCount = maLstBox.GetEntryCount();
557 nLast = nInbetweenEntry + 1;
558 while ( nLast < nEntryCount )
560 if ( maLstBox.GetEntryData( nLast ) != NULL )
561 break;
562 ++nLast;
566 // -----------------------------------------------------------------------
568 long DbgWindow::PreNotify( NotifyEvent& rNEvt )
570 if ( rNEvt.GetType() == EVENT_COMMAND )
572 if ( maLstBox.IsWindowOrChild( rNEvt.GetWindow() ) )
574 const CommandEvent& rCommand = *rNEvt.GetCommandEvent();
575 if ( rCommand.GetCommand() == COMMAND_CONTEXTMENU )
577 PopupMenu aMenu;
578 aMenu.InsertItem( 1, OUString("copy to clipboard") );
580 Point aPos;
581 if ( rCommand.IsMouseEvent() )
582 aPos = rCommand.GetMousePosPixel();
583 else
585 Rectangle aEntryRect( maLstBox.GetBoundingRectangle( maLstBox.GetSelectEntryPos() ) );
586 aPos = aEntryRect.Center();
588 sal_uInt16 nSelected = aMenu.Execute( rNEvt.GetWindow(), aPos );
589 if ( nSelected == 1 )
591 // search all entries which belong to this assertion
592 sal_uInt16 nAssertionFirst = 0;
593 sal_uInt16 nAssertionLast = 0;
594 GetAssertionEntryRange( maLstBox.GetSelectEntryPos(), nAssertionFirst, nAssertionLast );
596 // build the string to copy to the clipboard
597 OUStringBuffer sAssertion;
598 OUString sLineFeed = convertLineEnd(
599 OUString("\n"),
600 GetSystemLineEnd());
601 while ( nAssertionFirst < nAssertionLast )
603 sAssertion.append(maLstBox.GetEntry( nAssertionFirst++ ));
604 sAssertion.append(sLineFeed);
607 ::vcl::unohelper::TextDataObject::CopyStringTo(
608 sAssertion.makeStringAndClear(), GetClipboard());
611 return 1; // handled
614 return WorkWindow::PreNotify( rNEvt );
617 // -----------------------------------------------------------------------
619 void DbgWindow::InsertLine( const OUString& rLine )
621 OUString aStr = convertLineEnd(rLine, LINEEND_LF);
622 sal_Int32 nPos = aStr.indexOf( '\n' );
623 bool bFirstEntry = true;
624 while ( nPos != -1 )
626 if ( maLstBox.GetEntryCount() >= DBGWIN_MAXLINES )
627 maLstBox.RemoveEntry( 0 );
629 sal_uInt16 nInsertionPos = maLstBox.InsertEntry( aStr.copy( 0, nPos ) );
630 if ( bFirstEntry )
631 maLstBox.SetEntryData( nInsertionPos, reinterpret_cast< void* >( 1 ) );
632 bFirstEntry = false;
634 aStr = aStr.replaceAt( 0, nPos+1, "" );
635 nPos = aStr.indexOf( '\n' );
637 if ( maLstBox.GetEntryCount() >= DBGWIN_MAXLINES )
638 maLstBox.RemoveEntry( 0 );
639 sal_uInt16 nInsertionPos = maLstBox.InsertEntry( aStr );
640 if ( bFirstEntry )
641 maLstBox.SetEntryData( nInsertionPos, reinterpret_cast< void* >( 1 ) );
642 maLstBox.SetTopEntry( DBGWIN_MAXLINES-1 );
643 maLstBox.Update();
646 // =======================================================================
648 DbgDialog::DbgDialog() :
649 ModalDialog( NULL, WB_STDMODAL | WB_SYSTEMWINDOW ),
650 maXtorThis( this ),
651 maXtorFunc( this ),
652 maXtorExit( this ),
653 maXtorReport( this ),
654 maXtorTrace( this ),
655 maBox1( this ),
656 maProf( this ),
657 maRes( this ),
658 maDialog( this ),
659 maBoldAppFont( this ),
660 maBox3( this ),
661 maDebugName( this ),
662 maOverwrite( this ),
663 maInclClassText( this ),
664 maInclClassFilter( this ),
665 maExclClassText( this ),
666 maExclClassFilter( this ),
667 maInclText( this ),
668 maInclFilter( this ),
669 maExclText( this ),
670 maExclFilter( this ),
671 maTraceText( this ),
672 maTraceBox( this, WB_DROPDOWN ),
673 maWarningText( this ),
674 maWarningBox( this, WB_DROPDOWN ),
675 maErrorText( this ),
676 maErrorBox( this, WB_DROPDOWN ),
677 maHookOSLBox( this ),
678 maBox4( this ),
679 maOKButton( this, WB_DEFBUTTON ),
680 maCancelButton( this ),
681 maInfoButton( this ),
682 maHelpButton( this )
684 DbgData* pData = DbgGetData();
685 MapMode aAppMap( MAP_APPFONT );
686 Size aButtonSize = LogicToPixel( Size( 60, 12 ), aAppMap );
689 maXtorThis.Show();
690 maXtorThis.SetText("T~his");
691 if ( pData->nTestFlags & DBG_TEST_XTOR_THIS )
692 maXtorThis.Check( sal_True );
693 maXtorThis.SetPosSizePixel( LogicToPixel( Point( 10, 15 ), aAppMap ),
694 aButtonSize );
698 maXtorFunc.Show();
699 maXtorFunc.SetText("~Function");
700 if ( pData->nTestFlags & DBG_TEST_XTOR_FUNC )
701 maXtorFunc.Check( sal_True );
702 maXtorFunc.SetPosSizePixel( LogicToPixel( Point( 75, 15 ), aAppMap ),
703 aButtonSize );
707 maXtorExit.Show();
708 maXtorExit.SetText("E~xit");
709 if ( pData->nTestFlags & DBG_TEST_XTOR_EXIT )
710 maXtorExit.Check( sal_True );
711 maXtorExit.SetPosSizePixel( LogicToPixel( Point( 140, 15 ), aAppMap ),
712 aButtonSize );
716 maXtorReport.Show();
717 maXtorReport.SetText("~Report");
718 if ( pData->nTestFlags & DBG_TEST_XTOR_REPORT )
719 maXtorReport.Check( sal_True );
720 maXtorReport.SetPosSizePixel( LogicToPixel( Point( 205, 15 ), aAppMap ),
721 aButtonSize );
725 maXtorTrace.Show();
726 maXtorTrace.SetText("~Trace");
727 if ( pData->nTestFlags & DBG_TEST_XTOR_TRACE )
728 maXtorTrace.Check( sal_True );
729 maXtorTrace.SetPosSizePixel( LogicToPixel( Point( 270, 15 ), aAppMap ),
730 aButtonSize );
734 maBox1.Show();
735 maBox1.SetText("Object Tests");
736 maBox1.SetPosSizePixel( LogicToPixel( Point( 5, 5 ), aAppMap ),
737 LogicToPixel( Size( 330, 30 ), aAppMap ) );
741 maProf.Show();
742 maProf.SetText("~Profiling");
743 if ( pData->nTestFlags & DBG_TEST_PROFILING )
744 maProf.Check( sal_True );
745 maProf.SetPosSizePixel( LogicToPixel( Point( 10, 95 ), aAppMap ),
746 aButtonSize );
750 maRes.Show();
751 maRes.SetText("~Resourcen");
752 if ( pData->nTestFlags & DBG_TEST_RESOURCE )
753 maRes.Check( sal_True );
754 maRes.SetPosSizePixel( LogicToPixel( Point( 75, 95 ), aAppMap ),
755 aButtonSize );
759 maDialog.Show();
760 maDialog.SetText("~Dialog");
761 if ( pData->nTestFlags & DBG_TEST_DIALOG )
762 maDialog.Check( sal_True );
763 maDialog.SetPosSizePixel( LogicToPixel( Point( 140, 95 ), aAppMap ),
764 aButtonSize );
768 maBoldAppFont.Show();
769 maBoldAppFont.SetText("~Bold AppFont");
770 if ( pData->nTestFlags & DBG_TEST_BOLDAPPFONT )
771 maBoldAppFont.Check( sal_True );
772 maBoldAppFont.SetPosSizePixel( LogicToPixel( Point( 205, 95 ), aAppMap ),
773 aButtonSize );
774 maBoldAppFont.SaveValue();
778 maBox3.Show();
779 maBox3.SetText("Test Options");
780 maBox3.SetPosSizePixel( LogicToPixel( Point( 5, 85 ), aAppMap ),
781 LogicToPixel( Size( 330, 30 ), aAppMap ) );
785 maDebugName.Show();
786 maDebugName.SetText(OStringToOUString(pData->aDebugName, RTL_TEXTENCODING_UTF8));
787 maDebugName.SetMaxTextLen( sizeof( pData->aDebugName ) );
788 maDebugName.SetPosSizePixel( LogicToPixel( Point( 10, 130 ), aAppMap ),
789 LogicToPixel( Size( 185, 14 ), aAppMap ) );
793 maOverwrite.Show();
794 maOverwrite.SetText("Overwrite ~File");
795 if ( pData->bOverwrite )
796 maOverwrite.Check( sal_True );
797 maOverwrite.SetPosSizePixel( LogicToPixel( Point( 205, 130 ), aAppMap ),
798 aButtonSize );
802 maHookOSLBox.Show();
803 maHookOSLBox.SetText("Reroute osl debug ~messages");
804 if ( pData->bHookOSLAssert )
805 maHookOSLBox.Check( sal_True );
806 maHookOSLBox.SetPosSizePixel( LogicToPixel( Point( 10, 240 ), aAppMap ),
807 LogicToPixel( Size( 100, 12 ), aAppMap ) );
811 maInclClassText.Show();
812 maInclClassText.SetText("~Include-ObjectTest-Filter");
813 maInclClassText.SetPosSizePixel( LogicToPixel( Point( 10, 150 ), aAppMap ),
814 LogicToPixel( Size( 95, 9 ), aAppMap ) );
818 maInclClassFilter.Show();
819 maInclClassFilter.SetText(OStringToOUString(pData->aInclClassFilter, RTL_TEXTENCODING_UTF8));
820 maInclClassFilter.SetMaxTextLen( sizeof( pData->aInclClassFilter ) );
821 maInclClassFilter.SetPosSizePixel( LogicToPixel( Point( 10, 160 ), aAppMap ),
822 LogicToPixel( Size( 95, 14 ), aAppMap ) );
826 maExclClassText.Show();
827 maExclClassText.SetText("~Exclude-ObjectTest-Filter");
828 maExclClassText.SetPosSizePixel( LogicToPixel( Point( 115, 150 ), aAppMap ),
829 LogicToPixel( Size( 95, 9 ), aAppMap ) );
833 maExclClassFilter.Show();
834 maExclClassFilter.SetText(OStringToOUString(pData->aExclClassFilter, RTL_TEXTENCODING_UTF8));
835 maExclClassFilter.SetMaxTextLen( sizeof( pData->aExclClassFilter ) );
836 maExclClassFilter.SetPosSizePixel( LogicToPixel( Point( 115, 160 ), aAppMap ),
837 LogicToPixel( Size( 95, 14 ), aAppMap ) );
841 maInclText.Show();
842 maInclText.SetText("~Include-Filter");
843 maInclText.SetPosSizePixel( LogicToPixel( Point( 10, 180 ), aAppMap ),
844 LogicToPixel( Size( 95, 9 ), aAppMap ) );
848 maInclFilter.Show();
849 maInclFilter.SetText(OStringToOUString(pData->aInclFilter, RTL_TEXTENCODING_UTF8));
850 maInclFilter.SetMaxTextLen( sizeof( pData->aInclFilter ) );
851 maInclFilter.SetPosSizePixel( LogicToPixel( Point( 10, 190 ), aAppMap ),
852 LogicToPixel( Size( 95, 14 ), aAppMap ) );
856 maExclText.Show();
857 maExclText.SetText("~Exclude-Filter");
858 maExclText.SetPosSizePixel( LogicToPixel( Point( 115, 180 ), aAppMap ),
859 LogicToPixel( Size( 95, 9 ), aAppMap ) );
863 maExclFilter.Show();
864 maExclFilter.SetText(OStringToOUString(pData->aExclFilter, RTL_TEXTENCODING_UTF8));
865 maExclFilter.SetMaxTextLen( sizeof( pData->aExclFilter ) );
866 maExclFilter.SetPosSizePixel( LogicToPixel( Point( 115, 190 ), aAppMap ),
867 LogicToPixel( Size( 95, 14 ), aAppMap ) );
871 maTraceText.Show();
872 maTraceText.SetText("~Trace");
873 maTraceText.SetPosSizePixel( LogicToPixel( Point( 10, 210 ), aAppMap ),
874 LogicToPixel( Size( 95, 9 ), aAppMap ) );
878 maTraceBox.InsertEntry(OUString("None"));
879 maTraceBox.InsertEntry(OUString("File"));
880 maTraceBox.InsertEntry(OUString("Window"));
881 maTraceBox.InsertEntry(OUString("Shell"));
882 maTraceBox.InsertEntry(OUString("MessageBox"));
883 maTraceBox.InsertEntry(OUString("TestTool"));
884 maTraceBox.InsertEntry(OUString("Debugger"));
885 maTraceBox.InsertEntry(OUString("Abort"));
886 ImplAppendUserDefinedChannels( maTraceBox );
887 ImplSelectChannel( maTraceBox, pData->nTraceOut, 0 );
888 maTraceBox.Show();
889 maTraceBox.SetPosSizePixel( LogicToPixel( Point( 10, 220 ), aAppMap ),
890 LogicToPixel( Size( 95, 80 ), aAppMap ) );
894 maWarningText.Show();
895 maWarningText.SetText("~Warning");
896 maWarningText.SetPosSizePixel( LogicToPixel( Point( 115, 210 ), aAppMap ),
897 LogicToPixel( Size( 95, 9 ), aAppMap ) );
901 maWarningBox.InsertEntry(OUString("None"));
902 maWarningBox.InsertEntry(OUString("File"));
903 maWarningBox.InsertEntry(OUString("Window"));
904 maWarningBox.InsertEntry(OUString("Shell"));
905 maWarningBox.InsertEntry(OUString("MessageBox"));
906 maWarningBox.InsertEntry(OUString("TestTool"));
907 maWarningBox.InsertEntry(OUString("Debugger"));
908 maWarningBox.InsertEntry(OUString("Abort"));
909 ImplAppendUserDefinedChannels( maWarningBox );
910 ImplSelectChannel( maWarningBox, pData->nWarningOut, 0 );
911 maWarningBox.Show();
912 maWarningBox.SetPosSizePixel( LogicToPixel( Point( 115, 220 ), aAppMap ),
913 LogicToPixel( Size( 95, 80 ), aAppMap ) );
917 maErrorText.Show();
918 maErrorText.SetText("~Error");
919 maErrorText.SetPosSizePixel( LogicToPixel( Point( 220, 210 ), aAppMap ),
920 LogicToPixel( Size( 95, 9 ), aAppMap ) );
924 if ( DbgIsAllErrorOut() )
926 maErrorBox.InsertEntry( OUString("None") );
927 maErrorBox.InsertEntry( OUString("File") );
928 maErrorBox.InsertEntry( OUString("Window") );
929 maErrorBox.InsertEntry( OUString("Shell") );
930 mnErrorOff = 0;
932 else
933 mnErrorOff = 4;
934 maErrorBox.InsertEntry( OUString("MessageBox") );
935 maErrorBox.InsertEntry( OUString("TestTool") );
936 maErrorBox.InsertEntry( OUString("Debugger") );
937 maErrorBox.InsertEntry( OUString("Abort") );
938 ImplAppendUserDefinedChannels( maErrorBox );
939 ImplSelectChannel( maErrorBox, pData->nErrorOut, mnErrorOff );
940 maErrorBox.Show();
941 maErrorBox.SetPosSizePixel( LogicToPixel( Point( 220, 220 ), aAppMap ),
942 LogicToPixel( Size( 95, 80 ), aAppMap ) );
946 maBox4.Show();
947 maBox4.SetText("Output");
948 maBox4.SetPosSizePixel( LogicToPixel( Point( 5, 120 ), aAppMap ),
949 LogicToPixel( Size( 330, 135 ), aAppMap ) );
953 maOKButton.Show();
954 maOKButton.SetClickHdl( LINK( this, DbgDialog, ClickHdl ) );
955 maOKButton.SetPosSizePixel( LogicToPixel( Point( 10, 260 ), aAppMap ),
956 LogicToPixel( Size( 50, 15 ), aAppMap ) );
959 maCancelButton.Show();
960 maCancelButton.SetPosSizePixel( LogicToPixel( Point( 70, 260 ), aAppMap ),
961 LogicToPixel( Size( 50, 15 ), aAppMap ) );
964 maInfoButton.Show();
965 maInfoButton.SetClickHdl( LINK( this, DbgDialog, ClickHdl ) );
966 maInfoButton.SetText("~Info...");
967 maInfoButton.SetPosSizePixel( LogicToPixel( Point( 130, 260 ), aAppMap ),
968 LogicToPixel( Size( 50, 15 ), aAppMap ) );
971 maHelpButton.Show();
972 maHelpButton.SetPosSizePixel( LogicToPixel( Point( 190, 260 ), aAppMap ),
973 LogicToPixel( Size( 50, 15 ), aAppMap ) );
977 SetText("VCL Debug Options");
978 SetOutputSizePixel( LogicToPixel( Size( 340, 280 ), aAppMap ) );
982 // -----------------------------------------------------------------------
984 IMPL_LINK( DbgDialog, ClickHdl, Button*, pButton )
986 if ( pButton == &maOKButton )
988 DbgData aData;
990 memcpy( &aData, DbgGetData(), sizeof( DbgData ) );
991 aData.nTestFlags = 0;
993 aData.nTraceOut = ImplGetChannelId( maTraceBox, 0 );
994 aData.nWarningOut = ImplGetChannelId( maWarningBox, 0 );
995 aData.nErrorOut = ImplGetChannelId( maErrorBox, mnErrorOff );
997 strncpy( aData.aDebugName, OUStringToOString(maDebugName.GetText(), RTL_TEXTENCODING_UTF8).getStr(), sizeof( aData.aDebugName ) );
998 strncpy( aData.aInclClassFilter, OUStringToOString(maInclClassFilter.GetText(), RTL_TEXTENCODING_UTF8).getStr(), sizeof( aData.aInclClassFilter ) );
999 strncpy( aData.aExclClassFilter, OUStringToOString(maExclClassFilter.GetText(), RTL_TEXTENCODING_UTF8).getStr(), sizeof( aData.aExclClassFilter ) );
1000 strncpy( aData.aInclFilter, OUStringToOString(maInclFilter.GetText(), RTL_TEXTENCODING_UTF8).getStr(), sizeof( aData.aInclFilter ) );
1001 strncpy( aData.aExclFilter, OUStringToOString(maExclFilter.GetText(), RTL_TEXTENCODING_UTF8).getStr(), sizeof( aData.aExclFilter ) );
1002 aData.aDebugName[sizeof( aData.aDebugName )-1] = '\0';
1003 aData.aInclClassFilter[sizeof( aData.aInclClassFilter )-1] = '\0';
1004 aData.aExclClassFilter[sizeof( aData.aExclClassFilter )-1] = '\0';
1005 aData.aInclFilter[sizeof( aData.aInclFilter )-1] = '\0';
1006 aData.aExclFilter[sizeof( aData.aExclFilter )-1] = '\0';
1008 aData.bOverwrite = maOverwrite.IsChecked() ? sal_True : sal_False;
1009 aData.bHookOSLAssert = maHookOSLBox.IsChecked() ? sal_True : sal_False;
1011 if ( maXtorThis.IsChecked() )
1012 aData.nTestFlags |= DBG_TEST_XTOR_THIS;
1014 if ( maXtorFunc.IsChecked() )
1015 aData.nTestFlags |= DBG_TEST_XTOR_FUNC;
1017 if ( maXtorExit.IsChecked() )
1018 aData.nTestFlags |= DBG_TEST_XTOR_EXIT;
1020 if ( maXtorReport.IsChecked() )
1021 aData.nTestFlags |= DBG_TEST_XTOR_REPORT;
1023 if ( maXtorTrace.IsChecked() )
1024 aData.nTestFlags |= DBG_TEST_XTOR_TRACE;
1026 if ( maProf.IsChecked() )
1027 aData.nTestFlags |= DBG_TEST_PROFILING;
1029 if ( maRes.IsChecked() )
1030 aData.nTestFlags |= DBG_TEST_RESOURCE;
1032 if ( maDialog.IsChecked() )
1033 aData.nTestFlags |= DBG_TEST_DIALOG;
1035 if ( maBoldAppFont.IsChecked() )
1036 aData.nTestFlags |= DBG_TEST_BOLDAPPFONT;
1038 // Daten speichern
1039 DbgSaveData( aData );
1041 // Umschalten der Laufzeitwerte
1042 DBG_INSTOUTTRACE( aData.nTraceOut );
1043 DBG_INSTOUTWARNING( aData.nWarningOut );
1044 DBG_INSTOUTERROR( aData.nErrorOut );
1045 DbgUpdateOslHook( &aData );
1047 DbgData* pData = DbgGetData();
1048 #define IMMEDIATE_FLAGS (DBG_TEST_RESOURCE | DBG_TEST_DIALOG | DBG_TEST_BOLDAPPFONT)
1049 pData->nTestFlags &= ~IMMEDIATE_FLAGS;
1050 pData->nTestFlags |= aData.nTestFlags & IMMEDIATE_FLAGS;
1051 strncpy( pData->aInclClassFilter, aData.aInclClassFilter, sizeof( pData->aInclClassFilter ) );
1052 strncpy( pData->aExclClassFilter, aData.aExclClassFilter, sizeof( pData->aExclClassFilter ) );
1053 strncpy( pData->aInclFilter, aData.aInclFilter, sizeof( pData->aInclFilter ) );
1054 strncpy( pData->aExclFilter, aData.aExclFilter, sizeof( pData->aExclFilter ) );
1055 if ( maBoldAppFont.GetSavedValue() != maBoldAppFont.IsChecked() )
1057 AllSettings aSettings = Application::GetSettings();
1058 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1059 Font aFont = aStyleSettings.GetAppFont();
1060 if ( maBoldAppFont.IsChecked() )
1061 aFont.SetWeight( WEIGHT_BOLD );
1062 else
1063 aFont.SetWeight( WEIGHT_NORMAL );
1064 aStyleSettings.SetAppFont( aFont );
1065 aSettings.SetStyleSettings( aStyleSettings );
1066 Application::SetSettings( aSettings );
1068 if( (aData.nTestFlags & ~IMMEDIATE_FLAGS) != (pData->nTestFlags & ~IMMEDIATE_FLAGS) )
1070 InfoBox aBox( this, OUString(
1071 "Some of the changed settings will only be active after "
1072 "restarting the process"
1073 ) );
1074 aBox.Execute();
1076 EndDialog( sal_True );
1078 else if ( pButton == &maInfoButton )
1080 DbgInfoDialog aInfoDialog( this );
1081 aDbgInfoBuf[0] = '\0';
1082 DbgXtorInfo( aDbgInfoBuf );
1083 OUString aInfoText( aDbgInfoBuf, strlen(aDbgInfoBuf), RTL_TEXTENCODING_UTF8 );
1084 aInfoDialog.SetText( "Debug InfoReport" );
1085 aInfoDialog.SetInfoText( aInfoText );
1086 aInfoDialog.Execute();
1089 return 0;
1092 // -----------------------------------------------------------------------
1094 void DbgDialog::RequestHelp( const HelpEvent& rHEvt )
1096 if ( rHEvt.GetMode() & HELPMODE_CONTEXT )
1098 DbgInfoDialog aInfoDialog( this, true );
1099 OUString aHelpText;
1100 const sal_Char** pHelpStrs = pDbgHelpText;
1101 while ( *pHelpStrs )
1103 aHelpText += OUString::createFromAscii(*pHelpStrs);
1104 pHelpStrs++;
1106 aInfoDialog.SetText( "Debug Hilfe" );
1107 aInfoDialog.SetInfoText( aHelpText );
1108 aInfoDialog.Execute();
1112 // =======================================================================
1114 DbgInfoDialog::DbgInfoDialog( Window* pParent, bool bHelpText ) :
1115 ModalDialog( pParent, WB_STDMODAL ),
1116 maListBox( this, WB_BORDER | WB_AUTOHSCROLL ),
1117 maOKButton( this, WB_DEFBUTTON )
1119 mbHelpText = bHelpText;
1121 if ( !bHelpText )
1123 Font aFont = GetDefaultFont( DEFAULTFONT_FIXED, LANGUAGE_ENGLISH_US, 0 );
1124 aFont.SetHeight( 8 );
1125 aFont.SetPitch( PITCH_FIXED );
1126 maListBox.SetControlFont( aFont );
1128 maListBox.SetPosSizePixel( Point( 5, 5 ), Size( 630, 380 ) );
1129 maListBox.Show();
1131 maOKButton.SetPosSizePixel( Point( 290, 390 ), Size( 60, 25 ) );
1132 maOKButton.Show();
1134 SetOutputSizePixel( Size( 640, 420 ) );
1137 // -----------------------------------------------------------------------
1139 void DbgInfoDialog::SetInfoText( const OUString& rStr )
1141 maListBox.SetUpdateMode( sal_False );
1142 maListBox.Clear();
1143 OUString aStr = convertLineEnd(rStr, LINEEND_LF);
1144 sal_Int32 nStrIndex = 0;
1145 sal_Int32 nFoundIndex;
1148 nFoundIndex = aStr.indexOf( '\n', nStrIndex );
1149 OUString aTextParagraph = aStr.copy( nStrIndex, nFoundIndex-nStrIndex );
1150 if ( mbHelpText )
1152 long nMaxWidth = maListBox.GetOutputSizePixel().Width()-30;
1153 sal_Int32 nLastIndex = 0;
1154 sal_Int32 nIndex = aTextParagraph.indexOf( ' ' );
1155 while ( nIndex != -1 )
1157 if ( maListBox.GetTextWidth( aTextParagraph, 0, nIndex ) > nMaxWidth )
1159 if ( !nLastIndex )
1160 nLastIndex = nIndex+1;
1161 OUString aTempStr = aTextParagraph.copy( 0, nLastIndex );
1162 aTextParagraph = aTextParagraph.replaceAt( 0, nLastIndex, "" );
1163 maListBox.InsertEntry( aTempStr );
1164 nLastIndex = 0;
1166 else
1167 nLastIndex = nIndex+1;
1168 nIndex = aTextParagraph.indexOf( ' ', nLastIndex );
1171 if ( maListBox.GetTextWidth( aTextParagraph, 0, nIndex ) > nMaxWidth )
1173 if ( !nLastIndex )
1174 nLastIndex = nIndex+1;
1175 OUString aTempStr = aTextParagraph.copy( 0, nLastIndex );
1176 aTextParagraph = aTextParagraph.replaceAt( 0, nLastIndex, "" );
1177 maListBox.InsertEntry( aTempStr );
1180 maListBox.InsertEntry( aTextParagraph );
1181 nStrIndex = nFoundIndex+1;
1183 while ( nFoundIndex != -1 );
1184 maListBox.SetUpdateMode( sal_True );
1187 // =======================================================================
1189 void DbgDialogTest( Window* pWindow )
1191 bool aAccelBuf[65536] = {0};
1192 sal_uInt16 nChildCount = pWindow->GetChildCount();
1193 Window* pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
1194 Window* pChild;
1195 Point aTabPos;
1197 if ( !pGetChild )
1198 return;
1200 Rectangle* pRectAry = (Rectangle*)new long[(sizeof(Rectangle)*nChildCount)/sizeof(long)];
1201 memset( pRectAry, 0, sizeof(Rectangle)*nChildCount );
1203 if ( pWindow->IsDialog() )
1205 bool bOKCancelButton = false;
1206 bool bDefPushButton = false;
1207 bool bButton = false;
1208 pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
1209 while ( pGetChild )
1211 pChild = pGetChild->ImplGetWindow();
1213 if ( pChild->ImplIsPushButton() )
1215 bButton = true;
1216 if ( (pChild->GetType() == WINDOW_OKBUTTON) || (pChild->GetType() == WINDOW_CANCELBUTTON) )
1217 bOKCancelButton = true;
1218 if ( pChild->GetStyle() & WB_DEFBUTTON )
1219 bDefPushButton = true;
1222 pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
1225 if ( bButton )
1227 SAL_WARN_IF(
1228 !bOKCancelButton, "vcl",
1229 "Dialogs should have a OK- or CancelButton");
1230 SAL_WARN_IF(
1231 !bDefPushButton, "vcl",
1232 "Dialogs should have a Button with WB_DEFBUTTON");
1236 sal_uInt16 i = 0;
1237 pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
1238 while ( pGetChild )
1240 pChild = pGetChild->ImplGetWindow();
1242 if ( (pChild->GetType() != WINDOW_TABCONTROL) &&
1243 (pChild->GetType() != WINDOW_TABPAGE) &&
1244 (pChild->GetType() != WINDOW_GROUPBOX) )
1246 OUString aText = pChild->GetText();
1247 OUString aErrorText = aText;
1248 sal_Int32 nAccelPos = -1;
1249 sal_Unicode cAccel = 0;
1250 if ( aErrorText.getLength() > 128 )
1252 aErrorText = aErrorText.replaceAt( 128, aErrorText.getLength()-128, "" );
1253 aErrorText += "...";
1255 if ( !aText.isEmpty() && (aText.getLength() < 1024) )
1257 nAccelPos = aText.indexOf( '~' );
1258 if ( nAccelPos != -1 )
1260 const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
1261 uno::Reference < i18n::XCharacterClassification > xCharClass = vcl::unohelper::CreateCharacterClassification();
1262 OUString aUpperText = xCharClass->toUpper( aText, 0, aText.getLength(), rLocale );
1263 cAccel = aUpperText[nAccelPos+1];
1264 if ( pChild->IsVisible() )
1266 if ( aAccelBuf[cAccel] )
1267 DbgOutTypef( DBG_OUT_ERROR, "Double mnemonic char: %c", cAccel );
1268 else
1269 aAccelBuf[cAccel] = true;
1274 if ( (pChild->GetType() == WINDOW_RADIOBUTTON) ||
1275 (pChild->GetType() == WINDOW_CHECKBOX) ||
1276 (pChild->GetType() == WINDOW_TRISTATEBOX) ||
1277 (pChild->GetType() == WINDOW_PUSHBUTTON) )
1279 if ( !aText.isEmpty() && aText != "..." )
1281 const char* pClass;
1282 if ( pChild->GetType() == WINDOW_RADIOBUTTON )
1283 pClass = "RadioButton";
1284 else if ( pChild->GetType() == WINDOW_CHECKBOX )
1285 pClass = "CheckBox";
1286 else if ( pChild->GetType() == WINDOW_TRISTATEBOX )
1287 pClass = "TriStateBox";
1288 else if ( pChild->GetType() == WINDOW_PUSHBUTTON )
1289 pClass = "PushButton";
1290 else
1291 pClass = "Dontknow";
1292 if( !cAccel )
1293 DbgOutTypef( DBG_OUT_ERROR,
1294 "%s should have a mnemonic char (~): %s",
1295 pClass,
1296 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1298 // check text width
1299 int aWidth=0;
1300 switch( pChild->GetType() )
1302 case WINDOW_RADIOBUTTON:
1303 aWidth = ((RadioButton*)pChild)->CalcMinimumSize(0).Width();
1304 break;
1305 case WINDOW_CHECKBOX:
1306 case WINDOW_TRISTATEBOX:
1307 aWidth = ((CheckBox*)pChild)->CalcMinimumSize(0).Width();
1308 break;
1309 case WINDOW_PUSHBUTTON:
1310 aWidth = ((PushButton*)pChild)->CalcMinimumSize(0).Width();
1311 break;
1312 default: break;
1314 if( pChild->IsVisible() && pChild->GetSizePixel().Width() < aWidth )
1315 DbgOutTypef( DBG_OUT_ERROR,
1316 "%s exceeds window width: %s",
1317 pClass,
1318 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1322 if ( pChild->GetType() == WINDOW_FIXEDLINE )
1324 if ( pChild->GetSizePixel().Width() < pChild->GetTextWidth( aText ) )
1325 DbgOutTypef( DBG_OUT_ERROR,
1326 "FixedLine exceeds window width: %s",
1327 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1330 if ( pChild->GetType() == WINDOW_FIXEDTEXT )
1332 if ( (pChild->GetSizePixel().Height() >= pChild->GetTextHeight()*2) &&
1333 !(pChild->GetStyle() & WB_WORDBREAK) )
1335 DbgOutTypef( DBG_OUT_ERROR,
1336 "FixedText greater than one line, but WordBreak is not set: %s",
1337 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1340 if ( pChild->IsVisible() )
1342 int aWidth=0;
1343 if( nAccelPos != -1 )
1345 aWidth = pChild->GetTextWidth( aText, 0, nAccelPos ) +
1346 pChild->GetTextWidth( aText, nAccelPos+1, aText.getLength() - nAccelPos - 1);
1348 else
1349 aWidth = pChild->GetTextWidth( aText );
1351 if ( pChild->GetSizePixel().Width() < aWidth && !(pChild->GetStyle() & WB_WORDBREAK) )
1353 DbgOutTypef( DBG_OUT_ERROR,
1354 "FixedText exceeds window width: %s",
1355 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1359 if ( (i+1 < nChildCount) && !aText.isEmpty() )
1361 Window* pTempChild = pGetChild->GetWindow( WINDOW_NEXT )->ImplGetWindow();
1362 if ( (pTempChild->GetType() == WINDOW_EDIT) ||
1363 (pTempChild->GetType() == WINDOW_MULTILINEEDIT) ||
1364 (pTempChild->GetType() == WINDOW_SPINFIELD) ||
1365 (pTempChild->GetType() == WINDOW_PATTERNFIELD) ||
1366 (pTempChild->GetType() == WINDOW_NUMERICFIELD) ||
1367 (pTempChild->GetType() == WINDOW_METRICFIELD) ||
1368 (pTempChild->GetType() == WINDOW_CURRENCYFIELD) ||
1369 (pTempChild->GetType() == WINDOW_DATEFIELD) ||
1370 (pTempChild->GetType() == WINDOW_TIMEFIELD) ||
1371 (pTempChild->GetType() == WINDOW_LISTBOX) ||
1372 (pTempChild->GetType() == WINDOW_MULTILISTBOX) ||
1373 (pTempChild->GetType() == WINDOW_COMBOBOX) ||
1374 (pTempChild->GetType() == WINDOW_PATTERNBOX) ||
1375 (pTempChild->GetType() == WINDOW_NUMERICBOX) ||
1376 (pTempChild->GetType() == WINDOW_METRICBOX) ||
1377 (pTempChild->GetType() == WINDOW_CURRENCYBOX) ||
1378 (pTempChild->GetType() == WINDOW_DATEBOX) ||
1379 (pTempChild->GetType() == WINDOW_TIMEBOX) )
1381 if ( !cAccel )
1383 DbgOutTypef( DBG_OUT_ERROR,
1384 "Labels befor Fields (Edit,ListBox,...) should have a mnemonic char (~): %s",
1385 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1387 if ( !pTempChild->IsEnabled() && pChild->IsEnabled() )
1389 DbgOutTypef( DBG_OUT_ERROR,
1390 "Labels befor Fields (Edit,ListBox,...) should be disabled, when the field is disabled: %s",
1391 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1397 SAL_WARN_IF(
1398 (pChild->GetType() == WINDOW_MULTILINEEDIT
1399 && (pChild->GetStyle() & (WB_IGNORETAB | WB_READONLY)) == 0),
1400 "vcl",
1401 ("editable MultiLineEdits in Dialogs should have the Style"
1402 " WB_IGNORETAB"));
1404 if ( (pChild->GetType() == WINDOW_RADIOBUTTON) ||
1405 (pChild->GetType() == WINDOW_CHECKBOX) ||
1406 (pChild->GetType() == WINDOW_TRISTATEBOX) ||
1407 (pChild->GetType() == WINDOW_FIXEDTEXT) )
1409 pChild->SetBackground( Wallpaper( Color( COL_LIGHTGREEN ) ) );
1412 if ( pChild->IsVisible() )
1414 bool bMaxWarning = false;
1415 if ( pChild->GetType() == WINDOW_NUMERICFIELD )
1417 NumericField* pField = (NumericField*)pChild;
1418 if ( pField->GetMax() == LONG_MAX )
1419 bMaxWarning = true;
1421 else if ( pChild->GetType() == WINDOW_METRICFIELD )
1423 MetricField* pField = (MetricField*)pChild;
1424 if ( pField->GetMax() == LONG_MAX )
1425 bMaxWarning = true;
1427 else if ( pChild->GetType() == WINDOW_CURRENCYFIELD )
1429 CurrencyField* pField = (CurrencyField*)pChild;
1430 if ( pField->GetMax() == LONG_MAX )
1431 bMaxWarning = true;
1433 else if ( pChild->GetType() == WINDOW_TIMEFIELD )
1435 TimeField* pField = (TimeField*)pChild;
1436 if ( pField->GetMax() == Time( 23, 59, 59, 99 ) )
1437 bMaxWarning = true;
1439 else if ( pChild->GetType() == WINDOW_DATEFIELD )
1441 DateField* pField = (DateField*)pChild;
1442 if ( pField->GetMax() == Date( 31, 12, 9999 ) )
1443 bMaxWarning = true;
1445 else if ( pChild->GetType() == WINDOW_NUMERICBOX )
1447 NumericBox* pBox = (NumericBox*)pChild;
1448 if ( pBox->GetMax() == LONG_MAX )
1449 bMaxWarning = true;
1451 else if ( pChild->GetType() == WINDOW_METRICBOX )
1453 MetricBox* pBox = (MetricBox*)pChild;
1454 if ( pBox->GetMax() == LONG_MAX )
1455 bMaxWarning = true;
1457 else if ( pChild->GetType() == WINDOW_CURRENCYBOX )
1459 CurrencyBox* pBox = (CurrencyBox*)pChild;
1460 if ( pBox->GetMax() == LONG_MAX )
1461 bMaxWarning = true;
1463 else if ( pChild->GetType() == WINDOW_TIMEBOX )
1465 TimeBox* pBox = (TimeBox*)pChild;
1466 if ( pBox->GetMax() == Time( 23, 59, 59, 99 ) )
1467 bMaxWarning = true;
1469 else if ( pChild->GetType() == WINDOW_DATEBOX )
1471 DateBox* pBox = (DateBox*)pChild;
1472 if ( pBox->GetMax() == Date( 31, 12, 9999 ) )
1473 bMaxWarning = true;
1475 if ( bMaxWarning )
1477 DbgOutTypef( DBG_OUT_ERROR,
1478 "No Max-Value is set: %s",
1479 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1482 if ( (pChild->GetType() == WINDOW_RADIOBUTTON) ||
1483 (pChild->GetType() == WINDOW_CHECKBOX) ||
1484 (pChild->GetType() == WINDOW_TRISTATEBOX) ||
1485 (pChild->GetType() == WINDOW_PUSHBUTTON) ||
1486 (pChild->GetType() == WINDOW_OKBUTTON) ||
1487 (pChild->GetType() == WINDOW_CANCELBUTTON) ||
1488 (pChild->GetType() == WINDOW_HELPBUTTON) ||
1489 (pChild->GetType() == WINDOW_IMAGEBUTTON) ||
1490 (pChild->GetType() == WINDOW_FIXEDTEXT) ||
1491 (pChild->GetType() == WINDOW_EDIT) ||
1492 (pChild->GetType() == WINDOW_MULTILINEEDIT) ||
1493 (pChild->GetType() == WINDOW_SPINFIELD) ||
1494 (pChild->GetType() == WINDOW_PATTERNFIELD) ||
1495 (pChild->GetType() == WINDOW_NUMERICFIELD) ||
1496 (pChild->GetType() == WINDOW_METRICFIELD) ||
1497 (pChild->GetType() == WINDOW_CURRENCYFIELD) ||
1498 (pChild->GetType() == WINDOW_DATEFIELD) ||
1499 (pChild->GetType() == WINDOW_TIMEFIELD) ||
1500 (pChild->GetType() == WINDOW_LISTBOX) ||
1501 (pChild->GetType() == WINDOW_MULTILISTBOX) ||
1502 (pChild->GetType() == WINDOW_COMBOBOX) ||
1503 (pChild->GetType() == WINDOW_PATTERNBOX) ||
1504 (pChild->GetType() == WINDOW_NUMERICBOX) ||
1505 (pChild->GetType() == WINDOW_METRICBOX) ||
1506 (pChild->GetType() == WINDOW_CURRENCYBOX) ||
1507 (pChild->GetType() == WINDOW_DATEBOX) ||
1508 (pChild->GetType() == WINDOW_TIMEBOX) )
1510 Point aNewPos = pChild->GetPosPixel();
1511 Rectangle aChildRect( aNewPos, pChild->GetSizePixel() );
1513 if ( cAccel || (pChild->GetStyle() & WB_TABSTOP) ||
1514 (pChild->GetType() == WINDOW_RADIOBUTTON) )
1516 if ( (aNewPos.X() <= aTabPos.X()) && (aNewPos.Y() <= aTabPos.Y()) )
1518 DbgOutTypef( DBG_OUT_ERROR,
1519 "Possible wrong childorder for dialogcontrol: %s",
1520 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1522 aTabPos = aNewPos;
1525 for ( sal_uInt16 j = 0; j < i; j++ )
1527 if ( ((pRectAry[j].Right() != 0) || (pRectAry[j].Bottom() != 0)) &&
1528 aChildRect.IsOver( pRectAry[j] ) )
1530 DbgOutTypef( DBG_OUT_ERROR,
1531 "Window overlaps with sibling window: %s",
1532 OUStringToOString(aErrorText, RTL_TEXTENCODING_UTF8).getStr() );
1535 pRectAry[i] = aChildRect;
1540 pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
1541 i++;
1544 delete [] pRectAry;
1547 // =======================================================================
1548 #ifndef WNT
1549 #define USE_VCL_MSGBOX
1550 #define COPY_BUTTON_ID 25
1552 class DbgMessageBox : public ErrorBox
1554 OUString m_aMessage;
1555 public:
1556 DbgMessageBox( const OUString& rMessage ) :
1557 ErrorBox( NULL, WB_YES_NO_CANCEL | WB_DEF_NO, rMessage ),
1558 m_aMessage( rMessage )
1560 SetText("Debug Output");
1561 AddButton(OUString("Copy"), COPY_BUTTON_ID, 0);
1564 virtual void Click()
1566 if( GetCurButtonId() == COPY_BUTTON_ID )
1567 vcl::unohelper::TextDataObject::CopyStringTo( m_aMessage, GetClipboard() );
1568 else
1569 ErrorBox::Click();
1573 #endif
1575 class SolarMessageBoxExecutor : public ::vcl::SolarThreadExecutor
1577 private:
1578 OUString m_sDebugMessage;
1580 public:
1581 SolarMessageBoxExecutor( const OUString& _rDebugMessage )
1582 :m_sDebugMessage( _rDebugMessage )
1586 protected:
1587 virtual long doIt();
1590 long SolarMessageBoxExecutor::doIt()
1592 long nResult = RET_NO;
1594 // Stop tracking and release mouse, to assure boxes do not hang
1595 ImplSVData* pSVData = ImplGetSVData();
1596 if ( pSVData->maWinData.mpTrackWin )
1597 pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
1598 if ( pSVData->maWinData.mpCaptureWin )
1599 pSVData->maWinData.mpCaptureWin->ReleaseMouse();
1601 #if ! defined USE_VCL_MSGBOX
1602 #ifdef WNT
1603 sal_Bool bOldCallTimer = pSVData->mbNoCallTimer;
1604 pSVData->mbNoCallTimer = sal_True;
1605 nResult = MessageBoxW( 0, (LPWSTR)m_sDebugMessage.getStr(), L"Debug Output",
1606 MB_TASKMODAL | MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_ICONSTOP );
1607 pSVData->mbNoCallTimer = bOldCallTimer;
1608 switch ( nResult )
1610 case IDYES:
1611 nResult = RET_YES;
1612 break;
1613 case IDNO:
1614 nResult = RET_NO;
1615 break;
1616 case IDCANCEL:
1617 nResult = RET_CANCEL;
1618 break;
1620 #endif // WNT
1621 #else
1622 sal_uInt16 nOldMode = Application::GetSystemWindowMode();
1623 Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
1624 DbgMessageBox aBox( m_sDebugMessage );
1625 Application::SetSystemWindowMode( nOldMode );
1626 nResult = aBox.Execute();
1627 #endif
1629 return nResult;
1632 void DbgPrintMsgBox( const char* pLine )
1634 // are modal message boxes prohibited at the moment?
1635 if ( Application::IsDialogCancelEnabled() )
1637 #if defined( WNT )
1638 // TODO: Shouldn't this be a IsDebuggerPresent()?
1639 if ( GetSystemMetrics( SM_DEBUG ) )
1641 strcpy( aDbgOutBuf, pLine );
1642 strcat( aDbgOutBuf, "\r\n" );
1643 OutputDebugString( aDbgOutBuf );
1644 return;
1646 #endif
1648 #ifdef UNX
1649 fprintf( stderr, "%s\n", pLine );
1650 return;
1651 #else
1652 DbgPrintFile( pLine );
1653 return;
1654 #endif
1657 strcpy( aDbgOutBuf, pLine );
1658 #if defined UNX && HAVE_FEATURE_DESKTOP
1659 strcat( aDbgOutBuf, "\nAbort ? (Yes=abort / No=ignore / Cancel=core dump)" );
1660 #elif defined _WIN32
1661 strcat( aDbgOutBuf, "\nAbort ? (Yes=abort / No=ignore / Cancel=try to invoke debugger)" );
1662 #else
1663 strcat( aDbgOutBuf, "\nAbort ? (Yes=abort / No=ignore / Cancel=crash)" );
1664 #endif
1666 SolarMessageBoxExecutor aMessageBox( OUString( aDbgOutBuf, strlen(aDbgOutBuf), RTL_TEXTENCODING_UTF8 ) );
1667 TimeValue aTimeout; aTimeout.Seconds = 2; aTimeout.Nanosec = 0;
1668 long nResult = aMessageBox.execute( aTimeout );
1670 if ( aMessageBox.didTimeout() )
1671 DbgPrintShell( pLine );
1672 else if ( nResult == RET_YES )
1673 GetpApp()->Abort( OUString("Debug-Utilities-Error") );
1674 else if ( nResult == RET_CANCEL )
1675 DbgCoreDump();
1678 // -----------------------------------------------------------------------
1680 class SolarWindowPrinter : public ::vcl::SolarThreadExecutor
1682 private:
1683 OUString m_sDebugMessage;
1685 public:
1686 SolarWindowPrinter( const OUString& _rDebugMessage )
1687 :m_sDebugMessage( _rDebugMessage )
1691 protected:
1692 virtual long doIt();
1695 long SolarWindowPrinter::doIt()
1697 DbgWindow* pDbgWindow = ImplGetSVData()->maWinData.mpDbgWin;
1698 if ( !pDbgWindow )
1700 pDbgWindow = new DbgWindow;
1701 ImplGetSVData()->maWinData.mpDbgWin = pDbgWindow;
1703 pDbgWindow->InsertLine( m_sDebugMessage );
1705 return 0L;
1708 // -----------------------------------------------------------------------
1710 void DbgPrintWindow( const char* pLine )
1712 static bool bIn = false;
1714 // keine rekursiven Traces
1715 if ( bIn )
1716 return;
1717 bIn = true;
1719 SolarWindowPrinter aPrinter( OUString( pLine, strlen(pLine), RTL_TEXTENCODING_UTF8 ) );
1720 TimeValue aTimeout; aTimeout.Seconds = 2; aTimeout.Nanosec = 0;
1721 aPrinter.execute( aTimeout );
1723 if ( aPrinter.didTimeout() )
1724 DbgPrintShell( pLine );
1726 bIn = false;
1729 // -----------------------------------------------------------------------
1731 void DbgAbort( char const * i_message )
1733 OUString const message( i_message, strlen( i_message ), osl_getThreadTextEncoding() );
1734 Application::Abort( message );
1737 // =======================================================================
1739 void ImplDbgTestSolarMutex()
1741 assert(ImplGetSVData()->mpDefInst->CheckYieldMutex());
1744 // =======================================================================
1746 void DbgGUIInit()
1748 DbgSetPrintMsgBox( DbgPrintMsgBox );
1749 DbgSetPrintWindow( DbgPrintWindow );
1750 DbgSetTestSolarMutex( ImplDbgTestSolarMutex );
1751 DbgSetAbort( DbgAbort );
1754 // -----------------------------------------------------------------------
1756 void DbgGUIDeInit()
1758 DbgSetPrintMsgBox( NULL );
1759 DbgSetPrintWindow( NULL );
1760 DbgSetTestSolarMutex( NULL );
1761 DbgSetAbort( NULL );
1763 DbgWindow* pDbgWindow = ImplGetSVData()->maWinData.mpDbgWin;
1764 delete pDbgWindow;
1767 // -----------------------------------------------------------------------
1769 void DbgGUIStart()
1771 DbgData* pData = DbgGetData();
1773 if ( pData )
1775 DbgDialog* pDialog = new DbgDialog;
1776 // we switch off dialog tests for the debug dialog
1777 sal_uLong nOldFlags = pData->nTestFlags;
1778 pData->nTestFlags &= ~DBG_TEST_DIALOG;
1779 if ( !pDialog->Execute() )
1780 pData->nTestFlags |= (nOldFlags & DBG_TEST_DIALOG);
1781 delete pDialog;
1783 else
1785 ErrorBox( 0, WB_OK, OUString("TOOLS Library has no Debug-Routines") ).Execute();
1789 #endif // DBG_UTIL
1791 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */