2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
14 #include <afsconfig.h>
15 #include <afs/param.h>
24 #include <WINNT/c_debug.h>
29 #define THIS_HINST (GetModuleHandle (NULL))
32 #define WM_OUTSTRING (WM_USER + 0x99)
37 * VARIABLES __________________________________________________________________
43 int Debugstr::fRegistered
= 0;
44 int Debugstr::fInit
= 0;
45 HWND
Debugstr::hwnd
= 0;
51 char Debugstr::gdata
[ yMAX
][ xMAX
];
53 BOOL
Debugstr::fAngles
= FALSE
;
57 ushort
cxAvgWidth (void);
61 * ROUTINES ___________________________________________________________________
65 int AssertFn (int b
, char *expr
, int line
, char *name
)
73 wsprintf (szLine1
, "Assertion failed: \"%s\"", expr
);
74 wsprintf (szLine2
, "Line %u of module %s.", line
, name
);
77 debug
<< szLine1
<< "\n";
78 debug
<< szLine2
<< "\n";
81 MessageBox (NULL
, szLine1
, szLine2
, MB_ICONEXCLAMATION
);
87 * OPERATORS __________________________________________________________________
91 Debugstr
& Debugstr::operator<< (char *str
)
93 if (! strcmp (str
, ANGLES_ON
))
95 else if (! strcmp (str
, ANGLES_OFF
))
97 else if (! strcmp (str
, LASTERROR
))
101 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
|FORMAT_MESSAGE_FROM_SYSTEM
,
102 NULL
, GetLastError(),
103 MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
),
104 (LPTSTR
)&lp
, 0, NULL
);
106 (*this) << "#" << (LONG
)GetLastError();
107 (*this) << " (" << (char *)lp
<< ")";
113 Register(); // does nothing unless first time
114 Initialize(); // does nothing unless first time
116 char *strToSend
= (char *)Allocate(1+strlen(str
));
117 strcpy (strToSend
, str
);
119 PostMessage (Debugstr::hwnd
, WM_OUTSTRING
, 0, (LPARAM
)strToSend
);
124 Debugstr
& Debugstr::operator<< (void *addr
)
127 if (HIWORD(addr
) == 0x0000)
128 wsprintf (szTemp
, "0x%04X", (ushort
)LOWORD(PtrToLong(addr
)));
130 wsprintf (szTemp
, "0x%08lX", PtrToLong(addr
));
131 return (*this << szTemp
);
134 Debugstr
& Debugstr::operator<< (uchar ch
)
139 return (*this << szTemp
);
142 Debugstr
& Debugstr::operator<< (char ch
)
147 return (*this << szTemp
);
150 Debugstr
& Debugstr::operator<< (size_t l
)
153 _ltoa ((LONG
)l
, szTemp
, 10);
154 return (*this << szTemp
);
157 Debugstr
& Debugstr::operator<< (long l
)
160 _ltoa (l
, szTemp
, 10);
161 return (*this << szTemp
);
164 Debugstr
& Debugstr::operator<< (ushort s
)
167 _itoa (s
, szTemp
, 10);
168 return (*this << szTemp
);
171 Debugstr
& Debugstr::operator<< (short s
)
174 _itoa (s
, szTemp
, 10);
175 return (*this << szTemp
);
178 Debugstr
& Debugstr::operator<< (double f
)
180 char *psz
; // (may cross segments)
186 f
*= 180.0 / 3.1415926535897;
197 f
*= 1000000.0; // add 6 zeroes...
200 wsprintf (szTemp
, "%06ld", l
);
202 for (psz
= &szTemp
[ strlen(szTemp
)-1 ]; psz
>= szTemp
; psz
--)
211 *this << "." << szTemp
;
217 Debugstr
& Debugstr::operator<< (RECT r
)
219 *this << "{ x=" << (LONG
)r
.left
<< ".." << (LONG
)r
.right
;
220 *this << ", y=" << (LONG
)r
.top
<< ".." << (LONG
)r
.bottom
<< " }";
224 Debugstr
& Debugstr::operator<< (LPIDENT lpi
)
228 *this << "{ invalid ident }";
230 else if (lpi
->fIsCell())
232 TCHAR szCell
[ cchNAME
];
233 lpi
->GetCellName (szCell
);
234 *this << "{ cell " << szCell
<< " }";
236 else if (lpi
->fIsServer())
238 TCHAR szServer
[ cchNAME
];
239 lpi
->GetServerName (szServer
);
240 *this << "{ server " << szServer
<< " }";
242 else if (lpi
->fIsAggregate())
244 TCHAR szServer
[ cchNAME
];
245 lpi
->GetServerName (szServer
);
246 TCHAR szAggregate
[ cchNAME
];
247 lpi
->GetAggregateName (szAggregate
);
248 *this << "{ aggregate " << szServer
<< ":" << szAggregate
<< " }";
250 else if (lpi
->fIsFileset())
252 TCHAR szServer
[ cchNAME
];
253 lpi
->GetServerName (szServer
);
254 TCHAR szAggregate
[ cchNAME
];
255 lpi
->GetAggregateName (szAggregate
);
256 TCHAR szFileset
[ cchNAME
];
257 lpi
->GetFilesetName (szFileset
);
258 *this << "{ fileset " << szFileset
<< " on " << szServer
<< ":" << szAggregate
<< " }";
260 else if (lpi
->fIsServer())
262 TCHAR szServer
[ cchNAME
];
263 lpi
->GetServerName (szServer
);
264 TCHAR szService
[ cchNAME
];
265 lpi
->GetServiceName (szService
);
266 *this << "{ service " << szServer
<< ":" << szService
<< " }";
273 * STATICS ____________________________________________________________________
277 Debugstr::Debugstr (void)
283 Debugstr::~Debugstr (void)
287 DeleteObject (hfNew
);
293 DeleteObject (brBack
);
299 #define szDebugCLASS "DebugClass"
301 void Debugstr::Register (void)
309 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
310 wc
.lpfnWndProc
= DebugWndProc
;
313 wc
.hInstance
= THIS_HINST
;
314 wc
.hIcon
= LoadIcon(NULL
, IDI_EXCLAMATION
);
315 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
316 wc
.hbrBackground
= CreateSolidBrush( GetSysColor( COLOR_BTNFACE
));
317 wc
.lpszMenuName
= NULL
;
318 wc
.lpszClassName
= szDebugCLASS
;
320 (void)RegisterClass(&wc
);
324 void Debugstr::Initialize (void)
333 w
= cxAvgWidth() * 58;
334 // w = cxAvgWidth() * 160;
335 h
= GetSystemMetrics (SM_CYSCREEN
);
336 x
= GetSystemMetrics (SM_CXSCREEN
) - w
;
342 WS_OVERLAPPEDWINDOW
| // Window style
344 x
, // Default horizontal position
345 y
+35, // Default vertical position
347 h
-70, // Default height
348 NULL
, // Overlapped windows have no parent
349 NULL
, // Use the window class menu
350 THIS_HINST
, // This instance owns this window
351 NULL
// Pointer not needed
358 * Make the window visible and update its client area.
362 for (y
= 0; y
< yMAX
; y
++)
371 ShowWindow (hWnd
, SW_SHOWNOACTIVATE
);
374 Debugstr::hwnd
= hWnd
;
378 /*** OutString - Translates "\n" 's, and calls Output to display text
380 * ENTRY: char *str - string to display
381 * BOOL fRecord - FALSE if inside WM_PAINT message
387 void Debugstr::OutString (char *str
, BOOL fRecord
)
398 Register(); // does nothing unless first time
399 Initialize(); // does nothing unless first time
404 OutputDebugString (str
);
406 if (Debugstr::hwnd
== NULL
)
409 if ((hdc
= GetDC (Debugstr::hwnd
)) == NULL
)
412 fg
= SetTextColor (hdc
, GetSysColor( COLOR_BTNTEXT
));
413 bk
= SetBkColor (hdc
, GetSysColor( COLOR_BTNFACE
));
417 brBack
= CreateSolidBrush (GetBkColor(hdc
));
422 memset (&lf
, 0, sizeof(lf
));
424 lf
.lfWeight
= FW_NORMAL
;
425 lf
.lfHeight
= -MulDiv (8, GetDeviceCaps(hdc
, LOGPIXELSY
), 72);
426 strcpy (lf
.lfFaceName
, "Arial");
428 hfNew
= CreateFontIndirect(&lf
);
431 hfOld
= (HFONT
)SelectObject(hdc
, hfNew
);
432 GetTextMetrics (hdc
, &tm
);
434 GetClientRect (Debugstr::hwnd
, &r
);
436 if (!strcmp (str
, "CLS"))
445 FillRect (hdc
, &r
, brBack
);
447 else for (psz
= str
; *psz
; )
449 if ((pch
= strchr(psz
, '\n')) == NULL
)
451 Output (hdc
, psz
, fRecord
);
456 Output (hdc
, psz
, fRecord
);
458 gy
+= (ushort
)tm
.tmHeight
;
465 if ((gy
+ tm
.tmHeight
) > (ushort
)r
.bottom
)
470 GetTextExtentPoint (hdc
, gdata
[gcY
], (int)strlen(gdata
[gcY
]), &siz
);
473 r2
.bottom
= gy
+ tm
.tmHeight
;
477 FillRect (hdc
, &r2
, brBack
);
483 nRefr
= max( nRefr
, gcY
);
490 GetTextExtentPoint (hdc
, gdata
[gcY
+1], (int)strlen(gdata
[gcY
+1]), &siz
);
492 r2
.top
= gy
+tm
.tmHeight
;
493 r2
.bottom
= gy
+tm
.tmHeight
+tm
.tmHeight
;
497 FillRect (hdc
, &r2
, brBack
);
503 SelectObject (hdc
, hfOld
);
504 SetTextColor (hdc
, fg
);
505 SetBkColor (hdc
, bk
);
506 ReleaseDC (Debugstr::hwnd
, hdc
);
510 void Debugstr::Output (HDC hdc
, char *psz
, BOOL fRec
)
514 TextOut (hdc
, gx
, gy
, psz
, (int)strlen(psz
));
517 strcat (gdata
[gcY
], psz
);
519 GetTextExtentPoint (hdc
, psz
, (int)strlen(psz
), &siz
);
521 gx
+= (ushort
)siz
.cx
;
522 gcX
+= (int)strlen(psz
);
527 /*** DebugWndProc - Main window callback
532 * MESSAGES: WM_COMMAND - application menu (About dialog box)
533 * WM_DESTROY - destroy window
537 LRESULT APIENTRY
Debugstr::DebugWndProc (HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
547 if (Debugstr::hwnd
!= 0)
549 CloseWindow (Debugstr::hwnd
);
550 Debugstr::hwnd
= 0; // Turn off debugging--no window!
556 char *str
= (char*)lParam
;
557 debug
.OutString (str
, TRUE
);
566 hdc
= BeginPaint (hWnd
, &ps
);
567 EndPaint (hWnd
, &ps
);
569 x
= gx
; y
= gy
; cX
= gcX
; cY
= gcY
;
576 for (gcY
= 0; gcY
< nRefr
; )
578 TCHAR szLine
[] = TEXT("\n");
579 debug
.OutString (gdata
[gcY
], FALSE
);
580 debug
.OutString (szLine
, FALSE
);
582 debug
.OutString (gdata
[gcY
], FALSE
);
584 gx
= x
; gy
= y
; gcX
= cX
; gcY
= cY
;
593 return (DefWindowProc(hWnd
, message
, wParam
, lParam
));
597 /*** cxAvgWidth - Returns the average width of the chars in Arial/8point.
607 ushort
cxAvgWidth (void)
609 HFONT hfnt
, hfntOld
= NULL
;
615 hdc
= GetDC( GetDesktopWindow() );
617 memset (&lf
, 0, sizeof(lf
));
618 lf
.lfHeight
= -MulDiv (8, GetDeviceCaps(hdc
, LOGPIXELSY
), 72);
619 strcpy (lf
.lfFaceName
, "Arial");
621 if ((hfnt
= CreateFontIndirect(&lf
)) != NULL
)
623 hfntOld
= (HFONT
)SelectObject(hdc
, hfnt
);
626 if (! GetTextMetrics (hdc
, &tm
))
631 SelectObject (hdc
, hfntOld
);
635 ReleaseDC (GetDesktopWindow(), hdc
);
637 return (ushort
)tm
.tmAveCharWidth
;
646 #define LONG_TYPE 0x0001
647 #define SHORT_TYPE 0x0002
648 #define INT_TYPE 0x0004
649 #define CHAR_TYPE 0x0008
650 #define STRING_TYPE 0x0010
651 #define FLOAT_TYPE 0x0020
652 #define COMMA_TYPE 0x0040
653 #define MSG_TYPE 0x0080
655 cdecl LogOut::LogOut (char *psz
, ...)
663 strcpy (pszFormat
, psz
);
666 for (pch
= psz
; *pch
; pch
++)
681 case 'F': n
|= LONG_TYPE
; break;
682 case 'l': n
|= LONG_TYPE
; break;
683 case 'h': n
|= SHORT_TYPE
; break;
684 case 'X': n
|= INT_TYPE
; break;
685 case 'x': n
|= INT_TYPE
; break;
686 case 'O': n
|= INT_TYPE
; break;
687 case 'o': n
|= INT_TYPE
; break;
688 case 'd': n
|= INT_TYPE
; break;
689 case 'u': n
|= INT_TYPE
; break;
690 case 'c': n
|= CHAR_TYPE
; break;
691 case 's': n
|= STRING_TYPE
; break;
692 default: fBreak
= TRUE
; break;
696 if (nArgs
== MAX_ARGS
)
699 aPtr
[nArgs
] = va_arg (arg
, char *);
708 LogOut::~LogOut (void)
722 for (pszFmt
= pszFormat
; *pszFmt
; pszFmt
++)
733 for (pszTmpFmt
= tmpfmt
; !fBreak
; )
735 *pszTmpFmt
++ = *pszFmt
;
742 case 'F': n
|= LONG_TYPE
; break; // (far)
743 case 'l': n
|= LONG_TYPE
; break;
744 case 'h': n
|= SHORT_TYPE
; break;
745 case 'X': n
|= INT_TYPE
; break;
746 case 'x': n
|= INT_TYPE
; break;
747 case 'O': n
|= INT_TYPE
; break;
748 case 'o': n
|= INT_TYPE
; break;
749 case 'd': n
|= INT_TYPE
; break;
750 case 'u': n
|= INT_TYPE
; break;
751 case 'c': n
|= CHAR_TYPE
; break;
752 case 's': n
|= STRING_TYPE
; break;
753 default: fBreak
= TRUE
; break;
765 wsprintf (pszOut
, tmpfmt
, (char far
*)pch
);
767 else if (n
& LONG_TYPE
)
768 wsprintf (pszOut
, tmpfmt
, *(long *)pch
);
769 else if (n
& SHORT_TYPE
)
770 wsprintf (pszOut
, tmpfmt
, *(short *)pch
);
771 else if (n
& INT_TYPE
)
772 wsprintf (pszOut
, tmpfmt
, *(int *)pch
);
773 else if (n
& CHAR_TYPE
)
774 wsprintf (pszOut
, tmpfmt
, (char)*(char *)pch
);
778 pszOut
= &pszOut
[ strlen(pszOut
) ];
786 debug
<< text
<< "\n";