xref: /aoo42x/main/vcl/source/app/dbggui.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <sal/config.h>
32 
33 #ifdef DBG_UTIL
34 
35 #include <cstdio>
36 #include <cstring>
37 #include <cmath>
38 #include <limits.h>
39 
40 #include "tools/debug.hxx"
41 
42 #include "vos/mutex.hxx"
43 
44 #include "vcl/svapp.hxx"
45 #include "vcl/event.hxx"
46 #include "vcl/lstbox.hxx"
47 #include "vcl/button.hxx"
48 #include "vcl/edit.hxx"
49 #include "vcl/fixed.hxx"
50 #include "vcl/group.hxx"
51 #include "vcl/field.hxx"
52 #include "vcl/msgbox.hxx"
53 #include "vcl/wrkwin.hxx"
54 #include "vcl/sound.hxx"
55 #include "vcl/threadex.hxx"
56 
57 #include "svdata.hxx"
58 #include "dbggui.hxx"
59 
60 #include "vcl/unohelp.hxx"
61 #include "vcl/unohelp2.hxx"
62 
63 #include "salinst.hxx"
64 #include "svdata.hxx"
65 #include "svsys.h"
66 
67 #include "com/sun/star/i18n/XCharacterClassification.hpp"
68 
69 #include <map>
70 #include <algorithm>
71 
72 using namespace ::com::sun::star;
73 
74 // =======================================================================
75 
76 static const sal_Char* pDbgHelpText[] =
77 {
78 "Object Test\n",
79 "------------------------------------------\n",
80 "\n",
81 "--- Macros ---\n",
82 "DBG_NAME( aName )\n",
83 "Defines the administration data for a class. This macro may only be used "
84 " in a source file with the same name.\n",
85 "\n",
86 "DBG_NAMEEX( aName )\n",
87 "Like DBG_NAME, only for other source files.\n",
88 "\n",
89 "DBG_CTOR( aName, fTest )\n",
90 "Must be used in all constructors of a class (also in the CopyCtor). "
91 "The first parameter must be the registered name (best would be the "
92 "class name) and the second parameter the test function or 0.\n",
93 "\n",
94 "DBG_DTOR( aName, fTest )\n",
95 "Must be used in the destructor of the class. The first parameter is "
96 "the registered name and the second parameter is the test function or "
97 "0.\n",
98 "\n",
99 "DBG_CHKTHIS( aName, fTest )\n",
100 "Can be used in methods of the class when constructors and the "
101 "desctructor of the class are equiped with the corresponding macros. "
102 "The first parameter is the registered name, the second parameter is "
103 "the test function or 0.\n",
104 "\n",
105 "DBG_CHKOBJ( pObj, aName, fTest )\n",
106 "Can be used on instances of a class where the constructors and the "
107 "destructor of the class are equiped with the corresponding macros. "
108 "The first parameter is the registered name, the second parameter is "
109 "the test function or 0.\n",
110 "\n",
111 "To make the macros work DBG_UTIL must be defined.\n",
112 "\n",
113 "--- Options ---\n",
114 "This\n",
115 "The This pointer is validated. This way all objects that are equiped "
116 "with it can be tested to make sure one is working with existing objects. "
117 "This way it's easier to find bugs in case of multiple inheritence, "
118 "alignment or compiler errors. Since almost all standard classes of SV "
119 "(String, List, Pen, Brush, Polygon, ...) are equiped with DBG_CHKTHIS() "
120 "a lot of errors are found, although this test will impact performance "
121 "accordingly.\n",
122 "\n",
123 "Function\n",
124 "When a function is passed with macros, it will be called.\n",
125 "\n",
126 "Exit\n",
127 "This- and Func-Test will also run when exiting the function.\n",
128 "\n",
129 "Report\n",
130 "At the end of the program the number of generated objects is produced "
131 "as output. Because all important SV classes have at least DBG_CTOR() / "
132 "DBG_DTOR() it can checked so called resource leaks (system objects which "
133 " are not freed) exist. These include OutputDevice, Window, VirtualDevice, "
134 " Printer and Menu. Note: Dtor calls of static objects are not taken into "
135 " account. Therefor each SV program leaves 2 strings and a bitmap behind.\n",
136 "\n",
137 "Trace\n",
138 "Creation, destruction and usage of objects which are equiped with "
139 "DBG_XTOR is logged.\n",
140 "\n",
141 "\n",
142 "Memory Test\n",
143 "------------------------------------------\n",
144 "\n",
145 "--- Macros ---\n",
146 "DBG_MEMTEST()\n",
147 "Run the specified memory tests.\n",
148 "\n",
149 "DBG_MEMTEST_PTR( p )\n",
150 "Runs the specified memory tests and validates the pointer that was "
151 "passed if the pointer test is enabled.\n",
152 "\n",
153 "--- Options ---\n",
154 "Initialize\n",
155 "Allocated memory is initialized with 0x77 and free or freed memory "
156 "is initialized with 0x33. This option has almost no impact on performance "
157 "and should thus always be enabled during development. This will also "
158 "make crashes more often reproducable.\n",
159 "\n",
160 "Overwrite\n",
161 "This test check whether writes occur before or after the blocks. Before "
162 "and after the block memory is initialized with 0x55. This option costs "
163 "performance, but should be enabled once in a while to test for common "
164 "memory overwrites (+-1 errors). This option should also be enabled if the "
165 "program crashes in a new or delete operator.\n",
166 "\n",
167 "Free\n",
168 "This checks whether writes occur in free memory. This option costs lots "
169 " of performance and should thus only be used to test memory overwrites. "
170 " This option should perhaps also be enabled when the program crashes "
171 " in the new or delete operator.\n",
172 "\n",
173 "Pointer\n",
174 "The pointer is tested with delete and DBG_MEMTEST_PTR() to see if it was "
175 "created by new or SvMemAlloc(). When this option is enabled errors such as "
176 "double deletes, deletes on stack objects or invalid pointers will be found. "
177 "This option has an impact on performance and should therefor not be enabled "
178 "all the time. However, testing should be done with this option enabled once "
179 "in a while, because the memory manager does not always crash with delete and "
180 "invalid pointers. This option should also be enabled if the program crashes "
181 "in new or delete operators.\n",
182 "\n",
183 "Report\n",
184 "At the end of the program a small statistic and memory that was not freed are "
185 "output. Note: memory that is freed by global objects is also included in "
186 "the leak list.\n",
187 "\n",
188 "Trace\n",
189 "Allocating and freeing memory is logged.\n",
190 "\n",
191 "Leak report\n",
192 "Produces under WNT at the end of the program a list of memory leaks with "
193 "stack trace. Only blocks which were created inside Application::Execute() "
194 "are included. When this option and Overwrite are both enabled a memory "
195 "overwrite results in an attempt to output the stack where the block was "
196 "created. The output is included in the log file after the error message.\n"
197 "\n",
198 "New/Delete\n",
199 "Memory tests are performed on the entire memory with every new/delet. "
200 "Warning: this option makes programs very slow and should only be enabled "
201 "to track memory overwrites. Otherwise it is sufficient to enable "
202 "seperate options because (if no leak is present) every detectable "
203 "memory overwrite during run time should be found.\n",
204 "\n",
205 "Object Test\n",
206 "Memory test are performed on the entire memory with every object test. "
207 "Warning: this option makes programs very slow and should only be enabled "
208 "to track memory overwrite. Otherwise it is sufficient to enable "
209 "seperate options because (if no leak is present) every detectable "
210 "memory overwrite during run time should be found.\n",
211 "\n",
212 "Windows 16-bit and debug tests\n",
213 "Warning: when memory test are enabled (except for Initialize) memory with "
214 "offset 0 is never (even not in case of >= 64KB) returned. If necessary the "
215 "tests can be performed with 32-bit versions of the programs. To a certain "
216 "extend it is sufficient to create 64KB - 64 bytes instead of 64KB because "
217 "it will never come to a segment overflow.\n",
218 "Memory and object test should only be enabled when only one SV application "
219 "is running at one time. Otherwise uncontrolled errors may occur. In this "
220 "case only the use of 32-bit programs can help."
221 "\n",
222 "\n",
223 "\nOther tests and macros\n",
224 "------------------------------------------\n",
225 "\n",
226 "Profiling\n",
227 "DBG_PROFSTART() / DBG_PROFSTOP() / DBG_PROFCONTINUE() / DBG_PROFPAUSE() "
228 "are evaluated and at the end of the program the number of run throughs "
229 "and the time this took (including calls to children) in milliseconds is "
230 "output. These macros can be used to check the same function runs over the "
231 "entire development period, for example the startup speed. The registered name "
232 "which was registered with DBG_NAME() must be passed to the macros.\n",
233 "\n",
234 "Resources\n",
235 "In case of resource errors an error dialog is produced before the "
236 "exception handler is called.\n",
237 "\n",
238 "Dialog\n",
239 "FixedTexts, CheckBoxes, TriStateBoxes and RadioButtons are equiped with "
240 "a different background color to determine the size of the controls. This "
241 "test also shows whether controls overlap, whether the tab order is correct "
242 "and whether the mnemonic characters are correctly assigned. With dialogs "
243 "it is indicated when no default button or no OK/CancelButton is present. "
244 "These tests are not 100% correct (e.g. too many warnings are given) and "
245 "do not form any guarantee that all problematic cases are covered. For "
246 "example only initial and only visible controls are tested. No errors are "
247 "found which will occur during the use of a dialog.\n",
248 "\n",
249 "Bold AppFont\n",
250 "The application font is set to bold to see if the position of texts is "
251 "sufficient for other systems or other system settings. With very narrow "
252 "fonts the dialogs are made wider because they otherwise appear too narrow.\n",
253 "\n",
254 "Trace output\n",
255 "DBG_TRACE() can be use to produce TRACE output. DBG_TRACEFILE() also outputs "
256 "the file and line number where the macro is located. DBG_TRACE1() to "
257 "DBG_TRACE5() can be used to produce formatted output (printf format string) "
258 "Trace output is enabled when the corresponding option is selected in the "
259 "dropdown list.\n"
260 "\n",
261 "Warnings\n",
262 "DBG_WARNING() can be used to output warnings. DBG_WARNINGFILE() also outputs "
263 "the file and the line number where the macro is located. DBG_WARNING1() to "
264 "DBG_WARNING5() can be used to produce formatted output (printf format string). "
265 "In case you want to have conditional warnings DBG_ASSERTWARNING() can be "
266 "used. The warning will be produced if the condition was not met. The first "
267 "parameter is the condition and the second parameter is the message to be "
268 "produced. Warnings are enabled if the corresponding option is selected in the "
269 "dropdown box. When none are selected the condition with DBG_ASSERTWARNING() "
270 "is not evaluated.\n",
271 "\n",
272 "Errors\n",
273 "DBG_ERROR() can be used to produce error messages. DBG_ERRORFILE() also "
274 "produces the file and the line number where the macro is located. "
275 "DBG_ERROR1() bis DBG_ERROR5() can be used to produce formatted output "
276 "(print format string). "
277 "In case you want to have conditional warnings DBG_ASSERT() can be "
278 "used. The warning will be produced if the condition was not met. The first "
279 "parameter is the condition and the second parameter is the message to be "
280 "produced. Warnings are enabled if the corresponding option is selected in the "
281 "dropdown box. When none are selected the condition with DBG_ASSERT() "
282 "is not evaluated.\n",
283 "\n",
284 "\n",
285 "Output\n",
286 "------------------------------------------\n",
287 "\n",
288 "Overwrite - CheckBox\n",
289 "With every new program start the log file is overwritten if output has been "
290 "generated.\n",
291 "\n",
292 "Include ObjectTest filters\n",
293 "Only classes which contain one of the indicated filters are evaluated with "
294 "the object test. Filters are seperated by ';' and are case sensitive. "
295 "Wildcards are not supported. If no text is indicated the filters are not "
296 "active.\n",
297 "\n",
298 "Exclude ObjectTest filters\n",
299 "Only classes which do not contain one of the indicated filters are evaluated "
300 "with the object test. Filters are seperated by ';' and are case sensitive. "
301 "Wildcards are not supported. If no text is indicated the filters are not "
302 "active.\n",
303 "\n",
304 "Include filters\n",
305 "Only those texts which include the indicated filters are output. "
306 "Filters are seperated by ';' and are case sensitive. "
307 "Wildcards are not supported. The filter is used for all output (except for "
308 "errors). If no text is indicated the filters are not active.\n",
309 "\n",
310 "Exclude filters\n",
311 "Only those texts which do not include the indicated filters are output. "
312 "Filters are seperated by ';' and are case sensitive. "
313 "Wildcards are not supported. The filter is used for all output (except for "
314 "errors). If no text is indicated the filters are not active.\n",
315 "\n",
316 "Furthermore you can indicate where the data will be output:\n",
317 "\n",
318 "None\n",
319 "Output is surpressed.\n",
320 "\n",
321 "File\n",
322 "Outputi n debug file. Filename can be entered in the Editfield.\n",
323 "\n",
324 "Window\n",
325 "Output to a small debug window. The window size is stored if the debug "
326 "dialog is closed with OK and if the window is visible. Each assertion text can "
327 "be copied to the clipboard via the context menu of the respective entry.\n",
328 "\n",
329 "Shell\n",
330 "Output to a debug system (Windows debug window) when available or under "
331 "Unix in the shell window. Otherwise the same as Window.\n",
332 "\n",
333 "MessageBox\n",
334 "Output to a MessageBox. In this case you can select whether the program "
335 "must be continued, terminated (Application::Abort) or interrupted with "
336 "CoreDump. Additionally on some systems you get a \"Copy\" button pressing which "
337 "copies the text of the MessageBox to the clipboard. Because a MessageBox allows "
338 "further event processing other errors caused by Paint, Activate/Deactivate, "
339 "GetFocus/LoseFocus can cause more errors or incorrect errors and messages. "
340 "Therefor the message should also be directed to a file/debugger in case of "
341 "problems in order to produce the (right) error messages.\n",
342 "\n",
343 "TestTool\n",
344 "When the TestTool runs messages will be redirected inside the TestTool.\n",
345 "\n",
346 "Debugger\n",
347 "Attempt to activate the debugger and produce the message there, in order to "
348 "always obtain the corresponding stack trace in the debugger.\n",
349 "\n",
350 "Abort\n",
351 "Aborts the application\n",
352 "\n",
353 "\n",
354 "Reroute osl messages - Checkbox\n",
355 "OSL_ASSERT and similar messages can be intercepted by the general DBG GUI\n",
356 "or handled system specific as per normal handling in the sal library.\n",
357 "default is to reroute osl assertions\n",
358 "\n",
359 "\n",
360 "Settings\n",
361 "------------------------------------------\n",
362 "\n",
363 "Where by default the INI and LOG file is read and written the following "
364 "can be set:\n",
365 "\n",
366 "WIN/WNT (WIN.INI, Group SV, Default: dbgsv.ini and dbgsv.log):\n",
367 "INI: dbgsv\n",
368 "LOG: dbgsvlog\n",
369 "\n",
370 "OS2 (OS2.INI, Application SV, Default: dbgsv.ini and dbgsv.log):\n",
371 "INI: DBGSV\n",
372 "LOG: DBGSVLOG\n",
373 "\n",
374 "UNIX (Environment variable, Default: .dbgsv.init and dbgsv.log):\n",
375 "INI: DBGSV_INIT\n",
376 "LOG: DBGSV_LOG\n",
377 "\n",
378 "MAC (Default: dbgsv.ini and dbgsv.log):\n",
379 "INI: not possible\n",
380 "LOG: only debug dialog settings\n",
381 "\n",
382 "The path and file name must always be specified. The name of the log "
383 "file that was entered in the debug dialog has always priority.\n",
384 "\n",
385 "\n",
386 "Example\n",
387 "------------------------------------------\n",
388 "\n",
389 "DBG_NAME( String );\n",
390 "\n",
391 "#ifdef DBG_UTIL\n",
392 "const sal_Char* DbgCheckString( const void* pString )\n",
393 "{\n",
394 "    String* p = (String*)pString;\n",
395 "\n",
396 "    if ( p->mpData->maStr[p->mpData->mnLen] != 0 )\n",
397 "        return \"String damaged: aStr[nLen] != 0\";\n",
398 "\n",
399 "    return NULL;\n",
400 "}\n",
401 "#endif\n",
402 "\n",
403 "String::String()\n",
404 "{\n",
405 "    DBG_CTOR( String, DbgCheckString );\n",
406 "    // ...\n",
407 "}\n",
408 "\n",
409 "String::~String()\n",
410 "{\n",
411 "    DBG_DTOR( String, DbgCheckString );\n",
412 "    //...\n",
413 "}\n",
414 "\n",
415 "char& String::operator [] ( sal_uInt16 nIndex )\n",
416 "{\n",
417 "    DBG_CHKTHIS( String, DbgCheckString );\n",
418 "    DBG_ASSERT( nIndex <= pData->nLen, \"String::[] : nIndex > Len\" );\n",
419 "\n",
420 "    //...\n",
421 "}\n",
422 "\n",
423 "sal_uInt16 String::Search( const String& rStr, sal_uInt16 nIndex ) const\n",
424 "{\n",
425 "    DBG_CHKTHIS( String, DbgCheckString );\n",
426 "    DBG_CHKOBJ( &rStr, String, DbgCheckString );\n",
427 "\n",
428 "    //...\n",
429 "}",
430 "\n",
431 NULL
432 };
433 
434 // =======================================================================
435 
436 namespace
437 {
438     // -------------------------------------------------------------------
439     typedef ::std::map< XubString, DbgChannelId > UserDefinedChannels;
440     UserDefinedChannels& ImplDbgGetUserDefinedChannels()
441     {
442         static UserDefinedChannels s_aChannels;
443         return s_aChannels;
444     }
445 
446     // -------------------------------------------------------------------
447     void ImplAppendUserDefinedChannels( ListBox& rList )
448     {
449         const UserDefinedChannels& rChannels = ImplDbgGetUserDefinedChannels();
450         for ( UserDefinedChannels::const_iterator channel = rChannels.begin();
451               channel != rChannels.end();
452               ++channel
453             )
454         {
455             sal_uInt16 nEntryPos = rList.InsertEntry( channel->first );
456             rList.SetEntryData( nEntryPos, reinterpret_cast< void* >( channel->second ) );
457         }
458     }
459 
460     // -------------------------------------------------------------------
461     void ImplSelectChannel( ListBox& rList, sal_uLong nChannelToSelect, sal_uInt16 nPositionOffset )
462     {
463         if ( nChannelToSelect < DBG_OUT_USER_CHANNEL_0 )
464             rList.SelectEntryPos( (sal_uInt16)( nChannelToSelect - nPositionOffset ) );
465         else
466         {
467             for ( sal_uInt16 pos = 0; pos < rList.GetEntryCount(); ++pos )
468             {
469                 DbgChannelId nChannelId = static_cast< DbgChannelId >( reinterpret_cast<sal_IntPtr>(rList.GetEntryData( pos )) );
470                 if ( nChannelId == nChannelToSelect )
471                 {
472                     rList.SelectEntryPos( pos );
473                     return;
474                 }
475             }
476         }
477     }
478     // -------------------------------------------------------------------
479     DbgChannelId ImplGetChannelId( const ListBox& rList, sal_uInt16 nPositionOffset )
480     {
481         sal_uInt16 nSelectedChannelPos = rList.GetSelectEntryPos();
482         DbgChannelId nSelectedChannel = static_cast< DbgChannelId >( reinterpret_cast<sal_IntPtr>(rList.GetEntryData( nSelectedChannelPos )) );
483         if ( nSelectedChannel == 0)
484             return (DbgChannelId)( nSelectedChannelPos + nPositionOffset );
485         return nSelectedChannel;
486     }
487 }
488 
489 // =======================================================================
490 
491 // -------------
492 // - DbgWindow -
493 // -------------
494 
495 #define DBGWIN_MAXLINES     100
496 
497 class DbgWindow : public WorkWindow
498 {
499 private:
500     ListBox         maLstBox;
501 
502 public:
503                     DbgWindow();
504 
505     virtual sal_Bool    Close();
506     virtual void    Resize();
507     virtual long    PreNotify( NotifyEvent& rNEvt );
508     void            InsertLine( const XubString& rLine );
509     void            Update() { WorkWindow::Update(); maLstBox.Update(); }
510 
511 private:
512     void            GetAssertionEntryRange( sal_uInt16 nInbetweenEntry, sal_uInt16& nFirst, sal_uInt16& nLast );
513 };
514 
515 // -----------------
516 // - DbgInfoDialog -
517 // -----------------
518 
519 class DbgInfoDialog : public ModalDialog
520 {
521 private:
522     ListBox         maListBox;
523     OKButton        maOKButton;
524     sal_Bool            mbHelpText;
525 
526 public:
527                     DbgInfoDialog( Window* pParent, sal_Bool bHelpText = sal_False );
528 
529     void            SetInfoText( const XubString& rStr );
530 };
531 
532 // -------------
533 // - DbgDialog -
534 // -------------
535 
536 class DbgDialog : public ModalDialog
537 {
538 private:
539     CheckBox        maXtorThis;
540     CheckBox        maXtorFunc;
541     CheckBox        maXtorExit;
542     CheckBox        maXtorReport;
543     CheckBox        maXtorTrace;
544     GroupBox        maBox1;
545 
546     CheckBox        maMemInit;
547     CheckBox        maMemOverwrite;
548     CheckBox        maMemOverwriteFree;
549     CheckBox        maMemPtr;
550     CheckBox        maMemReport;
551     CheckBox        maMemTrace;
552     CheckBox        maMemLeakReport;
553     CheckBox        maMemNewDel;
554     CheckBox        maMemXtor;
555     GroupBox        maBox2;
556 
557     CheckBox        maProf;
558     CheckBox        maRes;
559     CheckBox        maDialog;
560     CheckBox        maBoldAppFont;
561     GroupBox        maBox3;
562 
563     Edit            maDebugName;
564     CheckBox        maOverwrite;
565     FixedText       maInclClassText;
566     Edit            maInclClassFilter;
567     FixedText       maExclClassText;
568     Edit            maExclClassFilter;
569     FixedText       maInclText;
570     Edit            maInclFilter;
571     FixedText       maExclText;
572     Edit            maExclFilter;
573     FixedText       maTraceText;
574     ListBox         maTraceBox;
575     FixedText       maWarningText;
576     ListBox         maWarningBox;
577     FixedText       maErrorText;
578     ListBox         maErrorBox;
579     CheckBox        maHookOSLBox;
580     GroupBox        maBox4;
581 
582     OKButton        maOKButton;
583     CancelButton    maCancelButton;
584     PushButton      maInfoButton;
585     HelpButton      maHelpButton;
586     sal_uInt16          mnErrorOff;
587 
588 public:
589                     DbgDialog();
590 
591                     DECL_LINK( ClickHdl, Button* );
592     void            RequestHelp( const HelpEvent& rHEvt );
593 };
594 
595 // =======================================================================
596 
597 static sal_Char aDbgInfoBuf[12288];
598 static sal_Char aDbgOutBuf[DBG_BUF_MAXLEN];
599 
600 // =======================================================================
601 
602 DbgWindow::DbgWindow() :
603     WorkWindow( NULL, WB_STDWORK ),
604     maLstBox( this, WB_AUTOHSCROLL )
605 {
606     DbgData* pData = DbgGetData();
607 
608     maLstBox.Show();
609     maLstBox.SetPosPixel( Point( 0, 0 ) );
610 
611     SetOutputSizePixel( Size( 600, 480 ) );
612     if ( pData->aDbgWinState )
613     {
614         ByteString aState( pData->aDbgWinState );
615         SetWindowState( aState );
616     }
617 
618     SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "StarView Debug Window" ) ) );
619     Show();
620     Update();
621 }
622 
623 // -----------------------------------------------------------------------
624 
625 sal_Bool DbgWindow::Close()
626 {
627     // remember window position
628     ByteString aState( GetWindowState() );
629     DbgData* pData = DbgGetData();
630     size_t nCopy = (sizeof( pData->aDbgWinState ) < size_t(aState.Len() + 1U ))
631     ? sizeof( pData->aDbgWinState ) : size_t(aState.Len() + 1U );
632     strncpy( pData->aDbgWinState, aState.GetBuffer(), nCopy );
633     pData->aDbgWinState[ sizeof( pData->aDbgWinState ) - 1 ] = 0;
634     // and save for next session
635     DbgSaveData( *pData );
636 
637     delete this;
638     ImplGetSVData()->maWinData.mpDbgWin = NULL;
639     return sal_True;
640 }
641 
642 // -----------------------------------------------------------------------
643 
644 void DbgWindow::Resize()
645 {
646     maLstBox.SetSizePixel( GetOutputSizePixel() );
647 }
648 
649 // -----------------------------------------------------------------------
650 
651 void DbgWindow::GetAssertionEntryRange( sal_uInt16 nInbetweenEntry, sal_uInt16& nFirst, sal_uInt16& nLast )
652 {
653     nFirst = nInbetweenEntry;
654     while ( nFirst > 0 )
655     {
656         if ( maLstBox.GetEntryData( nFirst ) != NULL )
657             break;
658         --nFirst;
659     }
660     sal_uInt16 nEntryCount = maLstBox.GetEntryCount();
661     nLast = nInbetweenEntry + 1;
662     while ( nLast < nEntryCount )
663     {
664         if ( maLstBox.GetEntryData( nLast ) != NULL )
665             break;
666         ++nLast;
667     }
668 }
669 
670 // -----------------------------------------------------------------------
671 
672 long DbgWindow::PreNotify( NotifyEvent& rNEvt )
673 {
674     if ( rNEvt.GetType() == EVENT_COMMAND )
675     {
676         if ( maLstBox.IsWindowOrChild( rNEvt.GetWindow() ) )
677         {
678             const CommandEvent& rCommand = *rNEvt.GetCommandEvent();
679             if ( rCommand.GetCommand() == COMMAND_CONTEXTMENU )
680             {
681                 PopupMenu aMenu;
682                 aMenu.InsertItem( 1, String::CreateFromAscii( "copy to clipboard" ) );
683 
684                 Point aPos;
685                 if ( rCommand.IsMouseEvent() )
686                     aPos = rCommand.GetMousePosPixel();
687                 else
688                 {
689                     Rectangle aEntryRect( maLstBox.GetBoundingRectangle( maLstBox.GetSelectEntryPos() ) );
690                     aPos = aEntryRect.Center();
691                 }
692                 sal_uInt16 nSelected = aMenu.Execute( rNEvt.GetWindow(), aPos );
693                 if ( nSelected == 1 )
694                 {
695                     // search all entries which belong to this assertion
696                     sal_uInt16 nAssertionFirst = 0;
697                     sal_uInt16 nAssertionLast = 0;
698                     GetAssertionEntryRange( maLstBox.GetSelectEntryPos(), nAssertionFirst, nAssertionLast );
699 
700                     // build the string to copy to the clipboard
701                     String sAssertion;
702                     String sLineFeed = String::CreateFromAscii( "\n" );
703                     sLineFeed.ConvertLineEnd( GetSystemLineEnd() );
704                     while ( nAssertionFirst < nAssertionLast )
705                     {
706                         sAssertion += maLstBox.GetEntry( nAssertionFirst++ );
707                         sAssertion += sLineFeed;
708                     }
709 
710                     ::vcl::unohelper::TextDataObject::CopyStringTo( sAssertion, GetClipboard() );
711                 }
712             }
713             return 1;   // handled
714         }
715     }
716     return WorkWindow::PreNotify( rNEvt );
717 }
718 
719 // -----------------------------------------------------------------------
720 
721 void DbgWindow::InsertLine( const XubString& rLine )
722 {
723     XubString aStr = rLine;
724     aStr.ConvertLineEnd( LINEEND_LF );
725     xub_StrLen  nPos = aStr.Search( _LF );
726     sal_Bool bFirstEntry = sal_True;
727     while ( nPos != STRING_NOTFOUND )
728     {
729         if ( maLstBox.GetEntryCount() >= DBGWIN_MAXLINES )
730             maLstBox.RemoveEntry( 0 );
731 
732         sal_uInt16 nInsertionPos = maLstBox.InsertEntry( aStr.Copy( 0, nPos ) );
733         if ( bFirstEntry )
734             maLstBox.SetEntryData( nInsertionPos, reinterpret_cast< void* >( 0x00000001 ) );
735         bFirstEntry = sal_False;
736 
737         aStr.Erase( 0, nPos+1 );
738         nPos = aStr.Search( _LF );
739     }
740     if ( maLstBox.GetEntryCount() >= DBGWIN_MAXLINES )
741         maLstBox.RemoveEntry( 0 );
742     sal_uInt16 nInsertionPos = maLstBox.InsertEntry( aStr );
743     if ( bFirstEntry )
744         maLstBox.SetEntryData( nInsertionPos, reinterpret_cast< void* >( 0x00000001 ) );
745     maLstBox.SetTopEntry( DBGWIN_MAXLINES-1 );
746     maLstBox.Update();
747 }
748 
749 // =======================================================================
750 
751 DbgDialog::DbgDialog() :
752     ModalDialog( NULL, WB_STDMODAL | WB_SYSTEMWINDOW ),
753     maXtorThis( this ),
754     maXtorFunc( this ),
755     maXtorExit( this ),
756     maXtorReport( this ),
757     maXtorTrace( this ),
758     maBox1( this ),
759     maMemInit( this ),
760     maMemOverwrite( this ),
761     maMemOverwriteFree( this ),
762     maMemPtr( this ),
763     maMemReport( this ),
764     maMemTrace( this ),
765     maMemLeakReport( this ),
766     maMemNewDel( this ),
767     maMemXtor( this ),
768     maBox2( this ),
769     maProf( this ),
770     maRes( this ),
771     maDialog( this ),
772     maBoldAppFont( this ),
773     maBox3( this ),
774     maDebugName( this ),
775     maOverwrite( this ),
776     maInclClassText( this ),
777     maInclClassFilter( this ),
778     maExclClassText( this ),
779     maExclClassFilter( this ),
780     maInclText( this ),
781     maInclFilter( this ),
782     maExclText( this ),
783     maExclFilter( this ),
784     maTraceText( this ),
785     maTraceBox( this, WB_DROPDOWN ),
786     maWarningText( this ),
787     maWarningBox( this, WB_DROPDOWN ),
788     maErrorText( this ),
789     maErrorBox( this, WB_DROPDOWN ),
790     maHookOSLBox( this ),
791     maBox4( this ),
792     maOKButton( this, WB_DEFBUTTON ),
793     maCancelButton( this ),
794     maInfoButton( this ),
795     maHelpButton( this )
796 {
797     DbgData*    pData = DbgGetData();
798     MapMode     aAppMap( MAP_APPFONT );
799     Size        aButtonSize = LogicToPixel( Size( 60, 12 ), aAppMap );
800 
801     {
802     maXtorThis.Show();
803     maXtorThis.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "T~his" ) ) );
804     if ( pData->nTestFlags & DBG_TEST_XTOR_THIS )
805         maXtorThis.Check( sal_True );
806     maXtorThis.SetPosSizePixel( LogicToPixel( Point( 10, 15 ), aAppMap ),
807                                 aButtonSize );
808     }
809 
810     {
811     maXtorFunc.Show();
812     maXtorFunc.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Function" ) ) );
813     if ( pData->nTestFlags & DBG_TEST_XTOR_FUNC )
814         maXtorFunc.Check( sal_True );
815     maXtorFunc.SetPosSizePixel( LogicToPixel( Point( 75, 15 ), aAppMap ),
816                                 aButtonSize );
817     }
818 
819     {
820     maXtorExit.Show();
821     maXtorExit.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "E~xit" ) ) );
822     if ( pData->nTestFlags & DBG_TEST_XTOR_EXIT )
823         maXtorExit.Check( sal_True );
824     maXtorExit.SetPosSizePixel( LogicToPixel( Point( 140, 15 ), aAppMap ),
825                                 aButtonSize );
826     }
827 
828     {
829     maXtorReport.Show();
830     maXtorReport.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Report" ) ) );
831     if ( pData->nTestFlags & DBG_TEST_XTOR_REPORT )
832         maXtorReport.Check( sal_True );
833     maXtorReport.SetPosSizePixel( LogicToPixel( Point( 205, 15 ), aAppMap ),
834                                   aButtonSize );
835     }
836 
837     {
838     maXtorTrace.Show();
839     maXtorTrace.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Trace" ) ) );
840     if ( pData->nTestFlags & DBG_TEST_XTOR_TRACE )
841         maXtorTrace.Check( sal_True );
842     maXtorTrace.SetPosSizePixel( LogicToPixel( Point( 270, 15 ), aAppMap ),
843                                  aButtonSize );
844     }
845 
846     {
847     maBox1.Show();
848     maBox1.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Object Tests" ) ) );
849     maBox1.SetPosSizePixel( LogicToPixel( Point( 5, 5 ), aAppMap ),
850                             LogicToPixel( Size( 330, 30 ), aAppMap ) );
851     }
852 
853     {
854     maMemInit.Show();
855     maMemInit.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Initialize" ) ) );
856     if ( pData->nTestFlags & DBG_TEST_MEM_INIT )
857         maMemInit.Check( sal_True );
858     maMemInit.SetPosSizePixel( LogicToPixel( Point( 10, 50 ), aAppMap ),
859                                aButtonSize );
860     }
861 
862     {
863     maMemOverwrite.Show();
864     maMemOverwrite.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Overwrite" )) );
865     if ( pData->nTestFlags & DBG_TEST_MEM_OVERWRITE )
866         maMemOverwrite.Check( sal_True );
867     maMemOverwrite.SetPosSizePixel( LogicToPixel( Point( 75, 50 ), aAppMap ),
868                                     aButtonSize );
869     }
870 
871     {
872     maMemOverwriteFree.Show();
873     maMemOverwriteFree.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Free" ) ) );
874     if ( pData->nTestFlags & DBG_TEST_MEM_OVERWRITEFREE )
875         maMemOverwriteFree.Check( sal_True );
876     maMemOverwriteFree.SetPosSizePixel( LogicToPixel( Point( 140, 50 ), aAppMap ),
877                                         aButtonSize );
878     }
879 
880     {
881     maMemPtr.Show();
882     maMemPtr.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Pointer" ) ) );
883     if ( pData->nTestFlags & DBG_TEST_MEM_POINTER )
884         maMemPtr.Check( sal_True );
885     maMemPtr.SetPosSizePixel( LogicToPixel( Point( 205, 50 ), aAppMap ),
886                               aButtonSize );
887     }
888 
889     {
890     maMemReport.Show();
891     maMemReport.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Report" ) ) );
892     if ( pData->nTestFlags & DBG_TEST_MEM_REPORT )
893         maMemReport.Check( sal_True );
894     maMemReport.SetPosSizePixel( LogicToPixel( Point( 270, 50 ), aAppMap ),
895                                  aButtonSize );
896     }
897 
898     {
899     maMemTrace.Show();
900     maMemTrace.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Trace" ) ) );
901     if ( pData->nTestFlags & DBG_TEST_MEM_TRACE )
902         maMemTrace.Check( sal_True );
903     maMemTrace.SetPosSizePixel( LogicToPixel( Point( 10, 65 ), aAppMap ),
904                                 aButtonSize );
905     }
906 
907     {
908     maMemLeakReport.Show();
909     maMemLeakReport.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Leak-Report" ) ) );
910     if ( pData->nTestFlags & DBG_TEST_MEM_LEAKREPORT )
911         maMemLeakReport.Check( sal_True );
912     maMemLeakReport.SetPosSizePixel( LogicToPixel( Point( 75, 65 ), aAppMap ),
913                                      aButtonSize );
914     }
915 
916     {
917     maMemNewDel.Show();
918     maMemNewDel.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~New/Delete" ) ) );
919     if ( pData->nTestFlags & DBG_TEST_MEM_NEWDEL )
920         maMemNewDel.Check( sal_True );
921     maMemNewDel.SetPosSizePixel( LogicToPixel( Point( 140, 65 ), aAppMap ),
922                                  aButtonSize );
923     }
924 
925     {
926     maMemXtor.Show();
927     maMemXtor.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Ob~ject Test" ) ) );
928     if ( pData->nTestFlags & DBG_TEST_MEM_XTOR )
929         maMemXtor.Check( sal_True );
930     maMemXtor.SetPosSizePixel( LogicToPixel( Point( 205, 65 ), aAppMap ),
931                                aButtonSize );
932     }
933 
934     {
935     maBox2.Show();
936     maBox2.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Memory Tests" ) ) );
937     maBox2.SetPosSizePixel( LogicToPixel( Point( 5, 40 ), aAppMap ),
938                             LogicToPixel( Size( 330, 40 ), aAppMap ) );
939     }
940 
941     {
942     maProf.Show();
943     maProf.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Profiling" ) ) );
944     if ( pData->nTestFlags & DBG_TEST_PROFILING )
945         maProf.Check( sal_True );
946     maProf.SetPosSizePixel( LogicToPixel( Point( 10, 95 ), aAppMap ),
947                             aButtonSize );
948     }
949 
950     {
951     maRes.Show();
952     maRes.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Resourcen" ) ) );
953     if ( pData->nTestFlags & DBG_TEST_RESOURCE )
954         maRes.Check( sal_True );
955     maRes.SetPosSizePixel( LogicToPixel( Point( 75, 95 ), aAppMap ),
956                            aButtonSize );
957     }
958 
959     {
960     maDialog.Show();
961     maDialog.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Dialog" ) ) );
962     if ( pData->nTestFlags & DBG_TEST_DIALOG )
963         maDialog.Check( sal_True );
964     maDialog.SetPosSizePixel( LogicToPixel( Point( 140, 95 ), aAppMap ),
965                               aButtonSize );
966     }
967 
968     {
969     maBoldAppFont.Show();
970     maBoldAppFont.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Bold AppFont" ) ) );
971     if ( pData->nTestFlags & DBG_TEST_BOLDAPPFONT )
972         maBoldAppFont.Check( sal_True );
973     maBoldAppFont.SetPosSizePixel( LogicToPixel( Point( 205, 95 ), aAppMap ),
974                                    aButtonSize );
975     maBoldAppFont.SaveValue();
976     }
977 
978     {
979     maBox3.Show();
980     maBox3.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Test Options" ) ) );
981     maBox3.SetPosSizePixel( LogicToPixel( Point( 5, 85 ), aAppMap ),
982                             LogicToPixel( Size( 330, 30 ), aAppMap ) );
983     }
984 
985     {
986     maDebugName.Show();
987     maDebugName.SetText( XubString( pData->aDebugName, RTL_TEXTENCODING_UTF8 ) );
988     maDebugName.SetMaxTextLen( sizeof( pData->aDebugName ) );
989     maDebugName.SetPosSizePixel( LogicToPixel( Point( 10, 130 ), aAppMap ),
990                                  LogicToPixel( Size( 185, 14 ), aAppMap ) );
991     }
992 
993     {
994     maOverwrite.Show();
995     maOverwrite.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Overwrite ~File" ) ) );
996     if ( pData->bOverwrite )
997         maOverwrite.Check( sal_True );
998     maOverwrite.SetPosSizePixel( LogicToPixel( Point( 205, 130 ), aAppMap ),
999                                  aButtonSize );
1000     }
1001 
1002     {
1003     maHookOSLBox.Show();
1004     maHookOSLBox.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Reroute osl debug ~messages" ) ) );
1005     if ( pData->bHookOSLAssert )
1006         maHookOSLBox.Check( sal_True );
1007     maHookOSLBox.SetPosSizePixel( LogicToPixel( Point( 10, 240 ), aAppMap ),
1008                                   LogicToPixel( Size( 100, 12 ), aAppMap ) );
1009     }
1010 
1011     {
1012     maInclClassText.Show();
1013     maInclClassText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Include-ObjectTest-Filter" ) ) );
1014     maInclClassText.SetPosSizePixel( LogicToPixel( Point( 10, 150 ), aAppMap ),
1015                                      LogicToPixel( Size( 95, 9 ), aAppMap ) );
1016     }
1017 
1018     {
1019     maInclClassFilter.Show();
1020     maInclClassFilter.SetText( XubString( pData->aInclClassFilter, RTL_TEXTENCODING_UTF8 ) );
1021     maInclClassFilter.SetMaxTextLen( sizeof( pData->aInclClassFilter ) );
1022     maInclClassFilter.SetPosSizePixel( LogicToPixel( Point( 10, 160 ), aAppMap ),
1023                                        LogicToPixel( Size( 95, 14 ), aAppMap ) );
1024     }
1025 
1026     {
1027     maExclClassText.Show();
1028     maExclClassText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Exclude-ObjectTest-Filter" ) ) );
1029     maExclClassText.SetPosSizePixel( LogicToPixel( Point( 115, 150 ), aAppMap ),
1030                                      LogicToPixel( Size( 95, 9 ), aAppMap ) );
1031     }
1032 
1033     {
1034     maExclClassFilter.Show();
1035     maExclClassFilter.SetText( XubString( pData->aExclClassFilter, RTL_TEXTENCODING_UTF8 ) );
1036     maExclClassFilter.SetMaxTextLen( sizeof( pData->aExclClassFilter ) );
1037     maExclClassFilter.SetPosSizePixel( LogicToPixel( Point( 115, 160 ), aAppMap ),
1038                                        LogicToPixel( Size( 95, 14 ), aAppMap ) );
1039     }
1040 
1041     {
1042     maInclText.Show();
1043     maInclText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Include-Filter" ) ) );
1044     maInclText.SetPosSizePixel( LogicToPixel( Point( 10, 180 ), aAppMap ),
1045                                 LogicToPixel( Size( 95, 9 ), aAppMap ) );
1046     }
1047 
1048     {
1049     maInclFilter.Show();
1050     maInclFilter.SetText( XubString( pData->aInclFilter, RTL_TEXTENCODING_UTF8 ) );
1051     maInclFilter.SetMaxTextLen( sizeof( pData->aInclFilter ) );
1052     maInclFilter.SetPosSizePixel( LogicToPixel( Point( 10, 190 ), aAppMap ),
1053                                   LogicToPixel( Size( 95, 14 ), aAppMap ) );
1054     }
1055 
1056     {
1057     maExclText.Show();
1058     maExclText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Exclude-Filter" ) ) );
1059     maExclText.SetPosSizePixel( LogicToPixel( Point( 115, 180 ), aAppMap ),
1060                                 LogicToPixel( Size( 95, 9 ), aAppMap ) );
1061     }
1062 
1063     {
1064     maExclFilter.Show();
1065     maExclFilter.SetText( XubString( pData->aExclFilter, RTL_TEXTENCODING_UTF8 ) );
1066     maExclFilter.SetMaxTextLen( sizeof( pData->aExclFilter ) );
1067     maExclFilter.SetPosSizePixel( LogicToPixel( Point( 115, 190 ), aAppMap ),
1068                                   LogicToPixel( Size( 95, 14 ), aAppMap ) );
1069     }
1070 
1071     {
1072     maTraceText.Show();
1073     maTraceText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Trace" ) ) );
1074     maTraceText.SetPosSizePixel( LogicToPixel( Point( 10, 210 ), aAppMap ),
1075                                  LogicToPixel( Size( 95, 9 ), aAppMap ) );
1076     }
1077 
1078     {
1079     maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) );
1080     maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) );
1081     maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Window" ) ) );
1082     maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Shell" ) ) );
1083     maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "MessageBox" ) ) );
1084     maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "TestTool" ) ) );
1085     maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debugger" ) ) );
1086     maTraceBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Abort" ) ) );
1087     ImplAppendUserDefinedChannels( maTraceBox );
1088     ImplSelectChannel( maTraceBox, pData->nTraceOut, 0 );
1089     maTraceBox.Show();
1090     maTraceBox.SetPosSizePixel( LogicToPixel( Point( 10, 220 ), aAppMap ),
1091                                 LogicToPixel( Size( 95, 80 ), aAppMap ) );
1092     }
1093 
1094     {
1095     maWarningText.Show();
1096     maWarningText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Warning" ) ) );
1097     maWarningText.SetPosSizePixel( LogicToPixel( Point( 115, 210 ), aAppMap ),
1098                                    LogicToPixel( Size( 95, 9 ), aAppMap ) );
1099     }
1100 
1101     {
1102     maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) );
1103     maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) );
1104     maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Window" ) ) );
1105     maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Shell" ) ) );
1106     maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "MessageBox" ) ) );
1107     maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "TestTool" ) ) );
1108     maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debugger" ) ) );
1109     maWarningBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Abort" ) ) );
1110     ImplAppendUserDefinedChannels( maWarningBox );
1111     ImplSelectChannel( maWarningBox, pData->nWarningOut, 0 );
1112     maWarningBox.Show();
1113     maWarningBox.SetPosSizePixel( LogicToPixel( Point( 115, 220 ), aAppMap ),
1114                                   LogicToPixel( Size( 95, 80 ), aAppMap ) );
1115     }
1116 
1117     {
1118     maErrorText.Show();
1119     maErrorText.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Error" ) ) );
1120     maErrorText.SetPosSizePixel( LogicToPixel( Point( 220, 210 ), aAppMap ),
1121                                  LogicToPixel( Size( 95, 9 ), aAppMap ) );
1122     }
1123 
1124     {
1125     if ( DbgIsAllErrorOut() )
1126     {
1127         maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "None" ) ) );
1128         maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "File" ) ) );
1129         maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Window" ) ) );
1130         maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Shell" ) ) );
1131         mnErrorOff = 0;
1132     }
1133     else
1134         mnErrorOff = 4;
1135     maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "MessageBox" ) ) );
1136     maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "TestTool" ) ) );
1137     maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debugger" ) ) );
1138     maErrorBox.InsertEntry( XubString( RTL_CONSTASCII_USTRINGPARAM( "Abort" ) ) );
1139     ImplAppendUserDefinedChannels( maErrorBox );
1140     ImplSelectChannel( maErrorBox, pData->nErrorOut, mnErrorOff );
1141     maErrorBox.Show();
1142     maErrorBox.SetPosSizePixel( LogicToPixel( Point( 220, 220 ), aAppMap ),
1143                                 LogicToPixel( Size( 95, 80 ), aAppMap ) );
1144     }
1145 
1146     {
1147     maBox4.Show();
1148     maBox4.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Output" ) ) );
1149     maBox4.SetPosSizePixel( LogicToPixel( Point( 5, 120 ), aAppMap ),
1150                             LogicToPixel( Size( 330, 135 ), aAppMap ) );
1151     }
1152 
1153     {
1154     maOKButton.Show();
1155     maOKButton.SetClickHdl( LINK( this, DbgDialog, ClickHdl ) );
1156     maOKButton.SetPosSizePixel( LogicToPixel( Point( 10, 260 ), aAppMap ),
1157                                 LogicToPixel( Size( 50, 15 ), aAppMap ) );
1158     }
1159     {
1160     maCancelButton.Show();
1161     maCancelButton.SetPosSizePixel( LogicToPixel( Point( 70, 260 ), aAppMap ),
1162                                     LogicToPixel( Size( 50, 15 ), aAppMap ) );
1163     }
1164     {
1165     maInfoButton.Show();
1166     maInfoButton.SetClickHdl( LINK( this, DbgDialog, ClickHdl ) );
1167     maInfoButton.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "~Info..." ) ) );
1168     maInfoButton.SetPosSizePixel( LogicToPixel( Point( 130, 260 ), aAppMap ),
1169                                   LogicToPixel( Size( 50, 15 ), aAppMap ) );
1170     }
1171     {
1172     maHelpButton.Show();
1173     maHelpButton.SetPosSizePixel( LogicToPixel( Point( 190, 260 ), aAppMap ),
1174                                   LogicToPixel( Size( 50, 15 ), aAppMap ) );
1175     }
1176 
1177     {
1178     SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "VCL Debug Options" ) ) );
1179     SetOutputSizePixel( LogicToPixel( Size( 340, 280 ), aAppMap ) );
1180     }
1181 }
1182 
1183 // -----------------------------------------------------------------------
1184 
1185 IMPL_LINK( DbgDialog, ClickHdl, Button*, pButton )
1186 {
1187     if ( pButton == &maOKButton )
1188     {
1189         DbgData aData;
1190 
1191         memcpy( &aData, DbgGetData(), sizeof( DbgData ) );
1192         aData.nTestFlags = 0;
1193 
1194         aData.nTraceOut   = ImplGetChannelId( maTraceBox, 0 );
1195         aData.nWarningOut = ImplGetChannelId( maWarningBox, 0 );
1196         aData.nErrorOut   = ImplGetChannelId( maErrorBox, mnErrorOff );
1197 
1198         strncpy( aData.aDebugName, ByteString( maDebugName.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aDebugName ) );
1199         strncpy( aData.aInclClassFilter, ByteString( maInclClassFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aInclClassFilter ) );
1200         strncpy( aData.aExclClassFilter, ByteString( maExclClassFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aExclClassFilter ) );
1201         strncpy( aData.aInclFilter, ByteString( maInclFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aInclFilter ) );
1202         strncpy( aData.aExclFilter, ByteString( maExclFilter.GetText(), RTL_TEXTENCODING_UTF8 ).GetBuffer(), sizeof( aData.aExclFilter ) );
1203         aData.aDebugName[sizeof( aData.aDebugName )-1] = '\0';
1204         aData.aInclClassFilter[sizeof( aData.aInclClassFilter )-1] = '\0';
1205         aData.aExclClassFilter[sizeof( aData.aExclClassFilter )-1] = '\0';
1206         aData.aInclFilter[sizeof( aData.aInclFilter )-1] = '\0';
1207         aData.aExclFilter[sizeof( aData.aExclFilter )-1] = '\0';
1208 
1209         aData.bOverwrite = maOverwrite.IsChecked() ? sal_True : sal_False;
1210         aData.bHookOSLAssert = maHookOSLBox.IsChecked() ? sal_True : sal_False;
1211 
1212         if ( maXtorThis.IsChecked() )
1213             aData.nTestFlags |= DBG_TEST_XTOR_THIS;
1214 
1215         if ( maXtorFunc.IsChecked() )
1216             aData.nTestFlags |= DBG_TEST_XTOR_FUNC;
1217 
1218         if ( maXtorExit.IsChecked() )
1219             aData.nTestFlags |= DBG_TEST_XTOR_EXIT;
1220 
1221         if ( maXtorReport.IsChecked() )
1222             aData.nTestFlags |= DBG_TEST_XTOR_REPORT;
1223 
1224         if ( maXtorTrace.IsChecked() )
1225             aData.nTestFlags |= DBG_TEST_XTOR_TRACE;
1226 
1227         if ( maMemInit.IsChecked() )
1228             aData.nTestFlags |= DBG_TEST_MEM_INIT;
1229 
1230         if ( maMemOverwrite.IsChecked() )
1231             aData.nTestFlags |= DBG_TEST_MEM_OVERWRITE;
1232 
1233         if ( maMemOverwriteFree.IsChecked() )
1234             aData.nTestFlags |= DBG_TEST_MEM_OVERWRITEFREE;
1235 
1236         if ( maMemPtr.IsChecked() )
1237             aData.nTestFlags |= DBG_TEST_MEM_POINTER;
1238 
1239         if ( maMemReport.IsChecked() )
1240             aData.nTestFlags |= DBG_TEST_MEM_REPORT;
1241 
1242         if ( maMemTrace.IsChecked() )
1243             aData.nTestFlags |= DBG_TEST_MEM_TRACE;
1244 
1245         if ( maMemLeakReport.IsChecked() )
1246             aData.nTestFlags |= DBG_TEST_MEM_LEAKREPORT;
1247 
1248         if ( maMemNewDel.IsChecked() )
1249             aData.nTestFlags |= DBG_TEST_MEM_NEWDEL;
1250 
1251         if ( maMemXtor.IsChecked() )
1252             aData.nTestFlags |= DBG_TEST_MEM_XTOR;
1253 
1254         if ( maProf.IsChecked() )
1255             aData.nTestFlags |= DBG_TEST_PROFILING;
1256 
1257         if ( maRes.IsChecked() )
1258             aData.nTestFlags |= DBG_TEST_RESOURCE;
1259 
1260         if ( maDialog.IsChecked() )
1261             aData.nTestFlags |= DBG_TEST_DIALOG;
1262 
1263         if ( maBoldAppFont.IsChecked() )
1264             aData.nTestFlags |= DBG_TEST_BOLDAPPFONT;
1265 
1266         // Daten speichern
1267         DbgSaveData( aData );
1268 
1269         // Umschalten der Laufzeitwerte
1270         DBG_INSTOUTTRACE( aData.nTraceOut );
1271         DBG_INSTOUTWARNING( aData.nWarningOut );
1272         DBG_INSTOUTERROR( aData.nErrorOut );
1273         DbgUpdateOslHook( &aData );
1274 
1275         DbgData* pData = DbgGetData();
1276         #define IMMEDIATE_FLAGS (DBG_TEST_MEM_INIT | DBG_TEST_RESOURCE | DBG_TEST_DIALOG | DBG_TEST_BOLDAPPFONT)
1277         pData->nTestFlags &= ~IMMEDIATE_FLAGS;
1278         pData->nTestFlags |= aData.nTestFlags & IMMEDIATE_FLAGS;
1279         strncpy( pData->aInclClassFilter, aData.aInclClassFilter, sizeof( pData->aInclClassFilter ) );
1280         strncpy( pData->aExclClassFilter, aData.aExclClassFilter, sizeof( pData->aExclClassFilter ) );
1281         strncpy( pData->aInclFilter, aData.aInclFilter, sizeof( pData->aInclFilter ) );
1282         strncpy( pData->aExclFilter, aData.aExclFilter, sizeof( pData->aExclFilter ) );
1283         if ( maBoldAppFont.GetSavedValue() != maBoldAppFont.IsChecked() )
1284         {
1285             AllSettings aSettings = Application::GetSettings();
1286             StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1287             Font aFont = aStyleSettings.GetAppFont();
1288             if ( maBoldAppFont.IsChecked() )
1289                 aFont.SetWeight( WEIGHT_BOLD );
1290             else
1291                 aFont.SetWeight( WEIGHT_NORMAL );
1292             aStyleSettings.SetAppFont( aFont );
1293             aSettings.SetStyleSettings( aStyleSettings );
1294             Application::SetSettings( aSettings );
1295         }
1296         if( (aData.nTestFlags & ~IMMEDIATE_FLAGS) != (pData->nTestFlags & ~IMMEDIATE_FLAGS) )
1297         {
1298             InfoBox aBox( this, String( RTL_CONSTASCII_USTRINGPARAM(
1299                 "Some of the changed settings will only be active after "
1300                 "restarting the process"
1301                 ) ) );
1302             aBox.Execute();
1303         }
1304         EndDialog( sal_True );
1305     }
1306     else if ( pButton == &maInfoButton )
1307     {
1308         DbgInfoDialog aInfoDialog( this );
1309         aDbgInfoBuf[0] = '\0';
1310         DbgMemInfo( aDbgInfoBuf );
1311         DbgXtorInfo( aDbgInfoBuf );
1312         XubString aInfoText( aDbgInfoBuf, RTL_TEXTENCODING_UTF8 );
1313         aInfoDialog.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debug InfoReport" ) ) );
1314         aInfoDialog.SetInfoText( aInfoText );
1315         aInfoDialog.Execute();
1316     }
1317 
1318     return 0;
1319 }
1320 
1321 // -----------------------------------------------------------------------
1322 
1323 void DbgDialog::RequestHelp( const HelpEvent& rHEvt )
1324 {
1325     if ( rHEvt.GetMode() & HELPMODE_CONTEXT )
1326     {
1327         DbgInfoDialog aInfoDialog( this, sal_True );
1328         XubString aHelpText;
1329         const sal_Char** pHelpStrs = pDbgHelpText;
1330         while ( *pHelpStrs )
1331         {
1332             aHelpText.AppendAscii( *pHelpStrs );
1333             pHelpStrs++;
1334         }
1335         aInfoDialog.SetText( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debug Hilfe" ) ) );
1336         aInfoDialog.SetInfoText( aHelpText );
1337         aInfoDialog.Execute();
1338     }
1339 }
1340 
1341 // =======================================================================
1342 
1343 DbgInfoDialog::DbgInfoDialog( Window* pParent, sal_Bool bHelpText ) :
1344     ModalDialog( pParent, WB_STDMODAL ),
1345     maListBox( this, WB_BORDER | WB_AUTOHSCROLL ),
1346     maOKButton( this, WB_DEFBUTTON )
1347 {
1348     mbHelpText = bHelpText;
1349 
1350     if ( !bHelpText )
1351     {
1352         Font aFont = GetDefaultFont( DEFAULTFONT_FIXED, LANGUAGE_ENGLISH_US, 0 );
1353         aFont.SetHeight( 8 );
1354         aFont.SetPitch( PITCH_FIXED );
1355         maListBox.SetControlFont( aFont );
1356     }
1357     maListBox.SetPosSizePixel( Point( 5, 5 ), Size( 630, 380 ) );
1358     maListBox.Show();
1359 
1360     maOKButton.SetPosSizePixel( Point( 290, 390 ), Size( 60, 25 ) );
1361     maOKButton.Show();
1362 
1363     SetOutputSizePixel( Size( 640, 420 ) );
1364 }
1365 
1366 // -----------------------------------------------------------------------
1367 
1368 void DbgInfoDialog::SetInfoText( const XubString& rStr )
1369 {
1370     maListBox.SetUpdateMode( sal_False );
1371     maListBox.Clear();
1372     XubString aStr = rStr;
1373     aStr.ConvertLineEnd( LINEEND_LF );
1374     sal_uInt16 nStrIndex = 0;
1375     sal_uInt16 nFoundIndex;
1376     do
1377     {
1378         nFoundIndex = aStr.Search( _LF, nStrIndex );
1379         XubString aTextParagraph = aStr.Copy( nStrIndex, nFoundIndex-nStrIndex );
1380         if ( mbHelpText )
1381         {
1382             long    nMaxWidth = maListBox.GetOutputSizePixel().Width()-30;
1383             sal_uInt16  nLastIndex = 0;
1384             sal_uInt16  nIndex = aTextParagraph.Search( ' ' );
1385             while ( nIndex != STRING_NOTFOUND )
1386             {
1387                 if ( maListBox.GetTextWidth( aTextParagraph, 0, nIndex ) > nMaxWidth )
1388                 {
1389                     if ( !nLastIndex )
1390                         nLastIndex = nIndex+1;
1391                     XubString aTempStr = aTextParagraph.Copy( 0, nLastIndex );
1392                     aTextParagraph.Erase( 0, nLastIndex );
1393                     maListBox.InsertEntry( aTempStr );
1394                     nLastIndex = 0;
1395                 }
1396                 else
1397                     nLastIndex = nIndex+1;
1398                 nIndex = aTextParagraph.Search( ' ', nLastIndex );
1399             }
1400 
1401             if ( maListBox.GetTextWidth( aTextParagraph, 0, nIndex ) > nMaxWidth )
1402             {
1403                 if ( !nLastIndex )
1404                     nLastIndex = nIndex+1;
1405                 XubString aTempStr = aTextParagraph.Copy( 0, nLastIndex );
1406                 aTextParagraph.Erase( 0, nLastIndex );
1407                 maListBox.InsertEntry( aTempStr );
1408             }
1409         }
1410         maListBox.InsertEntry( aTextParagraph );
1411         nStrIndex = nFoundIndex+1;
1412     }
1413     while ( nFoundIndex != STRING_NOTFOUND );
1414     maListBox.SetUpdateMode( sal_True );
1415 }
1416 
1417 // =======================================================================
1418 
1419 void DbgDialogTest( Window* pWindow )
1420 {
1421     sal_Bool        aAccelBuf[65536];
1422     sal_uInt16      nChildCount = pWindow->GetChildCount();
1423     Window*     pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
1424     Window*     pChild;
1425     Point       aTabPos;
1426 
1427     if ( !pGetChild )
1428         return;
1429 
1430     Rectangle*  pRectAry = (Rectangle*)new long[(sizeof(Rectangle)*nChildCount)/sizeof(long)];
1431     memset( aAccelBuf, 0, sizeof( aAccelBuf ) );
1432     memset( pRectAry, 0, sizeof(Rectangle)*nChildCount );
1433 
1434     if ( pWindow->IsDialog() )
1435     {
1436         sal_Bool    bOKCancelButton = sal_False;
1437         sal_Bool    bDefPushButton = sal_False;
1438         sal_Bool    bButton = sal_False;
1439         pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
1440         while ( pGetChild )
1441         {
1442             pChild = pGetChild->ImplGetWindow();
1443 
1444             if ( pChild->ImplIsPushButton() )
1445             {
1446                 bButton = sal_True;
1447                 if ( (pChild->GetType() == WINDOW_OKBUTTON) || (pChild->GetType() == WINDOW_CANCELBUTTON) )
1448                     bOKCancelButton = sal_True;
1449                 if ( pChild->GetStyle() & WB_DEFBUTTON )
1450                     bDefPushButton = sal_True;
1451             }
1452 
1453             pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
1454         }
1455 
1456         if ( bButton )
1457         {
1458             if ( !bOKCancelButton )
1459                 DbgError( "Dialogs should have a OK- or CancelButton" );
1460             if ( !bDefPushButton )
1461                 DbgError( "Dialogs should have a Button with WB_DEFBUTTON" );
1462         }
1463     }
1464 
1465     sal_uInt16 i = 0;
1466     pGetChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
1467     while ( pGetChild )
1468     {
1469         pChild = pGetChild->ImplGetWindow();
1470 
1471         if ( (pChild->GetType() != WINDOW_TABCONTROL) &&
1472              (pChild->GetType() != WINDOW_TABPAGE) &&
1473              (pChild->GetType() != WINDOW_GROUPBOX) )
1474         {
1475             XubString       aText = pChild->GetText();
1476             XubString       aErrorText = aText;
1477             sal_uInt16          nAccelPos = STRING_NOTFOUND;
1478             xub_Unicode     cAccel = 0;
1479             if ( aErrorText.Len() > 128 )
1480             {
1481                 aErrorText.Erase( 128 );
1482                 aErrorText.AppendAscii( "..." );
1483             }
1484             if ( aText.Len() && (aText.Len() < 1024) )
1485             {
1486                 nAccelPos = aText.Search( '~' );
1487                 if ( nAccelPos != STRING_NOTFOUND )
1488                 {
1489                     const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLocale();
1490                     uno::Reference < i18n::XCharacterClassification > xCharClass = vcl::unohelper::CreateCharacterClassification();
1491                     XubString aUpperText = xCharClass->toUpper( aText, 0, aText.Len(), rLocale );
1492                     cAccel = aUpperText.GetChar( nAccelPos+1 );
1493                     if ( pChild->IsVisible() )
1494                     {
1495                         if ( aAccelBuf[cAccel] )
1496                             DbgOutTypef( DBG_OUT_ERROR, "Double mnemonic char: %c", cAccel );
1497                         else
1498                             aAccelBuf[cAccel] = sal_True;
1499                     }
1500                 }
1501             }
1502 
1503             if ( (pChild->GetType() == WINDOW_RADIOBUTTON) ||
1504                  (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) ||
1505                  (pChild->GetType() == WINDOW_CHECKBOX) ||
1506                  (pChild->GetType() == WINDOW_TRISTATEBOX) ||
1507                  (pChild->GetType() == WINDOW_PUSHBUTTON) )
1508             {
1509                 if ( aText.Len() && !aText.EqualsAscii( "..." ) )
1510                 {
1511                     const char* pClass;
1512                     if ( pChild->GetType() == WINDOW_RADIOBUTTON )
1513                         pClass = "RadioButton";
1514                     else if ( pChild->GetType() == WINDOW_IMAGERADIOBUTTON )
1515                         pClass = "ImageRadioButton";
1516                     else if ( pChild->GetType() == WINDOW_CHECKBOX )
1517                         pClass = "CheckBox";
1518                     else if ( pChild->GetType() == WINDOW_TRISTATEBOX )
1519                         pClass = "TriStateBox";
1520                     else if ( pChild->GetType() == WINDOW_PUSHBUTTON )
1521                         pClass = "PushButton";
1522                     else
1523                         pClass = "Dontknow";
1524 					if( !cAccel )
1525 						DbgOutTypef( DBG_OUT_ERROR,
1526                                  "%s should have a mnemonic char (~): %s",
1527                                  pClass,
1528                                  ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1529 
1530 					// check text width
1531 					int aWidth=0;
1532 					switch( pChild->GetType() )
1533 					{
1534 						case WINDOW_RADIOBUTTON:
1535 						case WINDOW_IMAGERADIOBUTTON:
1536 							aWidth = ((RadioButton*)pChild)->CalcMinimumSize(0).Width();
1537 							break;
1538 						case WINDOW_CHECKBOX:
1539 						case WINDOW_TRISTATEBOX:
1540 							aWidth = ((CheckBox*)pChild)->CalcMinimumSize(0).Width();
1541 							break;
1542 						case WINDOW_PUSHBUTTON:
1543 							aWidth = ((PushButton*)pChild)->CalcMinimumSize(0).Width();
1544 							break;
1545 						default: break;
1546 					}
1547 					if( pChild->IsVisible() && pChild->GetSizePixel().Width() < aWidth )
1548 						DbgOutTypef( DBG_OUT_ERROR,
1549                                  "%s exceeds window width: %s",
1550                                  pClass,
1551                                  ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1552 				}
1553             }
1554 
1555             if ( pChild->GetType() == WINDOW_FIXEDLINE )
1556 			{
1557 				if ( pChild->GetSizePixel().Width() < pChild->GetTextWidth( aText ) )
1558 					DbgOutTypef( DBG_OUT_ERROR,
1559 								 "FixedLine exceeds window width: %s",
1560 								 ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1561 			}
1562 
1563             if ( pChild->GetType() == WINDOW_FIXEDTEXT )
1564             {
1565                 if ( (pChild->GetSizePixel().Height() >= pChild->GetTextHeight()*2) &&
1566                      !(pChild->GetStyle() & WB_WORDBREAK) )
1567                 {
1568                     DbgOutTypef( DBG_OUT_ERROR,
1569                                  "FixedText greater than one line, but WordBreak is not set: %s",
1570                                  ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1571                 }
1572 
1573                 if ( pChild->IsVisible() )
1574 				{
1575 					int aWidth=0;
1576 					if( nAccelPos != STRING_NOTFOUND )
1577 					{
1578 						aWidth = pChild->GetTextWidth( aText, 0, nAccelPos ) +
1579 								 pChild->GetTextWidth( aText, nAccelPos+1, aText.Len() - nAccelPos - 1);
1580 					}
1581 					else
1582 						aWidth = pChild->GetTextWidth( aText );
1583 
1584 					if ( pChild->GetSizePixel().Width() < aWidth && !(pChild->GetStyle() & WB_WORDBREAK) )
1585 						{
1586 							DbgOutTypef( DBG_OUT_ERROR,
1587 										 "FixedText exceeds window width: %s",
1588 										 ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1589 						}
1590 				}
1591 
1592                 if ( (i+1 < nChildCount) && aText.Len() )
1593                 {
1594                     Window* pTempChild = pGetChild->GetWindow( WINDOW_NEXT )->ImplGetWindow();
1595                     if ( (pTempChild->GetType() == WINDOW_EDIT) ||
1596                          (pTempChild->GetType() == WINDOW_MULTILINEEDIT) ||
1597                          (pTempChild->GetType() == WINDOW_SPINFIELD) ||
1598                          (pTempChild->GetType() == WINDOW_PATTERNFIELD) ||
1599                          (pTempChild->GetType() == WINDOW_NUMERICFIELD) ||
1600                          (pTempChild->GetType() == WINDOW_METRICFIELD) ||
1601                          (pTempChild->GetType() == WINDOW_CURRENCYFIELD) ||
1602                          (pTempChild->GetType() == WINDOW_DATEFIELD) ||
1603                          (pTempChild->GetType() == WINDOW_TIMEFIELD) ||
1604                          (pTempChild->GetType() == WINDOW_LISTBOX) ||
1605                          (pTempChild->GetType() == WINDOW_MULTILISTBOX) ||
1606                          (pTempChild->GetType() == WINDOW_COMBOBOX) ||
1607                          (pTempChild->GetType() == WINDOW_PATTERNBOX) ||
1608                          (pTempChild->GetType() == WINDOW_NUMERICBOX) ||
1609                          (pTempChild->GetType() == WINDOW_METRICBOX) ||
1610                          (pTempChild->GetType() == WINDOW_CURRENCYBOX) ||
1611                          (pTempChild->GetType() == WINDOW_DATEBOX) ||
1612                          (pTempChild->GetType() == WINDOW_TIMEBOX) )
1613                     {
1614                         if ( !cAccel )
1615                         {
1616                             DbgOutTypef( DBG_OUT_ERROR,
1617                                          "Labels befor Fields (Edit,ListBox,...) should have a mnemonic char (~): %s",
1618                                          ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1619                         }
1620                         if ( !pTempChild->IsEnabled() && pChild->IsEnabled() )
1621                         {
1622                             DbgOutTypef( DBG_OUT_ERROR,
1623                                          "Labels befor Fields (Edit,ListBox,...) should be disabled, when the field is disabled: %s",
1624                                          ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1625                         }
1626                     }
1627                 }
1628             }
1629 
1630             if ( pChild->GetType() == WINDOW_MULTILINEEDIT )
1631             {
1632                 if  (   ( 0 == ( pChild->GetStyle() & WB_IGNORETAB ) )
1633                     &&  ( 0 == ( pChild->GetStyle() & WB_READONLY ) )
1634                     )
1635                 {
1636                     DbgError( "editable MultiLineEdits in Dialogs should have the Style WB_IGNORETAB" );
1637                 }
1638             }
1639 
1640             if ( (pChild->GetType() == WINDOW_RADIOBUTTON) ||
1641                  (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) ||
1642                  (pChild->GetType() == WINDOW_CHECKBOX) ||
1643                  (pChild->GetType() == WINDOW_TRISTATEBOX) ||
1644                  (pChild->GetType() == WINDOW_FIXEDTEXT) )
1645             {
1646                 pChild->SetBackground( Wallpaper( Color( COL_LIGHTGREEN ) ) );
1647             }
1648 
1649             if ( pChild->IsVisible() )
1650             {
1651                 sal_Bool bMaxWarning = sal_False;
1652                 if ( pChild->GetType() == WINDOW_NUMERICFIELD )
1653                 {
1654                     NumericField* pField = (NumericField*)pChild;
1655                     if ( pField->GetMax() == LONG_MAX )
1656                         bMaxWarning = sal_True;
1657                 }
1658                 else if ( pChild->GetType() == WINDOW_METRICFIELD )
1659                 {
1660                     MetricField* pField = (MetricField*)pChild;
1661                     if ( pField->GetMax() == LONG_MAX )
1662                         bMaxWarning = sal_True;
1663                 }
1664                 else if ( pChild->GetType() == WINDOW_CURRENCYFIELD )
1665                 {
1666                     CurrencyField* pField = (CurrencyField*)pChild;
1667                     if ( pField->GetMax() == LONG_MAX )
1668                         bMaxWarning = sal_True;
1669                 }
1670                 else if ( pChild->GetType() == WINDOW_TIMEFIELD )
1671                 {
1672                     TimeField* pField = (TimeField*)pChild;
1673                     if ( pField->GetMax() == Time( 23, 59, 59, 99 ) )
1674                         bMaxWarning = sal_True;
1675                 }
1676                 else if ( pChild->GetType() == WINDOW_DATEFIELD )
1677                 {
1678                     DateField* pField = (DateField*)pChild;
1679                     if ( pField->GetMax() == Date( 31, 12, 9999 ) )
1680                         bMaxWarning = sal_True;
1681                 }
1682                 else if ( pChild->GetType() == WINDOW_NUMERICBOX )
1683                 {
1684                     NumericBox* pBox = (NumericBox*)pChild;
1685                     if ( pBox->GetMax() == LONG_MAX )
1686                         bMaxWarning = sal_True;
1687                 }
1688                 else if ( pChild->GetType() == WINDOW_METRICBOX )
1689                 {
1690                     MetricBox* pBox = (MetricBox*)pChild;
1691                     if ( pBox->GetMax() == LONG_MAX )
1692                         bMaxWarning = sal_True;
1693                 }
1694                 else if ( pChild->GetType() == WINDOW_CURRENCYBOX )
1695                 {
1696                     CurrencyBox* pBox = (CurrencyBox*)pChild;
1697                     if ( pBox->GetMax() == LONG_MAX )
1698                         bMaxWarning = sal_True;
1699                 }
1700                 else if ( pChild->GetType() == WINDOW_TIMEBOX )
1701                 {
1702                     TimeBox* pBox = (TimeBox*)pChild;
1703                     if ( pBox->GetMax() == Time( 23, 59, 59, 99 ) )
1704                         bMaxWarning = sal_True;
1705                 }
1706                 else if ( pChild->GetType() == WINDOW_DATEBOX )
1707                 {
1708                     DateBox* pBox = (DateBox*)pChild;
1709                     if ( pBox->GetMax() == Date( 31, 12, 9999 ) )
1710                         bMaxWarning = sal_True;
1711                 }
1712                 if ( bMaxWarning )
1713                 {
1714                     DbgOutTypef( DBG_OUT_ERROR,
1715                                  "No Max-Value is set: %s",
1716                                  ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1717                 }
1718 
1719                 if ( (pChild->GetType() == WINDOW_RADIOBUTTON) ||
1720                      (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) ||
1721                      (pChild->GetType() == WINDOW_CHECKBOX) ||
1722                      (pChild->GetType() == WINDOW_TRISTATEBOX) ||
1723                      (pChild->GetType() == WINDOW_PUSHBUTTON) ||
1724                      (pChild->GetType() == WINDOW_OKBUTTON) ||
1725                      (pChild->GetType() == WINDOW_CANCELBUTTON) ||
1726                      (pChild->GetType() == WINDOW_HELPBUTTON) ||
1727                      (pChild->GetType() == WINDOW_IMAGEBUTTON) ||
1728                      (pChild->GetType() == WINDOW_FIXEDTEXT) ||
1729                      (pChild->GetType() == WINDOW_EDIT) ||
1730                      (pChild->GetType() == WINDOW_MULTILINEEDIT) ||
1731                      (pChild->GetType() == WINDOW_SPINFIELD) ||
1732                      (pChild->GetType() == WINDOW_PATTERNFIELD) ||
1733                      (pChild->GetType() == WINDOW_NUMERICFIELD) ||
1734                      (pChild->GetType() == WINDOW_METRICFIELD) ||
1735                      (pChild->GetType() == WINDOW_CURRENCYFIELD) ||
1736                      (pChild->GetType() == WINDOW_DATEFIELD) ||
1737                      (pChild->GetType() == WINDOW_TIMEFIELD) ||
1738                      (pChild->GetType() == WINDOW_LISTBOX) ||
1739                      (pChild->GetType() == WINDOW_MULTILISTBOX) ||
1740                      (pChild->GetType() == WINDOW_COMBOBOX) ||
1741                      (pChild->GetType() == WINDOW_PATTERNBOX) ||
1742                      (pChild->GetType() == WINDOW_NUMERICBOX) ||
1743                      (pChild->GetType() == WINDOW_METRICBOX) ||
1744                      (pChild->GetType() == WINDOW_CURRENCYBOX) ||
1745                      (pChild->GetType() == WINDOW_DATEBOX) ||
1746                      (pChild->GetType() == WINDOW_TIMEBOX) )
1747                 {
1748                     Point       aNewPos = pChild->GetPosPixel();
1749                     Rectangle   aChildRect( aNewPos, pChild->GetSizePixel() );
1750 
1751                     if ( cAccel || (pChild->GetStyle() & WB_TABSTOP) ||
1752                          (pChild->GetType() == WINDOW_RADIOBUTTON) ||
1753                          (pChild->GetType() == WINDOW_IMAGERADIOBUTTON) )
1754                     {
1755                         if ( (aNewPos.X() <= aTabPos.X()) && (aNewPos.Y() <= aTabPos.Y()) )
1756                         {
1757                             DbgOutTypef( DBG_OUT_ERROR,
1758                                          "Possible wrong childorder for dialogcontrol: %s",
1759                                          ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1760                         }
1761                         aTabPos = aNewPos;
1762                     }
1763 
1764                     for ( sal_uInt16 j = 0; j < i; j++ )
1765                     {
1766                         if ( ((pRectAry[j].Right() != 0) || (pRectAry[j].Bottom() != 0)) &&
1767                              aChildRect.IsOver( pRectAry[j] ) )
1768                         {
1769                             DbgOutTypef( DBG_OUT_ERROR,
1770                                          "Window overlaps with sibling window: %s",
1771                                          ByteString( aErrorText, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
1772                         }
1773                     }
1774                     pRectAry[i] = aChildRect;
1775                 }
1776             }
1777         }
1778 
1779         pGetChild = pGetChild->GetWindow( WINDOW_NEXT );
1780         i++;
1781     }
1782 
1783     delete [] pRectAry;
1784 }
1785 
1786 // =======================================================================
1787 #ifndef WNT
1788 #define USE_VCL_MSGBOX
1789 #define COPY_BUTTON_ID 25
1790 
1791 class DbgMessageBox : public ErrorBox
1792 {
1793     String m_aMessage;
1794     public:
1795     DbgMessageBox( const String& rMessage ) :
1796        ErrorBox( NULL, WB_YES_NO_CANCEL | WB_DEF_NO, rMessage ),
1797        m_aMessage( rMessage )
1798     {
1799         SetText( String( RTL_CONSTASCII_USTRINGPARAM("Debug Output") ) );
1800         AddButton( String( RTL_CONSTASCII_USTRINGPARAM( "Copy" ) ), COPY_BUTTON_ID, 0 );
1801     }
1802 
1803     virtual void Click()
1804     {
1805         if( GetCurButtonId() == COPY_BUTTON_ID )
1806             vcl::unohelper::TextDataObject::CopyStringTo( m_aMessage, GetClipboard() );
1807         else
1808             ErrorBox::Click();
1809     }
1810 };
1811 
1812 #endif
1813 
1814 class SolarMessageBoxExecutor : public ::vcl::SolarThreadExecutor
1815 {
1816 private:
1817     String  m_sDebugMessage;
1818 
1819 public:
1820     SolarMessageBoxExecutor( const String& _rDebugMessage )
1821         :m_sDebugMessage( _rDebugMessage )
1822     {
1823     }
1824 
1825 protected:
1826     virtual long doIt();
1827 };
1828 
1829 long SolarMessageBoxExecutor::doIt()
1830 {
1831     long nResult = RET_NO;
1832 
1833     // Tracking beenden und Mouse freigeben, damit die Boxen nicht haengen
1834     ImplSVData* pSVData = ImplGetSVData();
1835     if ( pSVData->maWinData.mpTrackWin )
1836         pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
1837     if ( pSVData->maWinData.mpCaptureWin )
1838         pSVData->maWinData.mpCaptureWin->ReleaseMouse();
1839 
1840 #if ! defined USE_VCL_MSGBOX
1841 #ifdef WNT
1842     sal_Bool bOldCallTimer = pSVData->mbNoCallTimer;
1843     pSVData->mbNoCallTimer = sal_True;
1844     MessageBeep( MB_ICONHAND );
1845     nResult = MessageBoxW( 0, (LPWSTR)m_sDebugMessage.GetBuffer(), L"Debug Output",
1846                                      MB_TASKMODAL | MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_ICONSTOP );
1847     pSVData->mbNoCallTimer = bOldCallTimer;
1848     switch ( nResult )
1849     {
1850         case IDYES:
1851             nResult = RET_YES;
1852             break;
1853         case IDNO:
1854             nResult = RET_NO;
1855             break;
1856         case IDCANCEL:
1857             nResult = RET_CANCEL;
1858             break;
1859     }
1860 #endif // WNT
1861 #else
1862     sal_uInt16 nOldMode = Application::GetSystemWindowMode();
1863     Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
1864     DbgMessageBox aBox( m_sDebugMessage );
1865     Application::SetSystemWindowMode( nOldMode );
1866     nResult = aBox.Execute();
1867 #endif
1868 
1869     return nResult;
1870 }
1871 
1872 void DbgPrintMsgBox( const char* pLine )
1873 {
1874     // are modal message boxes prohibited at the moment?
1875     if ( Application::IsDialogCancelEnabled() )
1876     {
1877 #if defined( WNT )
1878         // TODO: Shouldn't this be a IsDebuggerPresent()?
1879         if ( GetSystemMetrics( SM_DEBUG ) )
1880         {
1881             MessageBeep( MB_ICONHAND );
1882             strcpy( aDbgOutBuf, pLine );
1883             strcat( aDbgOutBuf, "\r\n" );
1884             OutputDebugString( aDbgOutBuf );
1885             return;
1886         }
1887 #endif
1888 
1889         Sound::Beep( SOUND_ERROR );
1890 #ifdef UNX
1891         fprintf( stderr, "%s\n", pLine );
1892         return;
1893 #else
1894         DbgPrintFile( pLine );
1895         return;
1896 #endif
1897     }
1898 
1899     strcpy( aDbgOutBuf, pLine );
1900     strcat( aDbgOutBuf, "\nAbort ? (Yes=abort / No=ignore / Cancel=core dump)" );
1901 
1902     SolarMessageBoxExecutor aMessageBox( String( aDbgOutBuf, RTL_TEXTENCODING_UTF8 ) );
1903     TimeValue aTimeout; aTimeout.Seconds = 2; aTimeout.Nanosec = 0;
1904     long nResult = aMessageBox.execute( aTimeout );
1905 
1906     if ( aMessageBox.didTimeout() )
1907         DbgPrintShell( pLine );
1908     else if ( nResult == RET_YES )
1909         GetpApp()->Abort( XubString( RTL_CONSTASCII_USTRINGPARAM( "Debug-Utilities-Error" ) ) );
1910     else if ( nResult == RET_CANCEL )
1911         DbgCoreDump();
1912 }
1913 
1914 // -----------------------------------------------------------------------
1915 
1916 class SolarWindowPrinter : public ::vcl::SolarThreadExecutor
1917 {
1918 private:
1919     String  m_sDebugMessage;
1920 
1921 public:
1922     SolarWindowPrinter( const String& _rDebugMessage )
1923         :m_sDebugMessage( _rDebugMessage )
1924     {
1925     }
1926 
1927 protected:
1928     virtual long doIt();
1929 };
1930 
1931 long SolarWindowPrinter::doIt()
1932 {
1933     DbgWindow* pDbgWindow = ImplGetSVData()->maWinData.mpDbgWin;
1934     if ( !pDbgWindow )
1935     {
1936         pDbgWindow = new DbgWindow;
1937         ImplGetSVData()->maWinData.mpDbgWin = pDbgWindow;
1938     }
1939     pDbgWindow->InsertLine( m_sDebugMessage );
1940 
1941     return 0L;
1942 }
1943 
1944 // -----------------------------------------------------------------------
1945 
1946 void DbgPrintWindow( const char* pLine )
1947 {
1948     static sal_Bool bIn = sal_False;
1949 
1950     // keine rekursiven Traces
1951     if ( bIn )
1952         return;
1953     bIn = sal_True;
1954 
1955     SolarWindowPrinter aPrinter( String( pLine, RTL_TEXTENCODING_UTF8 ) );
1956     TimeValue aTimeout; aTimeout.Seconds = 2; aTimeout.Nanosec = 0;
1957     aPrinter.execute( aTimeout );
1958 
1959     if ( aPrinter.didTimeout() )
1960         DbgPrintShell( pLine );
1961 
1962     bIn = sal_False;
1963 }
1964 
1965 // -----------------------------------------------------------------------
1966 
1967 void DbgAbort( char const * i_message )
1968 {
1969     ::rtl::OUString const message( i_message, strlen( i_message ), osl_getThreadTextEncoding() );
1970     Application::Abort( message );
1971 }
1972 
1973 // =======================================================================
1974 
1975 void ImplDbgTestSolarMutex()
1976 {
1977     bool bCheck = ImplGetSVData()->mpDefInst->CheckYieldMutex();
1978     OSL_ENSURE( bCheck, "SolarMutex not locked" );
1979 }
1980 
1981 // =======================================================================
1982 
1983 void DbgGUIInit()
1984 {
1985     DbgSetPrintMsgBox( DbgPrintMsgBox );
1986     DbgSetPrintWindow( DbgPrintWindow );
1987     DbgSetTestSolarMutex( ImplDbgTestSolarMutex );
1988     DbgSetAbort( DbgAbort );
1989 }
1990 
1991 // -----------------------------------------------------------------------
1992 
1993 void DbgGUIDeInit()
1994 {
1995     DbgSetPrintMsgBox( NULL );
1996     DbgSetPrintWindow( NULL );
1997     DbgSetTestSolarMutex( NULL );
1998     DbgSetAbort( NULL );
1999 
2000     DbgWindow* pDbgWindow = ImplGetSVData()->maWinData.mpDbgWin;
2001     if ( pDbgWindow )
2002         delete pDbgWindow;
2003 }
2004 
2005 // -----------------------------------------------------------------------
2006 
2007 void DbgGUIStart()
2008 {
2009     DbgData* pData = DbgGetData();
2010 
2011     if ( pData )
2012     {
2013         DbgDialog* pDialog = new DbgDialog;
2014         // Fuer den Debug-Dialog schalten wir Dialogtests aus
2015         sal_uLong nOldFlags = pData->nTestFlags;
2016         pData->nTestFlags &= ~DBG_TEST_DIALOG;
2017         if ( !pDialog->Execute() )
2018             pData->nTestFlags |= (nOldFlags & DBG_TEST_DIALOG);
2019         delete pDialog;
2020     }
2021     else
2022     {
2023         ErrorBox( 0, WB_OK,
2024                   XubString( RTL_CONSTASCII_USTRINGPARAM( "TOOLS Library has no Debug-Routines" ) ) ).Execute();
2025     }
2026 }
2027 
2028 // -----------------------------------------------------------------------
2029 
2030 sal_uInt16 DbgRegisterNamedUserChannel( const XubString& _rChannelUIName, DbgPrintLine pProc )
2031 {
2032     DbgChannelId nChannelId = DbgRegisterUserChannel( pProc );
2033     UserDefinedChannels& rChannels = ImplDbgGetUserDefinedChannels();
2034     rChannels[ _rChannelUIName ] = nChannelId;
2035     return nChannelId;
2036 }
2037 
2038 #endif // DBG_UTIL
2039