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
11 #include <afs/param.h>
20 #include <WINNT/c_debug.h>
25 #define THIS_HINST (GetModuleHandle (NULL))
28 #define WM_OUTSTRING (WM_USER + 0x99)
33 * VARIABLES __________________________________________________________________
39 int Debugstr::fRegistered = 0;
40 int Debugstr::fInit = 0;
41 HWND Debugstr::hwnd = 0;
47 char Debugstr::gdata[ yMAX ][ xMAX ];
49 BOOL Debugstr::fAngles = FALSE;
53 ushort cxAvgWidth (void);
57 * ROUTINES ___________________________________________________________________
61 int AssertFn (int b, char *expr, int line, char *name)
69 wsprintf (szLine1, "Assertion failed: \"%s\"", expr);
70 wsprintf (szLine2, "Line %u of module %s.", line, name);
73 debug << szLine1 << "\n";
74 debug << szLine2 << "\n";
77 MessageBox (NULL, szLine1, szLine2, MB_ICONEXCLAMATION);
83 * OPERATORS __________________________________________________________________
87 Debugstr & Debugstr::operator<< (char *str)
89 if (! strcmp (str, ANGLES_ON))
91 else if (! strcmp (str, ANGLES_OFF))
93 else if (! strcmp (str, LASTERROR))
97 FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
99 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
100 (LPTSTR)&lp, 0, NULL);
102 (*this) << "#" << (LONG)GetLastError();
103 (*this) << " (" << (char *)lp << ")";
109 Register(); // does nothing unless first time
110 Initialize(); // does nothing unless first time
112 char *strToSend = (char *)Allocate(1+strlen(str));
113 strcpy (strToSend, str);
115 PostMessage (Debugstr::hwnd, WM_OUTSTRING, 0, (LPARAM)strToSend);
120 Debugstr & Debugstr::operator<< (void *addr)
123 if (HIWORD(addr) == 0x0000)
124 wsprintf (szTemp, "0x%04X", (ushort)LOWORD(addr));
126 wsprintf (szTemp, "0x%08lX", (LONG)addr);
127 return (*this << szTemp);
130 Debugstr & Debugstr::operator<< (uchar ch)
135 return (*this << szTemp);
138 Debugstr & Debugstr::operator<< (char ch)
143 return (*this << szTemp);
146 Debugstr & Debugstr::operator<< (size_t l)
149 _ltoa (l, szTemp, 10);
150 return (*this << szTemp);
153 Debugstr & Debugstr::operator<< (long l)
156 _ltoa (l, szTemp, 10);
157 return (*this << szTemp);
160 Debugstr & Debugstr::operator<< (ushort s)
163 _itoa (s, szTemp, 10);
164 return (*this << szTemp);
167 Debugstr & Debugstr::operator<< (short s)
170 _itoa (s, szTemp, 10);
171 return (*this << szTemp);
174 Debugstr & Debugstr::operator<< (double f)
176 char *psz; // (may cross segments)
182 f *= 180.0 / 3.1415926535897;
193 f *= 1000000.0; // add 6 zeroes...
196 wsprintf (szTemp, "%06ld", l);
198 for (psz = &szTemp[ strlen(szTemp)-1 ]; psz >= szTemp; psz--)
207 *this << "." << szTemp;
213 Debugstr & Debugstr::operator<< (RECT r)
215 *this << "{ x=" << (LONG)r.left << ".." << (LONG)r.right;
216 *this << ", y=" << (LONG)r.top << ".." << (LONG)r.bottom << " }";
220 Debugstr & Debugstr::operator<< (LPIDENT lpi)
224 *this << "{ invalid ident }";
226 else if (lpi->fIsCell())
228 TCHAR szCell[ cchNAME ];
229 lpi->GetCellName (szCell);
230 *this << "{ cell " << szCell << " }";
232 else if (lpi->fIsServer())
234 TCHAR szServer[ cchNAME ];
235 lpi->GetServerName (szServer);
236 *this << "{ server " << szServer << " }";
238 else if (lpi->fIsAggregate())
240 TCHAR szServer[ cchNAME ];
241 lpi->GetServerName (szServer);
242 TCHAR szAggregate[ cchNAME ];
243 lpi->GetAggregateName (szAggregate);
244 *this << "{ aggregate " << szServer << ":" << szAggregate << " }";
246 else if (lpi->fIsFileset())
248 TCHAR szServer[ cchNAME ];
249 lpi->GetServerName (szServer);
250 TCHAR szAggregate[ cchNAME ];
251 lpi->GetAggregateName (szAggregate);
252 TCHAR szFileset[ cchNAME ];
253 lpi->GetFilesetName (szFileset);
254 *this << "{ fileset " << szFileset << " on " << szServer << ":" << szAggregate << " }";
256 else if (lpi->fIsServer())
258 TCHAR szServer[ cchNAME ];
259 lpi->GetServerName (szServer);
260 TCHAR szService[ cchNAME ];
261 lpi->GetServiceName (szService);
262 *this << "{ service " << szServer << ":" << szService << " }";
269 * STATICS ____________________________________________________________________
273 Debugstr::Debugstr (void)
279 Debugstr::~Debugstr (void)
283 DeleteObject (hfNew);
289 DeleteObject (brBack);
295 #define szDebugCLASS "DebugClass"
297 void Debugstr::Register (void)
305 wc.style = CS_HREDRAW | CS_VREDRAW;
306 wc.lpfnWndProc = DebugWndProc;
309 wc.hInstance = THIS_HINST;
310 wc.hIcon = LoadIcon(NULL, IDI_EXCLAMATION);
311 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
312 wc.hbrBackground = CreateSolidBrush( GetSysColor( COLOR_BTNFACE ));
313 wc.lpszMenuName = NULL;
314 wc.lpszClassName = szDebugCLASS;
316 (void)RegisterClass(&wc);
320 void Debugstr::Initialize (void)
329 w = cxAvgWidth() * 58;
330 // w = cxAvgWidth() * 160;
331 h = GetSystemMetrics (SM_CYSCREEN);
332 x = GetSystemMetrics (SM_CXSCREEN) - w;
338 WS_OVERLAPPEDWINDOW | // Window style
340 x, // Default horizontal position
341 y +35, // Default vertical position
343 h -70, // Default height
344 NULL, // Overlapped windows have no parent
345 NULL, // Use the window class menu
346 THIS_HINST, // This instance owns this window
347 NULL // Pointer not needed
354 * Make the window visible and update its client area.
358 for (y = 0; y < yMAX; y++)
367 ShowWindow (hWnd, SW_SHOWNOACTIVATE);
370 Debugstr::hwnd = hWnd;
374 /*** OutString - Translates "\n" 's, and calls Output to display text
376 * ENTRY: char *str - string to display
377 * BOOL fRecord - FALSE if inside WM_PAINT message
383 void Debugstr::OutString (char *str, BOOL fRecord)
394 Register(); // does nothing unless first time
395 Initialize(); // does nothing unless first time
400 OutputDebugString (str);
402 if (Debugstr::hwnd == NULL)
405 if ((hdc = GetDC (Debugstr::hwnd)) == NULL)
408 fg = SetTextColor (hdc, GetSysColor( COLOR_BTNTEXT ));
409 bk = SetBkColor (hdc, GetSysColor( COLOR_BTNFACE ));
413 brBack = CreateSolidBrush (GetBkColor(hdc));
418 memset (&lf, 0, sizeof(lf));
420 lf.lfWeight = FW_NORMAL;
421 lf.lfHeight = -MulDiv (8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
422 strcpy (lf.lfFaceName, "Arial");
424 hfNew = CreateFontIndirect(&lf);
427 hfOld = (HFONT)SelectObject(hdc, hfNew);
428 GetTextMetrics (hdc, &tm);
430 GetClientRect (Debugstr::hwnd, &r);
432 if (!strcmp (str, "CLS"))
441 FillRect (hdc, &r, brBack);
443 else for (psz = str; *psz; )
445 if ((pch = strchr(psz, '\n')) == NULL)
447 Output (hdc, psz, fRecord);
452 Output (hdc, psz, fRecord);
454 gy += (ushort)tm.tmHeight;
461 if ((gy + tm.tmHeight) > (ushort)r.bottom)
466 GetTextExtentPoint (hdc, gdata[gcY], strlen(gdata[gcY]), &siz);
469 r2.bottom = gy + tm.tmHeight;
473 FillRect (hdc, &r2, brBack);
479 nRefr = max( nRefr, gcY );
486 GetTextExtentPoint (hdc, gdata[gcY+1], strlen(gdata[gcY+1]), &siz);
488 r2.top = gy +tm.tmHeight;
489 r2.bottom = gy +tm.tmHeight +tm.tmHeight;
493 FillRect (hdc, &r2, brBack);
499 SelectObject (hdc, hfOld);
500 SetTextColor (hdc, fg);
501 SetBkColor (hdc, bk);
502 ReleaseDC (Debugstr::hwnd, hdc);
506 void Debugstr::Output (HDC hdc, char *psz, BOOL fRec)
510 TextOut (hdc, gx, gy, psz, strlen(psz));
513 strcat (gdata[gcY], psz);
515 GetTextExtentPoint (hdc, psz, strlen(psz), &siz);
517 gx += (ushort)siz.cx;
523 /*** DebugWndProc - Main window callback
528 * MESSAGES: WM_COMMAND - application menu (About dialog box)
529 * WM_DESTROY - destroy window
533 LONG APIENTRY Debugstr::DebugWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
543 if (Debugstr::hwnd != 0)
545 CloseWindow (Debugstr::hwnd);
546 Debugstr::hwnd = 0; // Turn off debugging--no window!
552 char *str = (char*)lParam;
553 debug.OutString (str, TRUE);
562 hdc = BeginPaint (hWnd, &ps);
563 EndPaint (hWnd, &ps);
565 x = gx; y = gy; cX = gcX; cY = gcY;
572 for (gcY = 0; gcY < nRefr; )
574 TCHAR szLine[] = TEXT("\n");
575 debug.OutString (gdata[gcY], FALSE);
576 debug.OutString (szLine, FALSE);
578 debug.OutString (gdata[gcY], FALSE);
580 gx = x; gy = y; gcX = cX; gcY = cY;
589 return (DefWindowProc(hWnd, message, wParam, lParam));
593 /*** cxAvgWidth - Returns the average width of the chars in Arial/8point.
603 ushort cxAvgWidth (void)
605 HFONT hfnt, hfntOld = NULL;
611 hdc = GetDC( GetDesktopWindow() );
613 memset (&lf, 0, sizeof(lf));
614 lf.lfHeight = -MulDiv (8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
615 strcpy (lf.lfFaceName, "Arial");
617 if ((hfnt = CreateFontIndirect(&lf)) != NULL)
619 hfntOld = (HFONT)SelectObject(hdc, hfnt);
622 if (! GetTextMetrics (hdc, &tm))
627 SelectObject (hdc, hfntOld);
631 ReleaseDC (GetDesktopWindow(), hdc);
633 return (ushort)tm.tmAveCharWidth;
642 #define LONG_TYPE 0x0001
643 #define SHORT_TYPE 0x0002
644 #define INT_TYPE 0x0004
645 #define CHAR_TYPE 0x0008
646 #define STRING_TYPE 0x0010
647 #define FLOAT_TYPE 0x0020
648 #define COMMA_TYPE 0x0040
649 #define MSG_TYPE 0x0080
651 cdecl LogOut::LogOut (char *psz, ...)
659 strcpy (pszFormat, psz);
662 for (pch = psz; *pch; pch++)
677 case 'F': n |= LONG_TYPE; break;
678 case 'l': n |= LONG_TYPE; break;
679 case 'h': n |= SHORT_TYPE; break;
680 case 'X': n |= INT_TYPE; break;
681 case 'x': n |= INT_TYPE; break;
682 case 'O': n |= INT_TYPE; break;
683 case 'o': n |= INT_TYPE; break;
684 case 'd': n |= INT_TYPE; break;
685 case 'u': n |= INT_TYPE; break;
686 case 'c': n |= CHAR_TYPE; break;
687 case 's': n |= STRING_TYPE; break;
688 default: fBreak = TRUE; break;
692 if (nArgs == MAX_ARGS)
695 aPtr[nArgs] = va_arg (arg, char *);
704 LogOut::~LogOut (void)
718 for (pszFmt = pszFormat; *pszFmt; pszFmt++)
729 for (pszTmpFmt = tmpfmt; !fBreak; )
731 *pszTmpFmt++ = *pszFmt;
738 case 'F': n |= LONG_TYPE; break; // (far)
739 case 'l': n |= LONG_TYPE; break;
740 case 'h': n |= SHORT_TYPE; break;
741 case 'X': n |= INT_TYPE; break;
742 case 'x': n |= INT_TYPE; break;
743 case 'O': n |= INT_TYPE; break;
744 case 'o': n |= INT_TYPE; break;
745 case 'd': n |= INT_TYPE; break;
746 case 'u': n |= INT_TYPE; break;
747 case 'c': n |= CHAR_TYPE; break;
748 case 's': n |= STRING_TYPE; break;
749 default: fBreak = TRUE; break;
761 wsprintf (pszOut, tmpfmt, (char far *)pch);
763 else if (n & LONG_TYPE)
764 wsprintf (pszOut, tmpfmt, *(long *)pch);
765 else if (n & SHORT_TYPE)
766 wsprintf (pszOut, tmpfmt, *(short *)pch);
767 else if (n & INT_TYPE)
768 wsprintf (pszOut, tmpfmt, *(int *)pch);
769 else if (n & CHAR_TYPE)
770 wsprintf (pszOut, tmpfmt, (char)*(char *)pch);
774 pszOut = &pszOut[ strlen(pszOut) ];
782 debug << text << "\n";