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